• Keine Ergebnisse gefunden

Prof. Dr. A. Reuter Friedemann Schwenkreis. Beginn am: Beendet am:

N/A
N/A
Protected

Academic year: 2022

Aktie "Prof. Dr. A. Reuter Friedemann Schwenkreis. Beginn am: Beendet am:"

Copied!
85
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Beginn am: 06.05.1996 Beendet am: 05.11.1996

CR-Klassifikation: C.2.4, D.4.5, H.1.2, H.2.4, H.4.1, H.5.2

Studienarbeit-Nr. 1560

Ein Agent als

Informationsschnittstelle für einen elektronischen

Eingangskorb

Michael Steinmetz

Universität Stuttgart Fakultät für Informatik

Institut für Parallele und Verteilte Höchstleistungsrechner (IPVR) Breitwiesenstraße 20-22

70567 Stuttgart

(2)

Inhaltsverzeichnis

Inhaltsverzeichnis ... 1

Abbildungsverzeichnis ... 4

1. Einleitung... 5

1.1 Einführung und Aufgabenstellung... 5

1.2 Übersicht über die Ausarbeitung... 5

2. APRICOTS ... 6

2.1 ConTracts... 6

2.2 APRICOTS ... 7

2.2.1 ConTract Engine und Engine Factory... 7

2.2.2 Context Manager ... 7

2.2.3 Step Server ... 8

2.2.4 Resource Manager ... 8

2.2.5 Storage Agent ... 9

2.2.6 Benutzeragent (User Agent)... 9

2.2.7 Monitoring Interface ... 9

2.2.8 Tasklist Interface... 9

2.2.9 System Administration Interface ... 10

2.2.10 Programming Interface... 10

2.3 Kommunikation in APRICOTS: CORBA... 10

2.4 Object Transaction Service... 11

2.4.1 Verwendung in APRICOTS ... 12

2.5 Naming Service... 12

2.6 Entwicklungsstand von APRICOTS... 14

3. Der Benutzeragent... 15

3.1 Aufgabenstellung ... 15

3.2 Struktur des Benutzeragenten ... 15

3.3 Threads innerhalb des Benutzeragenten ... 17

4. Benutzeragent und Benutzer... 19

4.1 Kommunikation mit dem Tasklist Interface ... 19

4.2 Behandlung des Benutzers ... 21

4.2.1 Rollback nach der Bearbeitung ... 22

4.2.1.1 Der Benutzer als gewöhnlicher Stepserver ... 23

4.2.1.1 Sonderbehandlung des Benutzers... 24

4.2.2 Rollback während der Bearbeitung ... 27

4.2.3 Rollback vor der Bearbeitung ... 28

4.2.4 Commit... 30

(3)

4.3 Optionen des Benutzers ... 31

4.3.1 Zurückweisen einer Aufgabe ... 31

4.3.2 Erfragen früherer Bearbeiter... 32

4.4 Verwendung von Prioritäten ... 33

5. Benutzeragent und ConTract Engine ... 34

5.1 Synchrone und asynchrone Kommunikation ... 34

5.2 Übermittlung der Aufgaben und der Ergebnisse... 36

5.3 Bestandteile eines Auftrages... 37

5.4 Aufträge ohne Rückgabewerte ... 38

5.5 Direkte und indirekte Kommunikation... 40

5.5.1 Indirekte Kommunikation... 40

5.5.2 Direkte Kommunikation ... 42

5.6 Nicht-transaktionale Aufträge ... 43

6. Fehlertoleranz ... 45

6.1 Persistente Speicherung ... 45

6.2 Ausfall von APRICOTS-Komponenten ... 46

6.2.1 OTS nicht verfügbar... 46

6.2.2 Storage Agent nicht verfügbar... 47

6.2.3 ConTract Engine nicht verfügbar... 47

6.2.4 Tasklist Interface nicht verfügbar... 48

7. Verwaltung des Benutzeragenten ... 49

7.1 Eintragen eines Benutzers ... 49

7.2 Überwachung des Benutzeragenten... 49

8. Implementierung und interne Abläufe ... 51

8.1 Interne Struktur ... 51

8.2 Bearbeitung einer Aufgabe ... 52

8.2.1 Eintreffen der Aufgabe ... 52

8.2.2 Übermittlung an die Oberfläche ... 54

8.2.3 Zurückweisen der Aufgabe... 55

8.2.4 Abfrage der bisherigen Bearbeiter... 56

8.2.5 Rückgabe einer teilweise bearbeiteten Aufgabe... 56

8.2.6 Rückgabe einer vollständig bearbeiteten Aufgabe ... 57

8.2.7 Erfolgreiches Beenden einer Transaktion ... 58

8.2.8 Löschen der Aufgabe durch den Benutzer ... 59

8.2.9 Abbruch der Transaktion... 59

9. Zusammenfassung und Ausblick ... 61

9.1 Zusammenfassung... 61

9.2 Verbesserungen und Erweiterungen ... 61

9.2.1 Sicherheitsaspekte ... 61

9.2.2 Umgang mit dem Benutzer ... 62

(4)

Anhang... 63

A. Aufruf des Benutzeragenten... 63

B. Zustände von Aufgaben... 64

C. Schnittstellen des Benutzeragenten... 65

C.1 Grundlegende Definitionen: basedef.idl... 65

C.2 Schnittstelle zur Oberfläche: tasklistinterface.idl ... 67

C.3 Schnittstellen zur ConTract Engine... 69

C.3.1 Die Aufgaben werden geliefert: stepserver.idl und useragent.idl ... 69

C.3.2 Das Ergebnis wird zurückgegeben: ct_engine.idl... 70

C.4 Schnittstelle zum System Administration Interface: useragent.idl ... 70

C.5 Schnittstelle zum Storage Agent: storageagent.idl... 71

C.6 Schnittstelle zum Object Transaction Service: ots.idl ... 76

D. Quellcode-Dateien des Benutzeragenten... 77

E. Test des Benutzeragenten ... 79

F. Literatur ... 80

(5)

Abbildungsverzeichnis

Abbildung 1: Ein Skript, das aus vier Steps besteht, von denen zwei parallel bearbeitet werden7

Abbildung 2: Die Komponenten des APRICOTS-Systems ... 8

Abbildung 3: Modell des Object Request Broker... 10

Abbildung 4: Verwendung von OTS ... 11

Abbildung 5: Die Namenshierarchie im APRICOTS-System ... 13

Abbildung 6: Der Benutzeragent gliedert sich in einen Monitoring- und einen Tasklist-Teil. .. 16

Abbildung 7: Der Tasklist-Teil des Benutzeragenten mit mehreren Threads... 17

Abbildung 8: Die Oberfläche als Client, der Benutzeragent als Server ... 19

Abbildung 9: Die Oberfläche als Server, der Benutzeragent als Client ... 20

Abbildung 10: Verwendung von Callbacks... 20

Abbildung 11: Behandlung einer realen Aktion... 22

Abbildung 12: Zurücksetzen einer Transaktion nach der Bearbeitung durch den Benutzer ... 23

Abbildung 13: Zurücksetzen einer Transaktion während der Bearbeitung durch den Benutzer27 Abbildung 14: Zurücksetzen einer Transaktion vor der Bearbeitung (Fall 1) ... 28

Abbildung 15: Zurücksetzen einer Transaktion vor der Bearbeitung (Fall 2) ... 29

Abbildung 16: Erfolgreicher Abschluß einer Transaktion... 30

Abbildung 17: Der Benutzer weist die Bearbeitung einer Aufgabe zurück ... 31

Abbildung 18: Der Benutzer erfragt die früheren Bearbeiter eines Dokuments... 32

Abbildung 19: Synchroner Aufruf ... 34

Abbildung 20: Asynchroner Aufruf ... 35

Abbildung 21: Ein asynchroner Aufruf wird durch zwei synchrone Aufrufe simuliert ... 36

Abbildung 22: Verschicken des Dateiinhaltes ... 37

Abbildung 23: Verschicken von Zeigern auf den Dateiinhalt... 38

Abbildung 24: Rückmeldung an die ConTract Engine nach der Bearbeitung... 38

Abbildung 25: Rückmeldung an die ConTract Engine vor der Bearbeitung... 39

Abbildung 26: Verwendung von Stubs mit direkter Antwort ... 41

Abbildung 27: Verwendung von Stubs mit indirekter Antwort ... 42

Abbildung 28: Direkte Kommunikation zwischen Benutzeragent und ConTract Engine... 43

Abbildung 29: Die Bedeutung des Storage Agent... 45

Abbildung 30: Die mit dem Benutzeragenten interagierenden Komponenten von APRICOTS46 Abbildung 31: Der Benutzeragent in der Namenshierarchie von APRICOTS... 49

Abbildung 32: Die interne Struktur des Tasklist-Teils des Benutzeragenten... 51

Abbildung 33: Eintreffen der Aufgabe beim Benutzeragenten ... 53

Abbildung 34: Übermittlung der Aufgabe an die Oberfläche ... 55

Abbildung 35: Zurückweisen einer Aufgabe durch den Benutzer ... 56

Abbildung 36: Rückgabe einer teilweise bearbeiteten Aufgabe durch den Benutzer ... 57

Abbildung 37: Rückgabe einer vollständig bearbeiteten Aufgabe durch den Benutzer ... 57

Abbildung 38: Eine Transaktion wird erfolgreich beendet... 58

Abbildung 39: Der Benutzer kann eine erfolgreich beendete Aufgabe löschen ... 59

Abbildung 40: Eine Transaktion wird abgebrochen ... 60

Abbildung 41: Möglichkeiten der Verschlüsselung ... 62

(6)

1. Einleitung

1.1 Einführung und Aufgabenstellung

Die Nachbildung langlebiger Abläufe, sogenannter Workflows, aus dem realen Leben auf ei- nem Rechnersystem hat zur Folge, daß ein an diesem Ablauf beteiligter menschlicher Bearbei- ter theoretisch wie jede beliebige automatische Komponente rund um die Uhr zur Abarbeitung der bei ihm eintreffenden Aufträge bereitstehen müßte.

Aus diesem Grunde bietet es sich an, das Prinzip einer Mailbox anzuwenden: es wird eine Komponente benötigt, die in Abwesenheit des Benutzers alle für ihn anfallenden Aufgaben annimmt und auf Wunsch an ihn weiterleitet. Sobald der Benutzer einen Auftrag abgearbeitet hat, soll diese Komponente die Ergebnisse wieder an das übrige System zurückschicken.

Diese Komponente - ein Benutzeragent - steht im Mittelpunkt der vorliegenden Arbeit. Er ist Teil eines transaktionsorientierten Systems, muß also dafür sorgen, daß auch im Fehlerfall keine der an ihn übermittelten Informationen verloren gehen. Von besonderem Interesse ist die Interaktion mit dem Benutzer, der zwar einerseits an Transaktionen teilnimmt, andererseits jedoch davon nichts weiß und davor geschützt werden sollte, daß etwa im Falle eines Transak- tionsabbruches das von ihm mühsam Erarbeitete vom System weggeworfen wird.

1.2 Übersicht über die Ausarbeitung

In Kapitel 2 wird zunächst ein Überblick über das für die Abarbeitung langlebiger Abläufe konzipierte APRICOTS-System gegeben, wovon der Benutzeragent, der in Kapitel 3 einge- hender behandelt wird, ein Teil ist.

Kapitel 4 befaßt sich mit dem Verhältnis zwischen dem Benutzer und seinem Benutzeragenten, während im fünften Kapitel gezeigt wird, wie sich der Agent dem System gegenüber verhält.

Kapitel 6 beschäftigt sich mit dem Thema Fehlertoleranz und Kapitel 7 legt dar, wie der Be- nutzeragent verwaltet wird.

Abschließend wird in Kapitel 8 auf die Implementierung des Benutzeragenten näher eingegan- gen und in Kapitel 9 erfolgt ein Resümee der Arbeit.

Im Anhang finden sich technische Details des Benutzeragenten, wie zum Beispiel die Schnitt- stellen zu den anderen Komponenten des Systems.

(7)

2. APRICOTS

2.1 ConTracts

In der Praxis der Datenverarbeitung sind heute sogenannte ACID-Transaktionen weit verbrei- tet. Diese Transaktionen besitzen folgende Eigenschaften [GrRe91]:

• Atomicity (Atomizität):

Ein Zustandsübergang ist atomar, wenn es für den Beobachter so aussieht, als ob das Verlassen des Ausgangszustandes mit dem Erreichen des Endzustandes zeitlich zu- sammenfällt, das heißt, wenn es keine nach außen hin sichtbaren Zwischenzustände gibt.

• Consistency (Konsistenz):

Eine Transaktion geht von einem Zustand, in dem sämtliche Konsistenzbedingungen erfüllt sind, wieder in einen konsistenten Zustand über.

• Isolation:

Isolation bedeutet, daß sich ein Programm unter dem Schutz einer Transaktion so ver- hält, als ob keine weiteren Prozesse parallel dazu laufen würden; und zwar auch dann, wenn dies in Wirklichkeit der Fall ist.

• Durability (Dauerhaftigkeit):

Das Ergebnis einer Transaktion darf nach deren erfolgreichem Abschluß nicht mehr verloren gehen, sondern muß im Fehlerfall wieder rekonstruiert werden.

ACID-Transaktionen in der beschriebenen Form sind jedoch nur für kurze Transaktionen ge- eignet, da die Realisierung von Atomizität, Konsistenz, Isolation und Dauerhaftigkeit bei län- ger andauernden „Transaktionen“, wie beispielsweise Workflows, bisher unüberwindliche Schwierigkeiten bereitet.

Ein Ansatz zur Lösung dieses Problems stellen ConTracts (Controled Activities Controled Transaction Compound) dar. Ein ConTract besteht aus einer Beschreibung von Steps sowie einem Skript.

Ein Step stellt ein sequentielles Programm dar, das unter dem Schutz einer ACID-Transaktion abläuft. Im Skript wird dagegen der Kontrollfluß definiert, beispielsweise die Reihenfolge der auszuführenden Steps oder welche Steps parallel zu anderen abgearbeitet werden müssen. Zu- sätzlich enthält das Skript Angaben über Ein- und Ausgabedaten der einzelnen Steps.

(8)

Step Skript

Abbildung 1: Ein Skript, das aus vier Steps besteht, von denen zwei parallel bearbeitet werden Da nicht das gesamte Skript, sondern nur die einzelnen Steps unter Transaktionsschutz stehen, müssen im Fehlerfall für erfolgreich beendete Steps Kompensations-Steps ausgeführt werden.

Die Information, welcher Step zur Kompensation eines anderen Step dient, ist ebenfalls im Skript enthalten.

Diese Thematik wird in [WaeRe91], [ReSweWa] sowie in [ReSwe95] ausführlich behandelt.

2.2 APRICOTS

APRICOTS (A Prototype Implementation of a ConTract System) stellt die Realisierung eines Workflow-Systems auf der Basis von ConTracts dar, das zur Zeit am Institut für Parallele und Verteilte Höchstleistungsrechner der Fakultät Informatik an der Universität Stuttgart entwik- kelt wird [Schw93] [Schw95].

2.2.1 ConTract Engine und Engine Factory

Die ConTract Engine [Seif96] ist die wohl wichtigste Komponente in APRICOTS. Für jedes Skript, das abgearbeitet werden soll, wird von der Engine Factory eine ConTract Engine gene- riert. Deren Aufgabe ist die zuverlässige Abarbeitung des Skripts. Insbesondere muß sie die für die jeweiligen Steps zuständigen Stepserver aufrufen und im Fehlerfall dafür sogen, daß die benötigten Kompensationssteps ausgeführt werden.

2.2.2 Context Manager

Die bei der Abarbeitung eines Skriptes verwendeten Variablen sowie die Ein- und Ausgabepa- rameter der einzelnen Steps stellen den Kontext des ConTracts dar. Dieser Kontext wird vom Context Manager verwaltet, der dabei auch für die persistente Speicherung, die vor allem im Fehlerfall für die Recovery von Bedeutung ist, sorgt.

(9)

Resource Manager

Step Server

Context Manager

Storage Agent

ConTract Engine

Engine Factory generiert

Monitoring Interface

Tasklist Interface

Sysadmin Interface

Programming Interface

Monitoring Tasklist Benutzeragent

OTS

Abbildung 2: Die Komponenten des APRICOTS-Systems

2.2.3 Step Server

Zur Ausführung der einzelnen im Skript enthaltenen Steps stehen der jeweiligen ConTract En- gine verschiedene aufgabenspezifische Stepserver zur Verfügung. Diesen übermittelt sie die zu erledigende Aufgabe und bekommt das Ergebnis zurückgeliefert. In der Regel wird dazu ein synchroner Aufruf verwendet, das heißt die ConTract Engine wartet, bis der Stepserver mit der Bearbeitung zu Ende ist. Warum dieses Vorgehen im Falle des Benutzeragenten nicht prakti- kabel ist, wird weiter unten diskutiert.

2.2.4 Resource Manager

Zur Bearbeitung des erhaltenen Auftrags können die Step Server wiederum auf sogenannte Resource Manager zurückgreifen. Beispielsweise wird eine Datenbank von einem Resource Manager verwaltet, über den ein Step Server auf die benötigten Daten zugreifen kann.

(10)

2.2.5 Storage Agent

Der Storage Agent wird von den anderen Komponenten des APRICOTS-Systems für die per- sistente Speicherung von Daten verwendet. Eine Ausnahme hiervon bilden die Benutzerober- flächen - das Tasklist Interface und das Monitoring Interface -, deren einziger Kontakt zum System über die Benutzeragenten erfolgt, die dann die Kommunikation mit dem Storage Agent übernehmen.

2.2.6 Benutzeragent (User Agent)

Der Benutzeragent (oder User Agent) repräsentiert einerseits genau einen Benutzer im System, andererseits bildet er auch die einzige Schnittstelle der Benutzungsoberflächen zum System, repräsentiert also auch das System gegenüber dem Benutzer. Der Benutzeragent gliedert sich in zwei Teile:

Der Monitoring-Teil, der mit dem Monitoring Interface kommuniziert, ist für die Übermittlung von Steuerbefehlen des Benutzers an die jeweiligen ConTract Engine eines ConTracts und für entsprechende Rückmeldungen verantwortlich.

Der Tasklist-Teil, den diese Arbeit zum Inhalt hat, ist aus der Sicht der ConTract Engine nichts anderes als ein interaktiver Stepserver. Folglich erhält der Agent die während der Abarbeitung eines Skriptes für seinen Benutzer anfallenden Aufgaben.

Eine genauere Beschreibung dieses Teils des Benutzeragenten erfolgt in den nächsten Kapiteln.

Wenn in diesen Ausführungen vom Benutzeragenten die Rede ist, dann bezieht sich dieser Begriff zumeist nur auf den Tasklist-Teil. Entsprechend werden auch nur die Interaktionen mit dem Benutzer betrachtet, die über das Tasklist Interface ablaufen. Der Monitoring-Teil des Be- nutzeragenten wird parallel zu dieser Arbeit entwickelt, und eine detaillierte Beschreibung dürfte sich in der zugehörigen Ausarbeitung finden [Ru96].

2.2.7 Monitoring Interface

Das Monitoring Interface bietet dem Benutzer die Möglichkeit, ConTracts zu starten, sie an- zuhalten und weiterlaufen zu lassen, sie abzubrechen, ihren Status abzufragen und dergleichen.

Diese Benutzeraktionen erreichen die zuständige ConTract Engine über den Monitoring-Teil des Benutzeragenten.

2.2.8 Tasklist Interface

Dieses Interface stellt einen elektronischen Eingangskorb des Benutzers dar. Es holt sich die Aufgaben, die der Benutzer erledigen soll, vom Tasklist-Teil des Agenten, der sie wiederum von der ConTract Engine erhalten hat, und stellt sie am Bildschirm dar. Der Benutzer kann nun eine Aufgabe zur Bearbeitung auswählen, woraufhin das Tasklist-Interface die hierfür benötig- ten Applikationen startet. Die Ergebnisse der Bearbeitung werden schließlich wieder an den Benutzeragenten geschickt, der sie an die ConTract Engine weiterleitet, von der die Aufgabe kam.

(11)

2.2.9 System Administration Interface

Das System Administration Interface (Sysadmin Interface) überwacht und verwaltet die übri- gen Komponenten des Systems. Es ist beispielsweise dafür zuständig, im Falle eines Absturzes einer solchen Komponente die erforderlichen Gegenmaßnahmen einzuleiten und eine entspre- chende Meldung an den Administrator zu senden. Außerdem bietet dieses Interface die Mög- lichkeit, neue Komponenten ins System einzubinden; etwa einen Agenten für einen neu hinzu- gekommenen Benutzer anzulegen.

2.2.10 Programming Interface

Das Programming Interface dient dazu, die weiter oben kurz beschriebenen Skripte einzuge- ben, die dann vom APRICOTS-System abgearbeitet werden können.

2.3 Kommunikation in APRICOTS: CORBA

Die Kommunikation zwischen den einzelnen Komponenten des APRICOTS-Systems erfolgt mittels einer Implementierung der von der Object Management Group (OMG) erarbeiteten Common Object Request Broker Architecture (CORBA) [OMG93].

Reply Request Request Reply

Client Server

Object Request Broker

Abbildung 3: Modell des Object Request Broker

Die Dienste, die ein Server anbietet, werden in der durch die OMG entwickelten Interface De- finition Language (IDL) beschrieben. Diese Beschreibung wird im Interface Repository abge- legt. Mit Hilfe eines IDL-Compilers werden Stubs erzeugt, die in den Client- beziehungsweise den Servercode eingebunden werden und die die Komplexität der Kommunikation über den Object Request Broker vor den Anwendungen verbergen.

Ein Client, der einen bestimmten Dienst benötigt, wendet sich über den vom IDL-Compiler erzeugte Client-Stub mit seiner Anfrage an den Object Request Broker (ORB), der nun im In- terface Repository nach einem geeigneten Server sucht und die Anfrage an diesen beziehungs- weise an dessen Server-Stub weiterleitet.

Die Gründe, die für die Verwendung von CORBA in der Implementierung von APRICOTS

(12)

• Die Gliederung des APRICOTS-Systems in verschiedene Agenten und Oberflächen läßt sich besonders gut mit Hilfe eines objektorientierten Ansatzes realisieren. CORBA ist ein solcher objektorientierter Kommunikationsansatz.

• CORBA ermöglicht Interoperabilität: Eine Kommunikation zwischen zwei Komponenten mit Hilfe von CORBA ist auch dann möglich, wenn für deren Implementierung verschiedene Programmiersprachen verwendet werden. Es muß jedoch eine Abbildung von der jeweiligen Programmiersprache auf IDL definiert sein. Beispielsweise ist dies für C++ und Java der Fall. Dadurch wird es erst möglich, zwischen dem in C++ geschriebenen Benutzeragenten und den in Java realisierten Benutzungsoberflächen - dem Tasklist-Interface sowie dem Monitoring Interface - Informationen auszutauschen.

Die im APRICOTS-Projekt verwendete Implementierung von CORBA mit dem Namen Orbix stammt von der Firma IONA Technologies, die auch Mitglied in der OMG ist.

2.4 Object Transaction Service

Jeder Step eines ConTract soll unter dem Schutz einer ACID-Transaktion ablaufen. Um dies zu erreichen, wird bei der Entwicklung von APRICOTS der auf CORBA basierenden Object Transaction Service (OTS) der OMG [OTS94] verwendet.

Teilnahme an der Beendi- gung der Transaktion Resource

registrieren Transaktionen

starten oder beenden

verteilte Client-Server-Anwendung

Transaktionale Operation Transactional

Client

Recoverable Server

Transaction Service Transaktions-

Kontext Resource

Abbildung 4: Verwendung von OTS

Ein Transactional Client ist ein beliebiges Programm, das im Verlauf einer Transaktion Ope- rationen auf Transactional Objects ausführt. Ein Transactional Object ist hierbei ein Objekt, dessen Verhalten dadurch beeinflußt wird, daß es während einer Transaktion aufgerufen wird.

Das Programm, das eine Transaktion beginnt, wird mit Transaction Originator bezeichnet.

(13)

Ein Spezialfall eines Transactional Object stellt ein Recoverable Object dar, das persistente Daten enthält, die durch die Transaktion verändert werden. Aus diesem Grunde muß dieses Objekt am Commit-Protokoll der Transaktion teilnehmen, um zu erfahren, ob es seine Daten ändern soll (Commit-Fall) oder nicht (Abort-Fall). Mit dem Begriff Recoverable Server schließlich bezeichnet man einen Server, der ein oder mehrere Recoverable Objects enthält.

Um nun am Commit-Protokoll teilnehmen zu können, muß ein Recoverable Server dem Trans- action Service seinen Teilnahmewunsch mitteilen. Zu diesem Zweck registriert er beim Trans- action Service eine Resource; dies ist ein Objekt, dessen Schnittstelle Methoden anbietet, die der Transaction Service ansprechen kann, wenn er mit dem Recoverable Server das Commit- Protokoll ausführt. Außerdem bietet eine Resource die Möglichkeit, nach dem Absturz und Wiederanlauf eines Recoverable Servers beim Transaction Service den aktuellen Zustand der Transaktion zu erfragen (siehe die Schnittstellen des Benutzeragenten im Anhang).

Der Transaction Service beruht auf dem Prinzip des Presumed Abort. Dies bedeutet, daß das System von einem Abbruch der Transaktion ausgeht, wenn es feststellt, daß ein Programm, das eine Resource registriert hat, abgestürzt ist.

2.4.1 Verwendung in APRICOTS

In unserem Fall stellt die ConTract Engine, die ein Skript abarbeitet und für die einzelnen Steps Transaktionen startet, den Transaction Originator dar. Der Benutzeragent ist dann ein Reco- verable Server, da er sich den von der ConTract Engine erhaltenen Auftrag persistent merken und am Commit-Protokoll teilnehmen muß. Um vom Transaction Service eine Mitteilung zu erhalten, falls ein Rollback für einen bestimmten Auftrag erfolgt, die Bearbeitung durch den Benutzer also abgebrochen werden kann, muß der Benutzeragent für jeden Auftrag eine Re- source beim Transaction Service registrieren.

Leider stand den Entwicklern der verschiedenen APRICOTS-Komponenten die für Mitte die- ses Jahres angekündigte OTS-Implementierung der Firma IONA Technologies nicht zur Ver- fügung, so daß die Tests mit Hilfe einer selbstgeschriebenen OTS-Komponente durchgeführt wurden.

2.5 Naming Service

Die von der Object Management Group (OMG) erarbeiteten CORBAservices beinhalten unter anderem auch den Naming Service. Dieser ermöglicht es einem Server, sich unter einem belie- bigen Namen zu registrieren, der im Gegensatz zum bisherigen Ansatz unabhängig vom Schnittstellen-, Server- oder Hostnamen ist. Um ein Serverobjekt zu finden, muß der Aufrufer lediglich den Namen kennen, unter dem dieser Server registriert ist; der Naming Service liefert dann eine Referenz auf dieses Objekt.

Diese willkürliche Namensgebung erlaubt auch eine Strukturierung des Namensraums in der Form eines Baumes, wobei jede Hierarchiestufe durch einen Punkt abgetrennt wird. Um bei- spielsweise einen Benutzer einzutragen, könnte man den Namen Root.Users.TheUser

(14)

Bei der im APRICOTS-Projekt verwendeten Implementierung des Naming Service handelt es sich um den Orbix Naming Service der Firma IONA Technologies, von der auch das im APRICOTS-Projekt benutzte Orbix stammt. Hier ist der Naming Service als gewöhnlicher Orbix Server realisiert.

Root

APRICOTS ConTracts

CID1

CIID1

MonitorAgent

StorageAgent

ContextManagement

ConTractEngine

CIID2 ...

CID2 ...

Admin

StepServers

StepServer1 StepServer2 ...

UserAgents Staff

StorageAgent User1

MonitorAgent Service Tasklist

CallbackManager User2

...

StepServers

AutomatedServers StepServer1 StepServer2 ...

UserAgents Staff

User1 User2 ...

Abbildung 5: Die Namenshierarchie im APRICOTS-System

(15)

2.6 Entwicklungsstand von APRICOTS

Bedingt durch eine teilweise Neukonzeption des APRICOTS-Systems, beispielsweise der Verwendung von CORBA anstelle des früheren Kommunikationssystems, werden zur Zeit alle Komponenten, also auch die vorher schon vorhandenen, parallel zu dieser Studienarbeit im- plementiert.

(16)

3. Der Benutzeragent

3.1 Aufgabenstellung

Wie schon im letzten Kapitel kurz dargestellt, soll der Benutzeragent (User Agent) einen Be- nutzer gegenüber dem System repräsentieren. Es wäre zwar prinzipiell möglich, auf die Kom- ponente des Benutzeragenten zu verzichten und den Benutzer (beziehungsweise die Oberflä- che, mit der der Benutzer am Bildschirm arbeitet) direkt anzusprechen; allerdings wirft dieser Ansatz einige Probleme auf:

• Da ein Benutzer nicht ständig anwesend ist, etwa nachts oder an Wochenenden, können in dieser Zeit Aufträge (Tasks), die für diesen Benutzer bestimmt sind, nicht ausgeliefert wer- den. Es ist also eine Komponente notwendig, die sich in etwa mit einer Mailbox vergleichen läßt: Während der Abwesenheit des Benutzers werden die Aufträge durch diese Kompo- nente gesammelt und sind danach auf Wunsch des Benutzers abrufbar. Diese Funktionalität muß folglich durch den Benutzeragenten abgedeckt werden.

• Der Benutzeragent (User Agent) muß fehlertolerant sein: Hat er einen Auftrag (Task) von der ConTract Engine erhalten, so muß dieser an den Benutzer übermittelt werden, und zwar unabhängig davon, ob der Benutzeragent zwischen dem Empfang und der Weiterleitung der Aufgabe wegen eines System- oder Programmfehlers neu gestartet werden muß. Um diese Fehlertoleranz zu erreichen, nimmt der Benutzeragent die Dienste des Storage Agents in Anspruch, der für die persistente Speicherung der an ihn übermittelten Daten verantwortlich ist. Wird der Benutzeragent neu gestartet, ist er mit Hilfe dieser Daten in der Lage, eine Re- covery durchzuführen und seinen alten Zustand wiederherzustellen.

• Die Aufgaben, die der Benutzer zur Bearbeitung von der ConTract Engine erhält, laufen in der Regel unter dem Schutz einer Transaktion ab. Es ist daher notwendig, den Benutzer in diese Transaktion einzubinden. Dies ist jedoch nur möglich, wenn der Benutzeragent, als die den Benutzer repräsentierende Komponente, am Transaktions-Protokoll teilnimmt.

3.2 Struktur des Benutzeragenten

Wie schon im einführenden Kapitel kurz dargelegt, gliedert sich der Benutzeragent (User Agent) in zwei Teile: Zum einen in den Monitoring-Teil, der es dem Benutzer ermöglicht, Ein- fluß auf den Ablauf von ConTracts zu nehmen (der Benutzer kann ConTracts starten, anhalten, weiterlaufen lassen, abbrechen und ähnliches) und zum anderen in den Tasklist-Teil, der in die- ser Arbeit beschrieben wird.

(17)

Benutzeragent

Monitoring- Teil des Benutzer-

agenten Monitoring

Interface

Tasklist Interface

ConTract Manager ConTract

Manager ConTract

Engine

Tasklist- Teil des Benutzer-

agenten Schnittstellen-

Objekt Schnittstellen-

Objekt Schnittstellen-

Objekt

Dienst- Schnittstelle Schnittstelle

zum Monitoring Interface

Schnittstelle zum Tasklist

Interface

Abbildung 6: Der Benutzeragent gliedert sich in einen Monitoring- und einen Tasklist-Teil.

Auf der Seite des Monitoring-Teils des Benutzeragenten wird für jeden ConTract eine Instanz des Schnittstellenobjektes angelegt, das für die Übermittlung der Benutzerbefehle an die jewei- lige ConTract Engine und deren Meldungen an den Benutzer zuständig ist. Der Tasklist-Teil beschränkt sich auf nur ein Schnittstellenobjekt, das die durch den Benutzer zu erledigenden Aufgaben von allen ConTract Engines entgegennimmt.

Die beiden Teile des Benutzeragenten konzentrieren sich auf völlig unterschiedliche Dienste und sind deshalb weitgehend unabhängig voneinander. Einzig in der Initialisierungsphase beim Programmstart ergeben sich gemeinsam zu erledigende Aufgaben, wie etwa das Binden an den Storage Agent. Danach erfolgt zwischen den beiden Teilen keinerlei Interaktion mehr. Der Tasklist-Teil interessiert sich beispielsweise in keinster Weise dafür, welche ConTracts vom Benutzer gestartet wurden und in welchem Zustand sich diese befinden; der Monitoring-Teil zeigt sich hingegen von der Frage unberührt, welche Aufgaben der Benutzer zu bearbeiten hat.

Aus diesem Grunde bietet es sich an, den Tasklist-Teil und den Monitoring-Teil des Benutzer-

(18)

stellen. Die Vorteile dieses Ansatzes liegen in der größeren Sicherheit wegen der Trennung der Adreßräume. In der gegenwärtigen Implementierung ist es für jeden Teil möglich, auf den Speicherbereich des jeweils anderen zuzugreifen und dadurch einen Programmfehler zu verur- sachen. Auch falls aufgrund eines internen Fehlers ein Teil des Benutzeragenten abstürzt, zieht er den anderen mit ins Verderben, obwohl dieser eigentlich hätte weiterarbeiten können.

Der Grund, warum die beiden Komponenten des Benutzeragenten trotzdem in einem ausführ- baren Programm zusammengeführt werden, liegt in der Aufgabenstellung begründet, die eine Aufteilung nicht vorsieht. Für jeden Benutzer soll nur ein Agent zuständig sein.

3.3 Threads innerhalb des Benutzeragenten

Was geschieht nun, wenn die ConTract Engine und das Tasklist Interface gleichzeitig versu- chen, den Benutzeragenten (User Agent) anzusprechen? In diesem Fall ist es ohne die Verwen- dung mehrerer Threads nur möglich, eine der beiden Anfragen zu bearbeiten. Der andere Auf- ruf wird mit einer System Exception abgelehnt; im Falle von Threads lassen sich die Aufträge in einer Warteschlange halten.

Obwohl sowohl die Auslieferung neuer Aufgaben durch die ConTract Engine als auch die In- teraktion mit dem Tasklist Interface dadurch, daß es sich um die einen menschlichen Benutzer betreffende Kommunikation handelt, nur relativ selten stattfindet, ist eine solche Kollision doch möglich und sollte verhindert werden. Verschärft wird diese Problematik noch dadurch, daß sich nicht nur die Komponenten des Tasklist-Teils des Benutzeragenten, sondern auch die des Monitoring-Teils im selben ausführbaren Programm befinden und beim Eintreffen von Nach- richten um die Zuteilung des Prozessors konkurrieren.

Verarbeitung der zweiten Nachricht parallel zur ersten

weitere Nachricht, während die erste noch bearbeitet wird Verarbeitung

der Nachricht

Benutzeragent ConTract

Engine Schnittstelle zum ConTract Engine

Schnittstelle zur Tasklist Interface

Tasklist Interface

Nachricht an den Benutzeragenten

Zurückliefern des Ergebnisses

Zurückliefern des Ergebnisses

Abbildung 7: Der Tasklist-Teil des Benutzeragenten mit mehreren Threads

(19)

Aus diesem Grunde lassen die Implementierer des Benutzeragenten die jeweiligen Schnittstel- lenobjekte in verschiedenen Threads laufen. Der Nachteil einer Verwendung von Threads ist allerdings der erhöhte Aufwand für die Synchronisation des Zugriffs auf Datenstrukturen, auf die von verschiedenen Threads aus zugegriffen wird.

(20)

4. Benutzeragent und Benutzer

4.1 Kommunikation mit dem Tasklist Interface

Wie werden nun die von einer ConTract Engine an den Benutzeragenten (User Agent) ge- schickten Aufgaben an die Oberfläche, das Tasklist Interface, weitergeleitet? Hier bieten sich zwei prinzipielle Alternativen an:

Eine Möglichkeit besteht darin, daß die Oberfläche den Benutzeragenten aufruft, um eventuell vorhandene Aufgaben abzuholen. Das Tasklist Interface agiert hier als Client, während der Benutzeragent den Server darstellt. Dieses Verfahren wird Polling genannt. Die Nachteile bei diesem Vorgehen sind offensichtlich: Wenn der Benutzeragent eine Nachricht an die Oberflä- che hat, sei es nun eine neue Aufgabe oder eine Abbruchmeldung, muß er mit der Auslieferung warten, bis sich diese bei ihm meldet. Um diese Wartezeiten möglichst kurz zu halten ist es notwendig, daß die Oberfläche in kurzen Intervallen nachfragt. Das hat jedoch zur Folge, daß oft keine Nachricht für sie vorliegt; in diesem Fall hat sie das Netz und den Benutzeragenten völlig unnötigerweise belastet. Andererseits handelt es sich hier um Mitteilungen an einen menschlichen Benutzer; das heißt es geht nicht um Zeiträume von Sekunden oder gar Millise- kunden, sondern wir haben es hier mit Nachfragen im Abstand von Minuten zu tun. Diese - wenn auch unnötigen - Nachrichten im Minutenabstand dürften sowohl für das Netzwerk als auch für den angesprochenen Benutzeragenten zu verkraften sein.

Nachricht

Benutzer- agent

Tasklist Interface Liegt eine Nachricht vor?

Liegt eine Nachricht vor?

Liegt eine Nachricht vor?

Ja: Nachricht wird übermittelt

Abbildung 8: Die Oberfläche als Client, der Benutzeragent als Server

Die zweite Alternative wäre, daß der Benutzeragent aktiv die Oberfläche anspricht, wann im- mer er eine Nachricht irgendeiner Form für seinen Benutzer hat. In diesem Fall werden die oben erwähnten Nachteile vermieden: Erstens entsteht bei der Weiterleitung der erhaltenen Botschaft keine Verzögerung und zweitens werden das Netz und der Benutzeragent nur dann belastet, wenn es tatsächlich etwas Sinnvolles zu verschicken gibt. In diesem Fall ist das Task- list Interface der Server und der Benutzeragent übernimmt die Rolle des Client.

(21)

Benutzer- agent

Tasklist Interface

Nachricht

Weiterleiten der Nachricht

Abbildung 9: Die Oberfläche als Server, der Benutzeragent als Client

Es gibt nun noch eine Mischform der oben beschriebenen beiden Möglichkeiten, nämlich die Verwendung von Callbacks [SmiVin96]. Callbacks ermöglichen es dem Server nach einem Aufruf durch den Client, diesen im Gegenzug anzusprechen. Auf unsere Situation übertragen bedeutet dies, daß das Tasklist Interface als Client den Benutzeragenten, der den Server dar- stellt, aufruft und ihm bei diesem Aufruf eine Callback-Einsprungstelle mitteilt. Kommt eine Nachricht beim Benutzeragenten an, so benutzt er den Callback-Mechanismus, um das Tasklist Interface von dieser Tatsache in Kenntnis zu setzen. Dieses kann daraufhin die Botschaft abho- len. Auch bei dieser Variante der Kommunikation entsteht bei der Weiterleitung einer Nach- richt kein Verzug, und auch hier tritt keine unnötige Belastung des Netzes auf.

Benutzer- agent

Tasklist Interface Mitteilen der Callback-Einsprungstelle

Nachricht

Mitteilung, daß eine Nachricht vorliegt

Nachricht abholen

Abbildung 10: Verwendung von Callbacks

Für die Realisierung der Kommunikation zwischen dem Tasklist Interface und dem Benutzer- agenten bietet sich aus den oben beschriebenen Gründen die Verwendung der zweiten Alterna- tive - oder als Ausweichmöglichkeit die Callback-Variante - an. Die Oberfläche wird jedoch in Java implementiert, und bei der zur Verfügung stehenden Version 1.0 von Orbix for Java kann ein Javaprogramm nur als reiner Client realisiert werden. Auch Callbacks sind mit diesem Programmierwerkzeug nicht möglich. Der Hersteller IONA Technologies verspricht jedoch für die Version 2.0, diesen Mißstand zu beheben.

(22)

4.2 Behandlung des Benutzers

Ein großes Problem in einem transaktionsorientierten System wie APRICOTS ist der Umgang mit dem Benutzer. Die durch den Benutzer geleistet Arbeit ist ein Teil der Transaktion, die denjenigen Step enthält, der einen Aufruf des Benutzeragenten (User Agent) verlangt. Als Konsequenz aus diesem Sachverhalt wird der Benutzeragent behandelt wie jede andere an der betreffenden Transaktion teilnehmende Komponente. Er könnte nun die transaktionalen Mel- dungen, die er erhält, einfach an den Benutzer durchreichen; allerdings wäre dies ein wenig benutzerfreundliches Verhalten.

Jede Meldung, die der Benutzer zu Gesicht bekommt, entspricht in gewissem Umfang einer realen Aktion („real action“ in [GrRe91]), da sie auch dann Auswirkungen auf die Umwelt - beispielsweise das Verhalten des Benutzers - haben kann, wenn irgendwann eine „Undo-Mel- dung“ im Sinne von „Die vorherige Meldung ist nicht mehr gültig“ eintrifft.

Nehmen wir zum Beispiel an, eine Aufgabe trifft beim Benutzer ein. Dieser wird sie bearbeiten und das Ergebnis zurückschicken. Wenn währenddessen - oder auch nach Abschluß der Bear- beitung - ein Rollback für die Transaktion ausgeführt wird, zu der diese Aufgabe gehört, so bleibt zumindest das Wissen des Benutzers, eine bestimmte Aufgabe abgearbeitet zu haben, über das Ende der Transaktion hinaus bestehen. Unternimmt das System jetzt einen zweiten Anlauf und versucht, die Transaktion nochmals auszuführen, so wird der Benutzer mit Erstau- nen oder Verärgerung zur Kenntnis nehmen, daß er eine Aufgabe nochmals erhält, von der er genau weiß, daß er sie schon erfolgreich abgearbeitet hat.

Die Bearbeitung einer Aufgabe durch einen menschlichen Benutzer ist also auch unabhängig von der unterschiedlichen Leistungsfähigkeit etwa zu unterschiedlichen Tageszeiten nicht idempotent.

Die in [GrRe91] vorgeschlagene Lösung für die Einbindung einer realen Aktion in eine Trans- aktion besteht darin, diese erst auszuführen, wenn alle übrigen Aktionen einen Zustand erreicht haben, von dem aus sie nicht mehr zurücksetzen werden. Konkret bedeutet dies, daß der Auf- ruf an den Benutzer erst am Ende der Transaktion erfolgt, wenn alle übrigen teilnehmenden Komponenten für einen positiven Ausgang der Transaktion votiert haben.

Dieser Ansatz läßt sich immer dann problemlos verwenden, wenn die Arbeit des Benutzers soweit unabhängig von den übrigen Aktionen der Transaktion ist, daß keine auf den Ergebnis- sen, die der Benutzer erarbeitet hat, basiert.

Ein Beispiel hierfür wäre die Situation, daß der Benutzer ein Ergebnis, das in vorhergehenden Steps von automatischen Stepservern erzeugt wurde, abzeichnen muß. Wenn hingegen der Benutzer ein Dokument bearbeitet oder erstellt, das von nachfolgenden Steps weiterverarbeitet wird, ist die oben beschriebene Lösung leider nicht anwendbar.

Im Regelfall bleibt es also die Aufgabe des Benutzeragenten, sich einerseits dem System ge- genüber zu verhalten wie jede andere Komponente, die an einer Transaktion teilnimmt; ande- rerseits muß er dieses transaktionale Verhalten benutzerfreundlich vermitteln.

(23)

Transaktion Start

rücksetzbare Aktion rücksetzbare

Aktion reale Aktion rücksetzbare

Aktion

Commit oder Rollback

verzögern

Ausführen der realen Aktion nur

im Commit-Fall Abbildung 11: Behandlung einer realen Aktion

Es lassen sich folgende Fälle unterscheiden, wie eine Transaktion zu Ende gehen kann:

• Die Transaktion setzt zurück (Rollback), nachdem der Benutzer seine Aufgabe abgearbeitet und das Ergebnis zurückgeschickt hat.

• Die Transaktion setzt zurück (Rollback), während der Benutzer die zugehörige Aufgabe bearbeitet.

• Die Transaktion setzt zurück (Rollback), bevor der Benutzer mit der Abarbeitung begon- nen hat.

• Die Transaktion wird erfolgreich beendet (Commit). Damit sie dies tun kann, muß der Be- nutzer wie im ersten Fall sein Resultat schon zurückgeschickt haben.

4.2.1 Rollback nach der Bearbeitung

In diesem Szenario erhält der Benutzeragent (User Agent) von der ConTract Engine eine Auf- gabe zur Abarbeitung durch seinen Benutzer, die er an die Oberfläche - das Tasklist Interface - weiterleitet, sobald dieses vom Benutzer gestartet wird. Nach der Bearbeitung wird das Er- gebnis an den Benutzeragenten übermittelt und von diesem an die ConTract Engine weiterge- geben. Für den Benutzer ist die Aufgabe zu diesem Zeitpunkt erfolgreich bearbeitet und abge- schlossen. Nun erfolgt jedoch ein Zurücksetzen der zugehörigen Transaktion.

(24)

Aufgabe bearbeiten ConTract

Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

Aufgabe weiterleiten

Ergebnis zurückschicken Ergebnis weiterleiten

Zurücksetzen der Transaktion

Meldung an den Benutzer?

an der Transaktion teilnehmende Komponenten

OTS

Abbildung 12: Zurücksetzen einer Transaktion nach der Bearbeitung durch den Benutzer Es gibt nun zwei prinzipielle Ansätze, wie sich das System gegenüber dem Benutzer verhalten kann:

4.2.1.1 Der Benutzer als gewöhnlicher Stepserver

Die einfachste Möglichkeit besteht darin, den Benutzer zu behandeln wie einen gewöhnlichen automatischen Stepserver, das heißt das vom Benutzer erarbeitete Ergebnis wird vom System ohne eine Benachrichtigung weggeworfen. Da die ConTract Engine im Falle des Zurückset- zens einer Transaktion höchstwahrscheinlich nochmals versucht, den Step auszuführen, also dieselbe Transaktion nochmals startet, wird dem Benutzer über kurz oder lang dieselbe Auf- gabe erneut vorgelegt.

Da der Benutzeragent nur aus einem Grunde als Recoverable Server am transaktionalen Pro- tokoll des OTS teilnimmt, nämlich um den Benutzer über den Ausgang der Transaktion zu informieren, würde die Implementierung des Benutzeragenten durch diese Vorgehensweise stark vereinfacht, da durch den Verzicht auf eine Benachrichtigung des Benutzers die Zusam- menarbeit mit dem OTS entfällt.

Ein solches Verhalten des Systems ist dem Benutzer jedoch unter dem Gesichtspunkt der An- wenderfreundlichkeit nicht zumutbar, da unter Umständen von ihm verlangt wird, dieselbe Aufgabe wieder und wieder auszuführen. Auch möchte ein menschlicher Bearbeiter vermutlich erfahren, ob die Transaktion an der er mitgewirkt hat, erfolgreich verlaufen ist oder nicht.

(25)

4.2.1.1 Sonderbehandlung des Benutzers

Wir müssen also besonderes Augenmerk auf zwei Aspekte legen: Zum einen soll der Benutzer davor bewahrt werden, nach einem Abbruch der Transaktion dieselbe Aufgabe nochmals bear- beiten zu müssen. Zum anderen ist eine Mitteilung an den Benutzer darüber, was mit dem von ihm erarbeiteten Ergebnis geschehen ist, notwendig.

Aufbewahren alter Arbeitsergebnisse

Um die erste Anforderung zu erfüllen, kann der Benutzeragent die vom Benutzer erarbeiteten Ergebnisse auch nach dem Abbruch der Transaktion aufbewahren. Tritt nun der oben erwähnte Fall ein, daß dieselbe Aufgabe nochmals eintrifft, so kann das vom Benutzer zuvor erbrachte Ergebnis für diesen erneuten Aufruf verwendet werden. Dieser Vorgang könnte soweit auto- matisiert werden, daß der Benutzeragent die Aufgabe gar nicht erst an den Benutzer weiter- reicht, sondern, sobald er erkennt, daß die Aufgaben identisch sind, von sich aus das alte Er- gebnis an die ConTract Engine zurückschickt.

Der flexibelste Ansatz besteht jedoch darin, den Benutzer mit einzubeziehen. Es wäre nämlich denkbar, daß der Benutzer beispielsweise beim ersten Eintreffen der Aufgabe einen Bericht über einen Sachverhalt geschrieben hat, bei dem sich bis zum zweiten Eintreffen der Aufgabe einige Änderungen ergeben haben. Würde jetzt der Benutzeragent automatisch den alten Be- richt zurückschicken, so wäre dieser im günstigsten Fall veraltet, im schlimmsten Fall vielleicht sogar nicht mehr korrekt. Eine Einbeziehung des Benutzers ist folglich erstrebenswert.

Meiner Ansicht nach sollte daher der Benutzer die neu eingetroffene Aufgabe zusammen mit den Ergebnissen der früheren Bearbeitung erhalten. Er kann dann frei die Entscheidung treffen, was problemlos übernommen werden kann und wo er möglicherweise noch Änderungen an- bringen sollte.

Durch diese Vorgehensweise hat der Benutzer die größtmöglichen Freiheiten ohne daß der Benutzeragent auf die Teilnahme am transaktionalen Protokoll verzichten muß. Einerseits bricht der Benutzeragent dadurch, daß er Ergebnisse aufbewahrt, die zu abgebrochenen Trans- aktionen gehören, die Regel, daß jegliche Spur einer solchen Transaktion aus dem System ge- tilgt werden soll; andererseits verbirgt er diese Tatsache vor dem System, so daß er formal allen Anforderungen genügt, die an eine an einer Transaktion teilnehmende Komponente ge- stellt werden.

Die letztendliche Entscheidung, wie mit dem Benutzer umgegangen wird, läßt sich jedoch auf der Ebene des Benutzeragenten nicht treffen, da dieser nur mittelbar über die Benutzungsober- fläche - das Tasklist Interface - mit dem Benutzer kommuniziert. Er sollte also so flexibel kon- zipiert sein, daß er die Entscheidungen, die beim Entwurf der Benutzungsoberfläche getroffen werden, möglichst in keiner Weise einengt.

Aus diesem Grunde ist die Schnittstelle zwischen dem Benutzeragenten und dem Tasklist In- terface sehr allgemein gehalten (siehe Schnittstellen des Benutzeragenten im Anhang). Die Oberfläche kann sich über den Aufruf von

(26)

void getTask(

in string taName, out string request,

out string tasklistInfo,

out APRICOTS_Definitions::FileSequence params) raises (AgentError);

eine beliebige Aufgabe vom Benutzeragenten geben lassen. Dabei ist es unerheblich, ob es sich um eine vom Benutzer noch nicht begonnene, eine gerade in Bearbeitung befindliche oder eine schon abgeschlossene Aufgabe handelt. Es ist also - wenn die Oberfläche ein solches Vorgehen unterstützt - möglich, über diesen Aufruf eine alte, schon längst fertig bearbeitete Aufgabe, die zu einer abgebrochenen Transaktion gehört, nochmals darzustellen. Der Benutzer kann nun die alten Ergebnisse für die Bearbeitung der neuen, aber identischen, Aufgabe verwenden. Diese Vorgehensweise ist jedoch nicht zwingend: besteht von Seiten der Benutzungsoberfläche der Wunsch, die alten Ergebnisse unberücksichtigt zu lassen, so ist dies problemlos möglich.

Der Benutzeragent bewahrt also auch Aufgaben und ihre Ergebnisse auf, wenn die zugehöri- gen Transaktionen schon längst entweder erfolgreich beendet oder aber zurückgesetzt worden sind. Hier stellt sich zwangsläufig die Frage, wie lange diese Aufbewahrung erfolgen soll.

Eine Möglichkeit wäre das automatische Löschen nach einem bestimmten Zeitlimit. Die Schwierigkeit hierbei ist jedoch die Wahl der idealen Aufbewahrungszeit. Wird diese zu kurz gewählt, dann werden Aufgaben gelöscht, die der Benutzer vielleicht zur Bearbeitung eines neuen Auftrages benötigt; wählt man sie zu lang, dann verliert der Benutzer wegen der großen Anzahl leicht den Überblick über seine schon beendeten Aufgaben.

Die bessere Lösung stellt daher auch hier wieder die Einbeziehung des Benutzers dar. Der Be- nutzeragent bietet über die Schnittstelle

void deleteTask(in string taName) raises (AgentError);

die Möglichkeit, nicht mehr benötigte Aufgaben durch den Benutzer löschen zu lassen. Auch hier wiederum entscheidet jedoch letztendlich das Tasklist Interface über die Beteiligung des Benutzers: Ist diese nicht gewünscht, so kann die Oberfläche diese Schnittstelle automatisch aufrufen und dadurch Aufgaben ohne Zutun des Benutzers löschen.

Die Frage, wie die Benutzungsoberfläche letztendlich mit den Möglichkeiten, die der Benut- zeragent bietet, umgeht, wird in der Ausarbeitung zum Tasklist Interface, das parallel zu dieser Studienarbeit entwickelt wird, behandelt.

Benachrichtigung des Benutzers

Für die Motivation des Benutzers ist es wichtig, daß er nach der Abarbeitung einer Aufgabe eine Rückmeldung erhält, was mit seinen Arbeitsergebnissen geschehen ist. Er sollte also, falls die Transaktion erfolgreich beendet wird (Commit), eine Meldung von der Art „Die Ergebnisse der Aufgabe XYZ wurden erfolgreich bearbeitet!“ erhalten; im Falle eines Zurücksetzens der Transaktion (Abort) sollte er auch dies erfahren: „Die Ergebnisse der Aufgabe XYZ konnten nicht weiterbearbeitet werden!“.

(27)

Wird die oben erwähnte Alternative gewählt, daß im Falle eines Transaktionsabbruchs das Er- gebnis aufbewahrt und bei einem erneuten Eintreffen der Aufgabe automatisch und ohne Zutun des Benutzers verwendet wird, so muß die Meldung eines negativen Ausgangs zunächst zu- rückgehalten werden. Erst wenn feststeht, daß alle Versuche, diese Transaktion auszuführen, gescheitert sind, darf der Benutzer davon in Kenntnis gesetzt werden.

Um den Benutzer vom Ausgang einer Transaktion benachrichtigen zu können, ist es unerläß- lich, daß der Benutzeragent am Commit-Protokoll des OTS (Object Transaction Service) teil- nimmt. Nur auf diese Art und Weise kann er erfahren, ob eine Transaktion erfolgreich beendet wird (Commit) oder nicht (Abort). Er registriert zu diesem Zwecke beim Transaction Service für jede Aufgabe eine Resource, die über die beiden Schnittstellen

void rollback ()

raises ( HeuristicCommit, HeuristicMixed, HeuristicHazard );

void commit ()

raises ( NotPrepared, HeuristicRollback, HeuristicMixed, HeuristicHazard );

im Rollback- oder im Commit-Fall der Transaktion beziehungsweise über die Schnittstellen void commit_subtransaction ( in Coordinator parent );

void rollback_subtransaction ();

beim Rücksetzen oder erfolgreichen Ende der Subtransaktion vom OTS einen entsprechenden Aufruf erhalten (siehe auch [OTS94]).

Diese Informationen gibt der Benutzeragent dann über die folgenden Schnittstellen an das Tasklist Interface weiter:

string getAbortedTask() raises (AgentError);

string getCommittedTask() raises (AgentError);

Natürlich liegt es auch hier wiederum im Ermessen der Oberfläche, was dem Benutzer in den beiden Fällen angezeigt wird und ob die Aufgaben mittels der oben erwähnten deleteTask()-Schnittstelle nach dem Anzeigen gelöscht werden sollen oder nicht.

Könnte man auf die Benachrichtigung des Benutzers über den Ausgang einer Transaktion ver- zichten, so bräuchte der Benutzeragent nicht am transaktionalen Protokoll teilzunehmen. Eine Aufgabe wäre dann für diesen in dem Moment erledigt, wenn die Ergebnisse an die ConTract Engine weitergeliefert werden.

(28)

4.2.2 Rollback während der Bearbeitung

Betrachten wir nun den Fall, daß eine Transaktion zurückgesetzt wird (Rollback), während der Benutzer mit der Bearbeitung einer zu dieser Transaktion gehörigen Aufgabe beschäftigt ist.

Aufgabe bearbeiten

Bearbeitung unterbrechen ConTract

Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

Aufgabe weiterleiten an der Transaktion teilnehmende Komponenten

eventuell Teilergebnis zurückschreiben Zurücksetzen der Transaktion

Meldung an den Benutzer OTS

Abbildung 13: Zurücksetzen einer Transaktion während der Bearbeitung durch den Benutzer Es liegt auf der Hand, daß in diesem Fall eine Benachrichtigung des Benutzers unerläßlich ist.

Es ist dem Benutzer nicht zuzumuten, an einer Aufgabe weiterarbeiten zu müssen, an deren Erledigung von Seiten des Systems keinerlei Interesse mehr besteht. Die Möglichkeit, den Be- nutzer nicht von einem Transaktionsabbruch in Kenntnis zu setzen, die im vorherigen Fall eines Abbruchs nach der Bearbeitung durch den Benutzer zumindest möglich - wenn auch nicht be- nutzerfreundlich - war, ist daher hier nicht mehr gegeben.

Das Tasklist Interface erreicht die Abbruchmeldung wie im vorherigen Fall über die Schnitt- stelle

string getAbortedTask() raises (AgentError);.

Es muß dann geeignete Maßnahmen treffen, die weitere Bearbeitung der abgebrochenen Auf- gabe durch den Benutzer zu unterbinden.

Falls es sinnvoll erscheint, die vom Benutzer bis zu diesem Zeitpunkt erarbeiteten Teilergeb- nisse aufzubewahren, kann das Tasklist Interface diese über die Schnittstelle

(29)

void giveTouchedTask(

in string taName,

in string tasklistInfo,

in APRICOTS_Definitions::FileSequence params) raises (AgentError);

an den Benutzeragenten übermitteln. Diese Schnittstelle dient dazu, eine noch nicht vollständig bearbeitete Aufgabe zwischenzuspeichern, beispielsweise wenn der Benutzer seine Arbeit am Feierabend unterbricht.

Hätte man es nur mit dem Fall zu tun, daß eine Transaktion abgebrochen wird, solange der Benutzer die dazugehörige Aufgabe bearbeitet, könnte man bei der Implementierung des Be- nutzeragenten auf die Teilnahme am transaktionalen Protokoll verzichten, da eine Abbruch- meldung nicht nur vom OTS (Object Transaction Service) an die dort registrierte Resource erfolgt, sondern auch durch die ConTract Engine über die Schnittstelle

void killStepExecution (

in APRICOTS_Definitions::ConTractInstanceID ciid, in APRICOTS_Definitions::StepInstance stepInstance ) raises (AlreadyDone, APRICOTS_Definitions::NotFound);.

Da die Implementierung des Benutzeragenten die Registrierung einer Resource beim OTS vorsieht, wird eine Meldung über diese Schnittstelle von der ConTract Engine jedoch ignoriert.

4.2.3 Rollback vor der Bearbeitung

Eine weitere Möglichkeit stellt das Zurücksetzen einer Transaktion (Rollback) dar, bevor der Benutzer begonnen hat, die zu dieser Transaktion gehörende Aufgabe zu bearbeiten. Hierbei gilt es zwei Fälle zu unterscheiden:

ConTract Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

Aufgabe weiterleiten an der Transaktion teilnehmende Komponenten

Zurücksetzen der Transaktion

Meldung an den Benutzer OTS

(30)

Im ersten Fall wurde die Aufgabe vom Benutzeragenten schon an das Tasklist Interface wei- tergeleitet; der Benutzer hat aber noch nicht begonnen, diese Aufgabe abzuarbeiten. Für den Benutzeragenten unterscheidet sich dieser Fall nicht vom vorherigen Szenario, bei dem schon mit der Bearbeitung begonnen wurde, da es für ihn keine Möglichkeit gibt, festzustellen, wann der Benutzer sich einer bestimmten Aufgabe widmet. Er erfährt erst dann etwas über den Be- arbeitungsstand, wenn die Oberfläche mittels giveTouchedTask() eine teilweise fertigge- stellte beziehungsweise durch giveDoneTask() eine vollständig bearbeitete Aufgabe zu- rückliefert.

Wie vorher dargelegt wird die Abbruchmeldung auch hier über die Schnittstelle string getAbortedTask()

raises (AgentError);

an das Tasklist Interface übermittelt, das daraufhin dafür Sorge tragen muß, daß der Benutzer die Bearbeitung dieser Aufgabe nicht mehr anfängt.

ConTract Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

an der Transaktion teilnehmende Komponenten

Zurücksetzen der Transaktion OTS

Das Tasklist- Interface ist nicht aktiv, da der Benutzer nicht anwesend ist.

Abbildung 15: Zurücksetzen einer Transaktion vor der Bearbeitung (Fall 2)

Im zweiten Fall wurde die Aufgabe vom Benutzeragenten zum Zeitpunkt der Abbruchmeldung noch nicht an das Tasklist Interface übermittelt, da der Benutzer nicht anwesend ist und infol- gedessen auch die Oberfläche, an der er arbeitet, nicht gestartet worden ist.

Hier genügt es, der Oberfläche, sobald sie gestartet wird und die zu erledigenden Aufgaben beim Benutzeragenten abholt, die zu der abgebrochenen Transaktion gehörende Aufgabe ein- fach nicht zu übermitteln. Eventuell kann man dem Benutzer die Information zukommen las- sen, daß eine solche abgebrochene, von ihm nie bearbeitete Aufgabe existiert. Auch dies läßt sich über getAbortedTask()abwickeln.

(31)

4.2.4 Commit

Einen weiteren Fall - und zwar hoffentlich den Normalfall - stellt die erfolgreich ausgeführte Transaktion dar (Commit). Auch hier trifft die Meldung vom OTS, wie schon im weiter oben besprochenen Fall des Abbruches der Transaktion nach der Bearbeitung durch den Benutzer, erst ein, nachdem die Arbeitsergebnisse an die ConTract Engine übermittelt worden sind. Die übrigen beiden Fälle, die beim Transaktionsabbruch (Rollback) zu betrachten sind, entfallen bei der erfolgreichen Ausführung der Transaktion, da das System naturgemäß erst dann entschei- den kann, daß die Transaktion durchgeführt werden kann, wenn alle Ergebnisse vorliegen;

dazu gehören auch die vom Benutzer erarbeiteten Resultate.

Aufgabe bearbeiten ConTract

Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

Aufgabe weiterleiten

Ergebnis zurückschicken Ergebnis weiterleiten

Transaktion erfolgreich

Meldung an den Benutzer?

an der Transaktion teilnehmende Komponenten

OTS

Abbildung 16: Erfolgreicher Abschluß einer Transaktion

Auch in diesem Fall stellt sich wie beim Transaktionsabbruch die Frage, ob der Benutzer von der erfolgreichen Ausführung benachrichtigt werden soll oder nicht. Die Entscheidung hierüber liegt wieder bei der Benutzungsoberfläche, dem Tasklist Interface. Der Benutzeragent, der wie im Abbruchfall über eine Schnittstelle der beim OTS registrierten Resource (siehe Schnittstel- len des Benutzeragenten im Anhang), und zwar hier über

void commit ()

raises ( NotPrepared, HeuristicRollback, HeuristicMixed, HeuristicHazard );

(32)

über den Ausgang der Transaktion unterrichtet wird, bietet dem Tasklist Interface die Mög- lichkeit, diese Information mittels

string getCommittedTask() raises (AgentError);

abzufragen (siehe Schnittstellen im Anhang). Auch hier handelt es sich lediglich um eine Op- tion für die Oberfläche, sie kann auch auf das Auslesen und Übermitteln dieser Aufgaben an den Benutzer verzichten.

Da der Benutzeragent nicht entscheiden kann, ob der Benutzer vielleicht die ein oder andere erfolgreich durchgeführte Aufgabe noch aufbewahren möchte, etwa weil er deren Arbeitser- gebnis für eine ähnliche neue Aufgabe verwenden kann, löscht der Benutzeragent diese erst auf die explizite Anforderung über

void deleteTask(in string taName) raises (AgentError);.

4.3 Optionen des Benutzers

4.3.1 Zurückweisen einer Aufgabe

Bisher haben wir nur den Fall betrachtet, daß der Benutzer bereit und in der Lage ist, die an ihn übermittelten Aufgaben zu erledigen. Was geschieht aber, wenn dies nicht so ist, etwa weil sich im Skript, das die ConTract Engine ausführt, ein Fehler eingeschlichen hat?

nicht zuständig!

ConTract Engine

Benutzer- agent

Tasklist Interface und Benutzer Aufgabe verschicken

Aufgabe weiterleiten

Aufgabe zurückweisen Fehlermeldung

Abbildung 17: Der Benutzer weist die Bearbeitung einer Aufgabe zurück

Dem Benutzer sollte also die Möglichkeit offenstehen, eine Aufgabe, für deren Bearbeitung er sich nicht zuständig fühlt, zurückzuweisen. Hierzu bietet der Benutzeragent dem Tasklist Inter- face die Schnittstelle

(33)

void rejectTask(in string taName) raises (AgentError);

an (siehe Schnittstellen des Benutzeragenten im Anhang). Wird diese aufgerufen, so schickt der Benutzeragent der zuständigen ConTract Engine eine entsprechende Fehlermeldung. Eine Speicherung der Aufgabe ist in diesem Fall nicht nötig und wird deshalb unterlassen; der Be- nutzer kann also auf einmal zurückgewiesene Aufgaben nicht wieder zugreifen.

4.3.2 Erfragen früherer Bearbeiter

Bei der Bearbeitung eines Dokumentes durch den Benutzer möchte dieser unter Umständen wissen, wer zu diesem etwas beigetragen hat. Gesucht ist also eine Liste der vorherigen Bear- beiter. Der Benutzeragent erfüllt diesen Wunsch, indem er dem Tasklist Interface die Schnitt- stelle

void getFileHistory(

in string taName, in short pos,

out APRICOTS_Definitions::NameStringSeq executors) raises (AgentError);

anbietet (siehe Schnittstellen des Benutzeragenten im Anhang). Dieser Aufruf wird mittels void getModifiersOfParameter (

in APRICOTS_Definitions::StepObjectID soid, in unsigned short position,

out APRICOTS_Definitions::NameStringSeq executors ) raises (APRICOTS_Definitions::Reject);

an die ConTract Engine weitergegeben und das von dort erhaltene Ergebnis an die Oberfläche - und somit den Benutzer - zurückgeliefert.

Ergebnis Ergebnis

ConTract Engine

Benutzer- agent

Tasklist Interface und Benutzer

Bearbeiter erfragen Bearbeiter erfragen

Abbildung 18: Der Benutzer erfragt die früheren Bearbeiter eines Dokuments

(34)

4.4 Verwendung von Prioritäten

Die Aufgaben, die der Benutzer zur Bearbeitung vorgelegt bekommt, können unter Umständen von unterschiedlicher Wichtigkeit sein. Um diesem Umstand Rechnung zu tragen, bietet es sich an, den einzelnen Aufgaben als zusätzlichen Parameter die Priorität mitzugeben. Das Tasklist Interface könnte dann beispielsweise Aufgaben mit höherer Priorität in der Darstellung beson- ders hervorheben und den Benutzer auffordern, diese zuerst in Angriff zu nehmen.

Die Erfahrung zeigt jedoch, daß Prioritäten von menschlichen Bearbeitern nur unzureichend beachtet werden. Je öfter ein Auftrag mit dem Vermerk „schrecklich wichtig“ beim Benutzer eintrifft, um so weniger wird dieser bereit sein, jedesmal seine übrige Arbeit liegen zu lassen und sich zuerst dieser privilegierten Aufgabe zuzuwenden.

Bei der Implementierung von APRICOTS wurde daher auf die Verwendung von Prioritäten verzichtet.

(35)

5. Benutzeragent und ConTract Engine

5.1 Synchrone und asynchrone Kommunikation

Eine ConTract Engine, die ein Skript abarbeitet, findet darin zu jedem auszuführenden Step Informationen darüber, welcher Stepserver für diesen Step mit welchen Argumenten aufgeru- fen werden soll und was dieser Stepserver als Rückgabewert liefert. Mit Hilfe dieser Informa- tionen und der Verwendung des Dynamic Invocation Interface (DII) von CORBA kann die ConTract Engine den entsprechenden Stepserver ansprechen.

Hierbei werden die Stepserver durch einen synchronen Aufruf aktiviert. Dies bedeutet, daß die ConTract Engine - oder zumindest der Thread, der den Aufruf startet - solange blockiert ist, bis der Stepserver ein Ergebnis zurückschickt.

ConTract Engine

Stepserver

Stepserver aufrufen

ConTract Engine ist blockiert

Ergebnis empfangen und weiterarbeiten

Auftrag wird empfangen Bearbeitung des Auftrags Zurücksenden des

Ergebnisses

Abbildung 19: Synchroner Aufruf

Am einfachsten wäre es nun, wenn ein Benutzeragent (User Agent) wie jeder andere Stepser- ver auch behandelt werden könnte. Dieser Ansatz ist jedoch leider nicht praktikabel, da sich ein automatischer Stepserver (also eine Komponente, die zur Ausführung ihrer Aufgabe keine menschliche Interaktion benötigt) und ein Benutzeragent in einer Hinsicht wesentlich unter- scheiden: die Antwortzeit des Benutzeragent ist um ein vielfaches länger.

Der Grund hierfür liegt auf der Hand: Während ein automatischer Stepserver sofort, nachdem er einen Auftrag (Task) erhalten hat, losarbeiten kann und das Ergebnis in der Regel innerhalb von Sekunden liefert, nimmt ein Benutzeragent die Aufgabe nur entgegen. Diese muß erst an das Tasklist Interface übermittelt, vom Benutzer abgearbeitet und schließlich wieder an den

(36)

sultat vorliegt. Selbst wenn der Benutzer gerade vor dem Bildschirm sitzt und die übermittelte Aufgabe sofort in Angriff nimmt, bleibt die ConTract Engine bei der Verwendung von syn- chronen Aufrufen zu lange blockiert.

Die Lösung liegt in der Verwendung von asynchronen Aufrufen: Die ConTract Engine schickt wie beim synchronen Aufruf die Aufgabe an den Benutzeragenten; im Gegensatz zum vorheri- gen Fall kann sie jetzt jedoch weiterarbeiten, bis das vom Benutzer erarbeitete Resultat ein- trifft.

ConTract Engine

Benutzer- agent Stepserver

aufrufen

ConTract Engine kann weiterarbeiten

Ergebnis empfangen und weiterarbeiten

Auftrag wird empfangen Auftrag wird an das Tasklist Interface weitergegeben und das Ergebnis von dort empfangen Zurücksenden des Ergebnisses

Abbildung 20: Asynchroner Aufruf

Es wird also bei der Kommunikation zwischen der ConTract Engine und dem Benutzeragenten die zweite Variante benutzt. Dabei wird jeder asynchrone Aufruf durch jeweils zwei synchrone Aufrufe simuliert: Mit dem ersten synchronen Aufruf wird die Aufgabe an den Benutzeragen- ten übermittelt, der den Empfang bestätigt. Die ConTract Engine kann sich nun anderen Din- gen zuwenden, bis sie ihrerseits einen synchronen Aufruf vom Benutzeragenten erhält, mit dem das vom Benutzer erarbeitete Ergebnis überbracht wird. Die Zeit, für die die ConTract Engine während der synchronen Aufgabenübermittlung blockiert ist, liegt in der Größenordnung der Blockierung, die beim Aufruf von automatischen Stepservern auftritt.

(37)

ConTract Engine

Benutzer- agent Stepserver

aufrufen

Bestätigung empfangen ConTract Engine kann weiterarbeiten

Ergebnis empfangen und bestätigen

Auftrag wird empfangen und bestätigt

Auftrag wird an das Tasklist Interface weitergegeben und das Ergebnis von dort empfangen

Zurücksenden des Ergebnisses

Bestätigung wird empfangen Abbildung 21: Ein asynchroner Aufruf wird durch zwei synchrone Aufrufe simuliert

5.2 Übermittlung der Aufgaben und der Ergebnisse

Die ConTract Engine erfährt - wie oben dargelegt - bei der Abarbeitung des Skriptes aus den darin enthaltenen Informationen, welchen Stepserver sie mit welchen Parametern aufrufen soll.

Da die dabei zu benutzenden Schnittstellen zum Übersetzungszeitpunkt der ConTract Engine noch nicht bekannt sind, verwendet sie das Dynamic Invocation Interface (DII) von CORBA.

Da aus den oben genannten Gründen den Benutzeragenten (User Agent) als asynchroner Step- server behandelt wird, muß die ConTract Engine eine Schnittstelle zur Verfügung stellen, über die der Benutzeragent das vom Benutzer erarbeitete Ergebnis weitergeben kann. Zu diesem Zweck übermittelt sie an den Benutzeragenten eine Objektkennung, die auf sie selber weist.

Der Agent bindet sich dann für die Lieferung des Resultats an diese ConTract Engine. Auch hier weiß die Engine noch nicht, aus welchen Datentypen das Ergebnis besteht. Die Schnitt- stelle muß deshalb sehr allgemein gehalten werden (siehe Schnittstellen im Anhang):

void stepServerReply (

in APRICOTS_Definitions::StepInstance stepInstance, in APRICOTS_Definitions::StepServerResult result,

in APRICOTS_Definitions::OutParameterSeq outParameterSeq ) raises ( Reject );

(38)

Die Engine erwartet lediglich eine Sequenz von Werten beliebiger Typen („Any“). Von beson- derer Wichtigkeit ist daher die Reihenfolge der in dieser Sequenz übermittelten Parameter. Der Benutzeragent muß diese in genau derselben Ordnung liefern, die im Skript festgelegt ist.

5.3 Bestandteile eines Auftrages

Die Aufträge für den Benutzer, die die ConTract Engine an den Benutzeragenten (User Agent) verschickt, können völlig unterschiedlicher Natur sein. Da sie jedoch durch diesen und das Tasklist Interface immer auf dieselbe Weise behandelt werden, ist es notwendig, die Aufgaben in eine standardisierte Form überzuführen.

In dieser Realisierung besteht ein Auftrag an einen Benutzer aus einer Folge von Dateien, die wiederum mehrere Attribute beinhalten, und einer Anweisung an den Benutzer, was er mit diesen Dateien anfangen soll (siehe die Schnittstellen im Anhang):

typedef sequence<File> FileSequence;

void getTask(

in string taName, out string request,

out string tasklistInfo,

out APRICOTS_Definitions::FileSequence params) raises (AgentError);

Mit diesem allgemeinen Ansatz lassen sich die verschiedensten Anwendungen modellieren.

Letztendlich besteht wohl jede vom Benutzer zu erledigende Aufgabe aus einer oder mehreren Dateien, die er entweder lesen oder bearbeiten soll.

Transaktion Komponente

A

Komponente B Datei

Datei Datei

Abbildung 22: Verschicken des Dateiinhaltes

Eine Alternative zu dieser direkten Übergabe der Dateien wäre die Verwendung von URLs (Uniform Resource Locator). Da mit dieser Methode nur Verweise auf Dateien und nicht diese selbst übertragen werden, wird dadurch die Menge der zu übertragenden Daten signifikant verringert. Allerdings befinden sich in diesem Fall nur die URLs unter dem Schutz der Trans- aktion, die die jeweilige Aufgabe umschließt; der Dateiinhalt selbst bleibt ungeschützt. In der vorliegenden Realisierung kann eine veränderte Datei im Falle eines Transaktionsabbruches einfach weggeworfen werden, da sie ja nur eine Kopie darstellt. Bei der Verwendung von URLs müßte man jedoch die am Original erfolgten Veränderungen rückgängig machen, was einen erhöhten Aufwand darstellt.

(39)

Transaktion Komponente

A

Komponente B URLURL

URL Datei Datei Datei

Abbildung 23: Verschicken von Zeigern auf den Dateiinhalt

5.4 Aufträge ohne Rückgabewerte

Einen Spezialfall stellen Aufgaben dar, bei denen der Benutzer kein Ergebnis erarbeiten und zurückliefern muß, beispielsweise, wenn er eine Mitteilung nur lesen muß. Auch in diesem Fall muß die ConTract Engine natürlich über die stepServerReply-Schnittstelle eine Rückmeldung erhalten.

Auftrag bearbeiten Auftrag übermitteln

ConTract Engine

Benutzer- agent

Tasklist Interface

Auftrag weiterleiten

Ergebnis

Ergebnis

Abbildung 24: Rückmeldung an die ConTract Engine nach der Bearbeitung

Einerseits können solche Aufträge behandelt werden wie die übrigen auch: die ConTract Engine erhält erst dann eine Erfolgsmeldung, wenn der Benutzer die ihm vorgelegte Mitteilung auch tatsächlich gelesen hat. Da jedoch kein Ergebnis übermittelt werden muß, kann der Benutzeragent (User Agent) diese Erfolgsmeldung auch sofort loschicken.

Der Vorteil einer solchen Sonderbehandlung ist offensichtlich: Die ansonsten notwendige Wartezeit, bis der Benutzer eine Aufgabe abgearbeitet hat, entfällt; die Antwortzeit des Benutzeragenten bewegt sich in Regionen, die sonst nur von automatischen Stepservern erreicht werden. Man könnte also hier auf die weiter oben beschriebenen asynchronen Aufrufe verzichten, allerdings müßte dazu der Benutzeragent eine eigene Schnittstelle anbieten und auch die ConTract Engine müßte einen solchen Auftrag gesondert behandeln.

Referenzen

ÄHNLICHE DOKUMENTE

Da mir die Ehre zuteil wurde, diesem hohen Haus für die nächste Legislatur- periode vorzustehen, erlaube ich mir, mich den Ärzten Sachsens vorzustellen.. Ich bin Jahrgang

Ich bin ihm unendlich dankbar für die Prägung, die ich durch ihn erfah- ren habe, und ich bin mir sicher, dass es vielen Kolleginnen und Kollegen, die ihn kannten, ähnlich

a) Erstellen Sie im aktuellen Verzeichnis eine neue Datei neu.txt. Rechte anzeigen lassen. a) Lassen Sie sich die Rechte der neu erstellten Datei und des Verzeichnisses

Ohne das Vertrauen ins demokratische Frankreich aber wird es auch den Deutschen nicht möglich sein, weiter konstruktiv an Europa zu arbeiten. Man stelle sich Frankreich mit

Oder der Frust der amerikanischen Mehr- heit darüber, für die Folgen der Fi- nanzkrise zahlen zu müssen, während sie selbst immer weniger verdienen und kaum Aufstiegschancen

Die ständige Ausstellung infor- miert die Besucher auf rund 90 Quadratmetern über Ge- schichte, Tradition und kultu- rellen Stellenwert der Bratwurst im gesellschaftlichen Leben im

Bei einer überhöhten oralen Dosis jedoch ist die Kapazität der Leber während dieser ersten Passage rasch erschöpft und ein entsprechender Teil des Nalo- xons gelangt unverändert in

Dabei ist es egal, ob wir die Person kennen oder nicht, ob sie berühmt ist oder unbekannt, ja noch nicht einmal, ob das Ereignis real oder nur gespielt ist: Die Fähigkeit, sich in