From 3a5b6752b9538ffd2edcd350af485aa3bdd22745 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 11 Aug 2008 11:43:16 +0000 Subject: written a lot --- LaTeX/argouml.zargo | Bin 51736 -> 52006 bytes LaTeX/chapters/conclusion.tex | 8 +- LaTeX/chapters/implementierung.tex | 68 +- LaTeX/diplomarbeit.pdf | 4014 ++++++++++++++++++------------------ LaTeX/images/prefs-editors.eps | 62 +- LaTeX/revision.tex | 2 +- 6 files changed, 2107 insertions(+), 2047 deletions(-) diff --git a/LaTeX/argouml.zargo b/LaTeX/argouml.zargo index b33e86f..911ceb3 100644 Binary files a/LaTeX/argouml.zargo and b/LaTeX/argouml.zargo differ diff --git a/LaTeX/chapters/conclusion.tex b/LaTeX/chapters/conclusion.tex index 65d719c..677300b 100644 --- a/LaTeX/chapters/conclusion.tex +++ b/LaTeX/chapters/conclusion.tex @@ -6,16 +6,18 @@ Dar Mit dem Ereigniseditor gibt es eine komfortable Mglichkeit eigene Szenarien zu programmieren um sie anschlieend zu Simulieren. Hierbei kann entweder auf die bereits enthaltenen Protokolle- oder auf selbst implementierte Protokolle zugegriffen werden. Alle Dazugehrigen Einstellungen und programmierten Ereignisse lassen sich vom Gebraucher fr eine sptere Wiederverwendung plattformunabhngig abspeichern. Somit knnen auch abgespeicherte Szenarien beispielsweise an Kommilitonen weitergegeben werden oder fr eine sptere Prsentierung zwischengespeichert werden. Mit dem Loggfilter lassen sich mithilfe von regulren Ausdrcken nur die relevanten Loggnachrichten anzeigen, was die Analyse einer Simulation erheblich vereinfacht. Weitere Funktionalitten wie Lamport- und Vektor-Zeitstempel sowie Anti-Aliasing runden den Simulator ab. -Durch den objektorientierten Aufbau ist der Simulator relativ einfach erweiterbar, was nicht nur das Protokoll-API betrifft. Htte fr diese Diplomarbeit noch mehr Zeit zur Verfgung gestanden, dann knnten einige der folgenden Funktionen (hier in alphanumerisch sortierten Reihenfolge aufgelistet) auch eingebaut worden sein: +Durch den objektorientierten Aufbau ist der Simulator relativ einfach erweiterbar, was nicht nur das Protokoll-API betrifft. Insgesamt wurde an den meisten Stellen darauf geachtet, dass zu einem sp\"{a}teren Zeitpunkt Erweiterungen einflieen k\"{o}nnten. Insbesondere soll die Serialisierung von Objekten r\"{u}ckw\"{a}rtskompatibel bleiben, da sonst bei jeder neuen Simulatorversion alle Simulationen erneut angelegt und abgespeichert werden m\"{u}ssten. + +Htte fr diese Diplomarbeit noch mehr Zeit zur Verfgung gestanden, dann knnten einige der folgenden Funktionen (hier in alphanumerisch sortierten Reihenfolge aufgelistet) auch eingebaut worden sein: \begin{itemize} - \setlength{\itemsep}{-2mm} + \item Die M\"{o}glichkeit Protokolle zu entwickeln ohne den kompletten Quelltext des Simulators vorliegen zu haben. Protokollklassen also als separate Bibliothek einbinden, die dynamisch geladen werden k\"{o}nnen. \item Die Simulationsdauer beliebig lang machen knnen. Dazu msste \textit{VSSimulatorVisualisation} entlang der Zeitachse scrollbar gemacht werden, sodass der Benutzer fr eine nachtrgliche Betrachtung des Simulationsverlaufes zu jeder beliebigen Position zurckspringen kann. \item Eine Zoomfunktion fr die Simulationsvisualisierung einbauen. \item Im Ereigniseditor selbst auch periodische Ereignisse programmierbar machen. Bisher kann nur jedes Ereignis separat programmiert werden oder auf Protokoll-Interne Wecker zurckgegriffen werden. \item Lamport- und Vektor-Zeitstempel als Ereigniseintrittskriterien verwenden knnen. - \item Weitere Funktionalitten einbauen wie zum Beispiel das Anklicken einer Nachrichtenlinie, was zu einer Nachricht alle verfgbaren Informationen anzeigt und diese gegebenenfalls vom Benutzer editiert werden knnen. \item Tiefere Schichten des OSI-Referenzmodells simulieren knnen, wie zum Beispiel TCP, UDP, IP, ... + \item Weitere Funktionalitten einbauen wie zum Beispiel das Anklicken einer Nachrichtenlinie, was zu einer Nachricht alle verfgbaren Informationen anzeigt und diese gegebenenfalls vom Benutzer editiert werden knnen. \end{itemize} Da der Simulator hchstwahrscheinlich unter einer Open Source Lizenz freigegeben wird, und ich mich selbst sehr fr die Entwicklung und Anwendung von Open Source Software interessiere, werden die einen oder anderen Funktionen nachtrglich eingebaut werden. Kommilitonen werden auch herzlich dazu eingeladen sein sich an diesem Software-Projekt zu beteiligen. Als Vorbild sei hier der CPU-Simulator M32, der von Prof. Omann an der Fachhochschule Aachen entwickelt wurde, genannt. Hier existieren bereits einige Erweiterungen und Verbesserungen der Ursprungsversion, die von den Studenten angefertigt wurden. Fr die Entwicklung/Erweiterung wurde keine proprietre Software verwendet, sodass jeder kostenlosen Zugriff auf die dazugehrigen Tools htte. diff --git a/LaTeX/chapters/implementierung.tex b/LaTeX/chapters/implementierung.tex index ed70dc3..b385850 100644 --- a/LaTeX/chapters/implementierung.tex +++ b/LaTeX/chapters/implementierung.tex @@ -34,7 +34,7 @@ Eine Simulation ist von einer Vielzahl von Einstellungen abh \subsection{Einstellungsobjekte} -Auf Abbildung \ref{fig:PackagePrefs} ist der Aufbau des Pakets \textit{prefs} zu sehen. In einer Instanz der Klasse \textit{VSPrefs} lassen sich viele verschiedene Daten als Variablen fr eine sptere Verwendung dynamisch ablegen und stellt somit einen Container fr diese Daten dar. In einem \textit{VSPrefs}-Objekt speichert der Simulator alle seine Einstellungen ab. Zudem besitzt jedes Prozessobjekt und jedes Ereignisobjekt fr lokale Einstellungen seine eigene Instanz von \textit{VSPrefs}. Spter wird noch erklrt, dass Protokollobjekte auch als Ereignisse eingesetzt werden. Somit knnen Protokolleinstellungen auch in ein \textit{VSPrefs}-Objekt abgespeichert werden. Selbst Nachrichtenobjekte besitzt hiervon eine eigene Instanz, wobei hier die zu verschickenden Daten abgelegt werden knnen. +Auf Abbildung \ref{fig:PackagePrefs} ist der Aufbau des Pakets \textit{prefs} zu sehen. In einer Instanz der Klasse \textit{VSPrefs} lassen sich viele verschiedene Daten als Variablen fr eine sptere Verwendung dynamisch ablegen und stellt somit einen Container fr diese Daten dar. In einem \textit{VSPrefs}-Objekt speichert der Simulator alle seine Einstellungen ab. Zudem besitzt jedes Prozessobjekt und jedes Ereignisobjekt fr lokale Einstellungen seine eigene Instanz von \textit{VSPrefs}. Spter wird noch erklrt, dass Protokollobjekte auch als Ereignisse eingesetzt werden. Somit knnen Protokolleinstellungen auch in ein \textit{VSPrefs}-Objekt abgespeichert werden. Selbst Nachrichtenobjekte besitzt hiervon eine eigene Instanz, wobei hier die zu verschickenden Daten abgelegt werden knnen. \begin{figure}[h] \centering @@ -45,7 +45,7 @@ Auf Abbildung \ref{fig:PackagePrefs} ist der Aufbau des Pakets \textit{prefs} zu Jede Variable besteht aus einen Datentypen, einen Variablennamen und einer optionalen Beschreibung sowie einen Wert. Einige Datentypen untersttzen auch die Angabe von Minimal- und Maximalwerten (zum Beispiel besteht eine Prozentangabe aus einen Integerwert zwischen \textit{0} und \textit{100}), was mithilfe der \textit{VSPrefsRestriction}-Klasse implementiert wird. Da man beispielsweise bei Prozent ein \textit{\%} und bei Millisekunden ein \textit{ms} hinter der Variable sehen mchte, kann fr jede Variable auch ein optionaler Einheiten-String abgespeichert werden. -Eine Variablenbeschreibung wird fr die Darstellung im GUI verwendet, whrend der Variablenname eher fr die interne Verwendung vom Simulator verwendet wird. Zum Beispiel hat die Variable \textit{message.prob.outage} (Verlustwahrscheinlichkeit einer Nachricht) die Variablenbeschreibung ``Nachrichtenverlustw'keit''. Wenn fr eine Variable keine Beschreibung existiert so wird, wie auf Abbildung \ref{fig:SimulationseinstellungenExperten} anhand der Farbvariablen schon gesehen wurde, fr die Anzeige einer Variable der Datentyp und der Variablenname verwendet. Variablennamen verwenden die auf Tabelle \ref{tb:VariablenPrefixe} angegebenen Prefixkonventionen. Alle verfgbaren Typen wurden bereits in Tabelle \ref{tb:VariablenDatentypen} aufgelistet. \textit{VSPrefs} stellt fr alle Variablentypen entsprechende Zugriffsmethoden zur Verfgung. +Eine Variablenbeschreibung wird fr die Darstellung im GUI verwendet, whrend der Variablenname eher fr die interne Verwendung vom Simulator verwendet wird. Zum Beispiel hat die Variable \textit{message.prob.outage} (Verlustwahrscheinlichkeit einer Nachricht) als Variablenbeschreibung ``Nachrichtenverlustw'keit''. Wenn fr eine Variable keine Beschreibung existiert so wird, wie auf Abbildung \ref{fig:SimulationseinstellungenExperten} anhand der Farbvariablen schon gesehen wurde, fr die Anzeige einer Variable der Datentyp und der Variablenname verwendet. Variablennamen verwenden die auf Tabelle \ref{tb:VariablenPrefixe} angegebenen Prefixkonventionen. Alle verfgbaren Typen wurden bereits in Tabelle \ref{tb:VariablenDatentypen} aufgelistet. \textit{VSPrefs} stellt fr alle Variablentypen entsprechende Zugriffsmethoden zur Verfgung. Im Folgenden werden nicht alle existierenden Methoden aufgelistet, da diese auch in der Quelltext-Dokumentation eingesehen werden knnen. Die Methoden werden nun nur anhand des Integer-Datentyps verdeutlicht. Fr alle anderen Typen gilt fast alles analog. Fr Integer stehen in \textit{VSPrefs} folgende Methoden zur Verfgung: @@ -92,7 +92,7 @@ Hierbei stellt \textit{key} den Variablennamen- und \textit{val} den Variablenwe \textit{VSSerializablePrefs} implementiert das Interface \textit{VSSerializable} und kann somit alle enthaltenen Daten in eine Datei abspeichern beziehungsweise laden. Auf die Serialisierung und Deserialisierung von Simulationen wird spter genauer eingegangen. -Die Klasse \textit{VSDefaultPrefs} erweitert \textit{VSSerializablePrefs} und initialisiert bei Instantiierung automatisch alle verfgbaren Simulationsvariablen mit ihren Standardwerten. Dort sind auch alle Spracheinstellungen abgelegt. Sollte jemand den Simulator in eine andere Sprache, zum Beispiel ins Englische, bersetzen wollen, so mu er lediglich diese Datei und die Protokoll-Klassen (mehr dazu spter) editieren. Die Spracheinstellungen sind nmlich in einem \textit{VSPrefs}--Objekt als versteckte String-Variablen abgespeichert. Spracheinstellungen fr Protokolle wurden in den Protokollklassen direkt angegeben, da dies mehr Komfort fr den Protokollentwickler bietet und fr jede neue Textausgabe nicht stndig \textit{VSDefaultPrefs.java} editiert werden muss. +Die Klasse \textit{VSDefaultPrefs} erweitert \textit{VSSerializablePrefs} und initialisiert bei Instantiierung automatisch alle verfgbaren Simulationsvariablen (bereits schon \"{u}ber 160) mit ihren Standardwerten. Dort sind auch alle Spracheinstellungen abgelegt. Sollte jemand den Simulator in eine andere Sprache, zum Beispiel ins Englische, bersetzen wollen, so mu er lediglich diese Datei und die Protokoll-Klassen (mehr dazu spter) editieren. Die Spracheinstellungen sind nmlich in einem \textit{VSPrefs}--Objekt als versteckte String-Variablen abgespeichert. Spracheinstellungen fr Protokolle wurden in den Protokollklassen direkt angegeben, da dies mehr Komfort fr den Protokollentwickler bietet und fr jede neue Textausgabe nicht stndig \textit{VSDefaultPrefs.java} editiert werden muss. Alle Variablen die als Prefix \textit{lang}, \textit{keyevent}, \textit{div} oder \textit{col} im Namen tragen, sind versteckte Variablen und werden in einem Editor nicht angezeigt. Im Expertenmodus sind hingegen nur Variablen die mit \textit{lang} und \textit{keyevent} beginnen versteckt. Somit lassen sich im Expertenmodus weitere Variablen vom Anwender editieren. @@ -172,9 +172,7 @@ Da \textit{VSAbstractEvent} die Klasse \textit{VSSerializablePrefs} erweitert, k \subsection{Beispielimplementierung eines Ereignisses} -Im Folgenden wird als Beispiel die Implementierung des Prozessabsturzereignisses \textit{VSProcessCrashEvent} behandelt. Da die dazugehrige Klasse keine Attribute besitzt, verbleibt hier auch die \textit{initCopy}-Methode mit leerem Rumpf. Jede Ereignisklasse muss in \textit{onInit()} mit \textit{setClassname} den eigenen Klassennamen mitteilen. In \textit{onStart()} wird das eigentliche Ereignis ausgefhrt. Hier wird obligatorisch berprft, ob der Prozess bereits abgestrzt (hier eigentlich nicht Notwendig, verbessert aber die Lesbarkeit der Logik) ist und gegebenenfalls wird der Prozess dann zum Absturz bewegt. - -Der Task-Manager berprft bereits, ob der Prozess abgestrzt ist oder nicht, d.h. ein Ereignis wird bei einem abgestrztem Prozess gar nicht erst ausgefhrt. Die einzige Ausnahme bildet ein Wiederbelebungsereignis (\text{VSProcessRecover}), welches vom Task-Manager ausgefhrt wird, auch wenn der Prozess abgestrzt ist. Mit \textit{logg} wird eine Nachricht (die ber \textit{prefs} bezogen wird) in das Loggfenster geschrieben. +Im Folgenden wird als Beispiel die Implementierung des Prozessabsturzereignisses \textit{VSProcessCrashEvent} behandelt. Da die dazugehrige Klasse keine Attribute besitzt, verbleibt hier auch die \textit{initCopy}-Methode mit leerem Rumpf. Wegen der Serializierung und Deserialisierung von Ereignisobjektten muss jede Ereignisklasse in \textit{onInit()} mit \textit{setClassname} den eigenen Klassennamen mitteilen. Bei der Deserialisierung von Ereignissen werden n\"{a}mlich Objekte anhand der Klassennamen dynamisch neu erstellt, wo der Klassenname stets bekannt sein muss. In \textit{onStart()} wird das eigentliche Ereignis ausgefhrt. Hier wird obligatorisch berprft, ob der Prozess bereits abgestrzt (hier eigentlich nicht notwendig, verbessert hier aber die Lesbarkeit) ist und gegebenenfalls wird der Prozess dann zum Absturz bewegt. \begin{code} package events.implementations; @@ -197,6 +195,7 @@ extends VSAbstractEvent implements VSCopyableEvent { } } \end{code} +Der Task-Manager berprft bereits, ob der Prozess abgestrzt ist oder nicht. Das heit, dass ein Ereignis bei einem abgestrztem Prozess gar nicht erst ausgefhrt wird. Die einzige Ausnahme bildet ein Wiederbelebungsereignis (\text{VSProcessRecover}), welches vom Task-Manager ausgefhrt wird, auch wenn der Prozess abgestrzt ist. Mit \textit{logg} wird eine Nachricht (die ber \textit{prefs} bezogen wird) in das Loggfenster geschrieben. In der Datei \textit{events/VSRegisteredEvents.java} muss in der \textit{init}-Methode fr jedes programmierbare Ereignis ein Eintrag existieren. Die \textit{init}-Methode wird einmal beim Starten des Simulators ausgefhrt: @@ -213,7 +212,7 @@ public static void init(VSPrefs prefs_) { } \end{code} -Als Resultat kann das Prozessabsturzereignis nach Belieben via GUI programmieren- und eingesetzt werden. +Als Resultat kann das Prozessabsturzereignis nach Belieben via GUI programmiert- und eingesetzt werden. \section{Zeitformate, Prozesse, Nachrichten sowie Task-Manager} @@ -228,7 +227,7 @@ Das Paket \textit{core.time} auf Abbildung \ref{fig:PackageCoreTime} stellt ledi \label{fig:PackageCoreTime} \end{figure} -Auf Abbildung \ref{fig:PackageCore} ist stark vereinfacht das Paket \textit{core} dargestellt. Fr jedes auszufhrendes Ereignis wird eine Instanz von \textit{VSTask} bentigt, welche die Ereigniseintrittszeit als Attribut abgespeichert hat sowie eine Referenz auf das Objekt des auszufhrenden Ereignisses (\textit{VSAbstractEvent}) und dem Prozessobjekt besitzt. Geplante \textit{VSTask}-Instanzen werden fr eine sptere Ausfhrung dem Task-Manager bergeben. +Auf Abbildung \ref{fig:PackageCore} ist stark vereinfacht das Paket \textit{core} dargestellt. Fr jedes auszufhrendes Ereignis wird eine Instanz von \textit{VSTask} bentigt, welche die Ereigniseintrittszeit als Attribut abgespeichert hat sowie eine Referenz auf das Objekt des auszufhrenden Ereignisses (\textit{VSAbstractEvent}) und dem Prozessobjekt (\textit{VSInternalProcess}) besitzt. Geplante \textit{VSTask}-Instanzen werden fr eine sptere Ausfhrung dem Task-Manager bergeben. Die Kapselung eines \textit{VSAbstractEvent}-Objektes in einem \textit{VSTask}-Objekt erlaubt es, dass die selbe \textit{VSAbstractEvent}-Instanz mehrmals auf einmal im Task-Manager geplant werden kann. Ohne dieser Kapselung gbe es fr jedes Ereignis lediglich nur eine einzige mgliche Eintrittszeit. Von dieser Mglichkeit wird zum Beispiel bei den Server- und Clientanfragen eines Protokollobjektes Gebrauch gemacht. Fr jedes Protokoll kann der Anwender in einer Simulation beliebig viele Anfragen programmieren, wobei fr jede Anfrage stets das selbe Protokollobjekt als Ereignis verwendet wird. @@ -241,9 +240,7 @@ Die Kapselung eines \textit{VSAbstractEvent}-Objektes in einem \textit{VSTask}-O Jede Simulation besitzt genau eine Instanz von \textit{VSTaskManager}. Eine Instanz dieser Klasse stellt den Task-Manager dar. Er verwaltet alle \textit{VSTask}-Instanzen und berprft periodisch, ob es auszufhrende Ereignisse gibt. Der Task-Manager unterscheidet zwischen globalen und lokalen Ereignissen. Hierbei werden alle globalen Ereignisse (gekapselt in einem \textit{VSTask}-Objekt) in einer Prioritts-Warteschlange abgelegt. Die Prioritts-Warteschlange stellt hierbei die korrekte Ereigniseintrittsreihenfolge sicher. Da sich die lokalen Zeiten aller beteiligten Prozesse voneinander unterscheiden knnen, muss fr jeden Prozess eine separate lokale Prioritts-Warteschlange verwendet werden, auf die jedes Prozessobjekt seine eigene Referenz hat. In den lokalen Warteschlangen sind die geplanten lokalen Ereignisse (auch gekapselt in einem \textit{VSTask}-Objekt) abgelegt. Der Task-Manager greift ber eine \textit{java.util.ArrayList} auf alle Prozessobjekte zu und kann somit auch auf alle lokalen Warteschlangen zugreifen und verwalten. -Eine Instanz von \textit{VSMessage} stellt eine Nachricht dar, die von einem Prozess verschickt wird. Fr jedes Versenden einer Nachricht wird hiervon eine Instanz gebildet, wo der Senderprozess die zu verschickende Daten ablegt. Da \textit{VSMessage} von \textit{VSPrefs} erbt, knnen zwischen zwei Prozessen beliebige Datentypen (Tabelle \ref{tb:VariablenDatentypen}) ber eine Nachricht verschickt werden. Anschlieend wird fr jeden Empfngerprozess das neues Ereignisobjekt der Klasse \textit{VSMessageReceiveEvent} angelegt, welches eine Referenz der verschickten Nachricht besitzt (Abbildung \ref{fig:Wrapping}). Danach wird ein \textit{VSTask}-Objekt instantiiert, wo die Referenz auf das Ereignisobjekt und das dazugehrige Prozessobjekt sowie die Ereigniseintrittszeit als Attribute gespeichert werden. Das \textit{VSTask}-Objekt wird dann dem Task-Manager bergeben, der das dazugehrige Ereignis ausfhrt, wenn die Ereigniseintrittszeit eingetroffen ist. Via Java-Polymorphie wird das \textit{VSMessageReceiveEvent}-Objekt in ein \textit{VSAbstractEvent} umgewandelt. - -Erwhnenswert ist auch die Klasse \textit{VSMessageStub}, welche ein \textit{VSMessage} kapselt. Ihr Zweck ist das Verstecken einiger Methoden vor dem Protokoll-API, welches fr die Erstellung eigener Protokolle dient. Der Protokoll-Entwickler soll mglichst nichts falsch machen knnen und deswegen soll den Protokoll-API ein eingeschrnkter Funktionsumfang zur Verfgung gestellt werden. Da sich \textit{VSMessageStub} im selben Paket wie \textit{VSMessage} befindet, kann \textit{VSMessageStub} auf paket-private Methoden von \textit{VSMessage} zugreifen. Protokolle hingegen werden in einem anderen Paket implementiert und haben somit keinen Zugriff auf diese paket-privaten Methoden. Zwar kann der Protokollentwickler ein eigenes \textit{VSMessageStub}-Objekt anlegen, jedoch kann er auf diese Weise besser unterscheiden auf welche Methoden er zugreifen sollte und auf welche nicht. Das Protokoll-API wird spter genauer behandelt. +Eine Instanz von \textit{VSMessage} stellt eine Nachricht dar, die von einem Prozess verschickt wird. Fr jedes Versenden einer Nachricht wird hiervon eine Instanz gebildet, wo der Senderprozess die zu verschickende Daten ablegt. Da \textit{VSMessage} von \textit{VSPrefs} erbt, knnen zwischen zwei Prozessen beliebige Datentypen (Tabelle \ref{tb:VariablenDatentypen}) ber eine Nachricht verschickt werden. Anschlieend wird fr jeden Empfngerprozess das neues Ereignisobjekt der Klasse \textit{VSMessageReceiveEvent} angelegt, welches eine Referenz der verschickten Nachricht besitzt (Abbildung \ref{fig:Wrapping}). Danach wird ein \textit{VSTask}-Objekt instantiiert, wo die Referenz auf das Ereignisobjekt und das dazugehrige Prozessobjekt sowie die Ereigniseintrittszeit als Attribute gespeichert werden. Das \textit{VSTask}-Objekt wird dann dem Task-Manager bergeben, der das dazugehrige Ereignis ausfhrt, wenn die Ereigniseintrittszeit eingetroffen ist. Via Java-Polymorphie wird hier das \textit{VSMessageReceiveEvent}-Objekt in ein \textit{VSAbstractEvent} umgewandelt. \begin{figure}[h] \centering @@ -252,6 +249,8 @@ Erw \label{fig:Wrapping} \end{figure} +Erwhnenswert ist auch die Klasse \textit{VSMessageStub}, welche ein \textit{VSMessage} kapselt. Ihr Zweck ist das Verstecken einiger Methoden vor dem Protokoll-API, welches fr die Erstellung eigener Protokolle dient. Der Protokoll-Entwickler soll mglichst nichts falsch machen knnen und deswegen soll dem Protokoll-API ein eingeschrnkter Funktionsumfang zur Verfgung gestellt werden. Da sich \textit{VSMessageStub} im selben Paket wie \textit{VSMessage} befindet, kann \textit{VSMessageStub} auf paket-private Methoden von \textit{VSMessage} zugreifen. Protokolle hingegen werden in einem anderen Paket implementiert und haben somit keinen Zugriff auf diese paket-privaten Methoden. Zwar kann der Protokollentwickler ein eigenes \textit{VSMessageStub}-Objekt anlegen, jedoch kann er auf diese Weise besser unterscheiden auf welche Methoden er zugreifen sollte und auf welche nicht. Das Protokoll-API wird spter genauer behandelt. + Der Task-Manager speichert anschlieend in der globalen Warteschlange die Nachrichtenempfangsereignisse. Die Nachricht kommt bei einem Empfngerprozess an, sobald das Ereignis fr den Empfang eintritt. Fr die korrekte Implementierung der Lamport- und Vektor-Zeitstempel wird jeder Nachricht automatisch eine Referenz auf die Lamport- sowie auf die Vektorzeit des sendenden Prozesses als Attribut beigefgt. Fr die berprfung des Protokolls wird in jeder Nachricht auch der Klassenname des jeweiligen Protokolls abgespeichert. Eine Instanz von \textit{VSInternalProcess} reprsentiert einen simulierten Prozess. Ein \textit{VSInternalProcess} stellt alle vom Simulator intern verwendeten Methoden zur Verfgung, whrend ein \textit{VSAbstractProcess} lediglich Methoden hat, die der Protokollentwickler fr die Erstellung eigener Protokolle verwenden darf. Da \textit{VSAbstractProcess} abstrakt ist und hiervon keine Instanz gebildet werden darf, muss fr einen neuen Prozesses stets ein \textit{VSInternalProcess}-Objekt erstellt werden. Via Polymorphie wird dieses Objekt nach \textit{VSAbstractProcess} umgewandelt und so dem Protokoll-API zur Verfgung gestellt. Beispielsweise darf mit \textit{getTasks()} nur vom Simulator intern auf die Prioritts-Warteschlangen zugegriffen werden, whrend man im Protokoll-API selbiges vermeiden sollte und auch gar nicht direkt mglich ist. Hierfr htte man auch ein Stub-Objekt \textit{VSProcessStub} implementieren knnen. Da aber so gut wie alle paar Millisekunden auf die Methoden von \textit{VSInternalProcess} zugegriffen wird, wurde hier aus Performancegrnden der Weg ber eine Vererbungungsstufe preferiert. @@ -300,7 +299,7 @@ Auf Abbildung \ref{fig:PackageProtocols} sind die Pakete \textit{protocols} und \label{fig:Protokollvariablen} \end{figure} -Es ist bereits bekannt, dass Protokolle im Prozesseditor editierbare Variablen haben knnen. Da \textit{VSAbstractProtocol} von \textit{VSAbstractEvent} erbt, was wiederum von \textit{VSPrefs} erbt, werden alle Protokollvariablen einfach in die Mutterklasse \textit{VSPrefs} abgelegt. Zum Beispiel kann mit \textit{super.setBoolean(``test'', true);} eine neue Protokollvariable \textit{test} mit dem Standardwert \textit{true} angelegt werden. Diese Variable erscheint dann automatisch im Prozesseditor. +Es ist bereits bekannt, dass Protokolle im Prozesseditor editierbare Variablen haben knnen. Da \textit{VSAbstractProtocol} von \textit{VSAbstractEvent} erbt, was wiederum von \textit{VSSerializablePrefs} erbt (und \textit{VSSerializablePrefs} erweitert \textit{VSPrefs}), werden alle Protokollvariablen einfach in die Mutterklasse \textit{VSPrefs} abgelegt. Zum Beispiel kann mit \textit{super.setBoolean(``test'', true);} eine neue Protokollvariable \textit{test} mit dem Standardwert \textit{true} angelegt werden. Diese Variable erscheint dann automatisch im Prozesseditor und kann vom Anwender konfiguriert werden. Da der Simulator dafr ausgelegt wurde eigene Protokolle zu implementieren, werden im Folgenden alle verfgbaren Protokoll-API-Methoden etwas ausfhrlicher als gewohnt beschrieben. Jede Protokollklasse mu die folgenden Methoden implementieren: @@ -325,9 +324,9 @@ Jede Protokollklasse bekommt folgende Methoden von \textit{VSAbstractProtocol} v \item \textit{pubic final boolean hasOnServerStart()}: Hiermit lt sich bestimmen, ob der Server- oder der Client bei dem aktuellen Protokoll die Anfragen startet. \item \textit{pubic final boolean isServer()}: Hiermit lt sich bestimmen, ob der aktuelle Prozess das aktuelle Protokoll serverseitig aktiviert hat. \item \textit{pubic final boolean isClient()}: Hiermit lt sich bestimmen, ob der aktuelle Prozess das aktuelle Protokoll clientseitig aktiviert hat. - \item \textit{pubic final void scheduleAt(long time)}: Diese Methode stellt einen Wecker, der zur angegebenen lokalen Prozesszeit eintritt. Nach Ablauf des Weckers wird, abhngig ob der aktuelle Kontext Client- oder Serverseitig ist, \textit{onClientSchedue} beziehungsweise \textit{onServerSchedule} ausgefhrt. + \item \textit{pubic final void scheduleAt(long time)}: Diese Methode stellt einen Wecker dar, der zur angegebenen lokalen Prozesszeit eintritt. Nach Ablauf des Weckers wird, abhngig ob der aktuelle Kontext client- oder serverseitig ist, \textit{onClientSchedue} beziehungsweise \textit{onServerSchedule} ausgefhrt. \item \textit{pubic final void removeSchedules()}: Entfernt alle gesetzten Wecker des aktuellen Kontextes (Server oder Client). - \item \textit{pubic final int getNumProcesses()}: Gibt die Anzahl an der Simulation beteiligten Prozesse zurck. + \item \textit{pubic final int getNumProcesses()}: Gibt die totale Anzahl an der Simulation beteiligten Prozesse zurck. \end{itemize} Bei der Implementierung von Protokollen knnen zustzlich auf die vererbten Attribute \textit{VSAbstractProcess process} und \textit{VSPrefs prefs} zugegriffen werden. Verfgbare Methoden von \textit{VSPrefs} wurden bereits behandelt. ber \textit{prefs} lassen sich alle globalen Simulationseinstellungen abrufen (zum Beispiel die Simulationsvariable die Angibt, ob Prozesse eigene Nachrichten empfangen: \textit{bool recvOwn = prefs.getBoolean(``sim.message.own.recv'')}). Folgende Prozessmethoden drfen auf \textit{process} aus dem Protokoll-API verwendet werden: @@ -347,10 +346,10 @@ Bei der Implementierung von Protokollen k \item \textit{public VSTime[] getLamportTimeArray()}: Gibt die gesamte Lamportzeitstempelhistorie des Prozesses zurck. Kann jeweils nach VSLamportTime umgewandelt werden. \item \textit{public VSTime getVectorTimeArray()}: Gibt die gesamte Vektor-Zeitstempel-Historie des Prozesses zurck. Kann jeweils nach VSVectorTime umgewandelt werden. \item \textit{public void updateVectorTime(VSVectorTime vectorTimeUpdate)}: Erneuert die Vektorzeit. Siehe Kapitel 2.6.1 wie die Vektorzeiten erneuert werden. - \item \textit{public void increaseVectorTime()}: Inkrementiert die Vektorzeit an lokalem Index um eins. + \item \textit{public void increaseVectorTime()}: Inkrementiert die Vektorzeit am lokalen Index um eins. \item \textit{public int getProcessID()}: Gibt die PID zurck. \item \textit{public void setProcessID(int processID)}: Setzt die PID. - \item \textit{public int getProcessNum()}: Gibt die Prozessnummer zurck. Dieser Wert unterscheidet sich von der PID. Die Prozessnummer gibt an, um den wievielten Prozess, beginnend bei 0, es sich handelt. + \item \textit{public int getProcessNum()}: Gibt die Prozessnummer zurck. Dieser Wert unterscheidet sich von der PID. Die Prozessnummer gibt an, um den wievielten Prozess, beginnend bei 0, es sich handelt. PIDs hingegen k\"{o}nnen alle m\"{o}glichen ganzstelligen positiven Zahlen sein. \item \textit{public int getRandomPercentage()}: Gibt einen Zufallswert zwischen \textit{0} und \textit{100} zurck. \item \textit{public boolean hasCrashed()}: Gibt \textit{true} zurck, wenn der Prozess whrend der aktuellen Simulation schon mal abgestrzt ist. \item \textit{public boolean isCrashed()}: Gibt \textit{true} zurck, wenn der Prozess aktuell abgestrzt ist. @@ -362,7 +361,7 @@ In der Regel werden in Protokollen auch Nachrichten (\textit{VSMessage}) verschi \begin{itemize} \setlength{\itemsep}{-2mm} \item \textit{public VSMessage()}: Der Standardkonstruktor fr die Erstellung einer neuen Nachricht. - \item \textit{public int getmessageID()}: Gibt die Nachrichten-ID zurck. + \item \textit{public int getMessageID()}: Gibt die Nachrichten-ID zurck. \item \textit{public boolean equals(VSMessage message)}: Hiermit lt sich berprfen, ob eine weitere Nachricht die selbe NID besitzt (wobei es sich dann um die selbe Nachricht handeln wrde). \end{itemize} @@ -384,7 +383,7 @@ Wenn Im Folgenden wird die Implementierung des zuverlssigen Multicast-Protokolls \textit{VSReliableMulticastProtocol.java} als Beispiel aufgefhrt. Die Funktionsweise des Protokolls wurde bereits in Kapitel 2.5.10 beschrieben. Client- und Serverseite werden in der selben Klasse implementiert. -Im Konstruktor mu stets angegeben werden, ob beim gegebenen Protokoll der Client oder der Server die Anfragen startet. Mit \textit{HAS\_ON\_CLIENT\_START} wird dem API mitgeteilt, dass der Client die Anfragen startet. Fr \textit{HAS\_ON\_SERVER\_START} und Serveranfragen gilt Selbiges analog. Da ein Protokoll auch ein \textit{VSAbstractEvent} ist, muss auch hier im Konstruktor mit \textit{setClassname} der Klassenname des aktuellen Protokolls angegeben werden: +Im Konstruktor mu stets angegeben werden, ob beim gegebenen Protokoll der Client oder der Server die Anfragen startet. Mit \textit{VSAbstractProtocol.HAS\_ON\_CLIENT\_START} wird dem API mitgeteilt, dass der Client die Anfragen startet. Fr \textit{VSAbstractProtocol.HAS\_ON\_SERVER\_START} und Serveranfragen gilt Selbiges analog. Da ein Protokoll auch ein \textit{VSAbstractEvent} ist, muss auch hier mit \textit{setClassname} der Klassenname des aktuellen Protokolls angegeben werden: \begin{code} package protocols.implementations; @@ -410,7 +409,9 @@ Das private Klassenattribut \textit{pids} wird f public void onClientInit() { Vector vec = new Vector(); - vec.add(1); vec.add(3); + vec.add(1); + vec.add(3); + super.initVector("pids", vec, "PIDs beteiligter Prozesse"); super.initLong("timeout", 2500, @@ -512,7 +513,7 @@ Der Server benutzt in diesem Beispiel keinen Wecker. Dementsprechend hat die Met \subsection{Erstellung eigener Protokolle (Schnelldurchlauf)} -Hier werden alle Schritte zusammengefasst, die fr die Erstellung eines eigenen Protokolls \textit{VSMyProtocol} durchgefhrt werden mssen. +Hier werden alle Schritte zusammengefasst, die fr die Erstellung eines eigenen Protokolls \textit{VSMyProtocol} durchgefhrt werden mssen. Hierf\"{u}r muss der Protokoll-Entwickler das Java-SDK sowie Apache Ant installiert- und den Quelltext des Simulators vorliegen haben. \begin{enumerate} \item VS-Simulator Quelltext beziehen und in das Verzeichnis \textit{vs/sources/protocols/implementations} wechseln. @@ -529,15 +530,15 @@ registerEvent("protocols.implementations.VSMyProtocol", \item Mit dem Befehl \textit{ant dist} das Archiv \textit{dist/lib/VS-Sim-Latest.jar} erstellen und verwenden. \end{enumerate} +Wenn eine Simulatorversion versucht eine abgespeicherte Simulation eines nicht implementierten Protokolls zu laden, dann kommt es zu Fehlern. Mit einem neuen Protokoll muss also stets auch immer ein neuer Simulator ausgeliefert werden. + \section{GUI sowie Simulationsvisualisierung} \subsection{Funktionsweise} Das Paket \textit{simulator} (vereinfacht auf Abbildung \ref{fig:PackageProtocols} dargestellt) implementiert die eigentliche graphische Benutzeroberflche des Simulators. Ausnahmen sind die Editorklassen in \textit{prefs.editors} sowie \textit{utils.VSFrame}. -Beim Starten des Simulators wird auf die Main-Methode, welche sich in \textit{VSMain} befindet, aufgerufen. Sie instantiiert ein \textit{VSDefaultPrefs}-Objekt, wo alle Standardeinstellungen des Simulators abgelegt sind. Anschlieend wird ein \textit{VSSimulatorFrame} erzeugt, welches ein Simulatorfenster (wie bereits schon auf Abbildung \ref{fig:NeuesFenster} zu sehen war) implementiert. Das Simulatorfenster erstellt fr jede neue Simulation jeweils ein Objekt von \textit{VSSimulator}. Jede Simulation hat im Simulationsfenster einen eigenen Tab. Auf Abbildung \ref{fig:NeuErstellteSimulation} wurde bereits eine neue Simulation erstellt, wo auch unten links der dazugehrige Tab mit der Beschriftung ``Simulator 1'' zu sehen ist. Jede Simulation besitzt dabei eine eigene Simulationsnummer, die bei jeder neuen Simulation um eins inkrementiert wird. Jedes \textit{VSSimulator}-Objekt greift auf \textit{VSSimulatorVisualization} zurck, was die Simulationsvisualisierung (Abbildung \ref{fig:Visualisierung}) implementiert. - -\textit{VSSimulatorVisualization} greift auf Java's Grafikbibliothek Java2D zurck und ist aus Performancegrnden mit dem Simulationsverlauf stark verzahnt \cite{Games}. Klassenattribute, dessen Wert sich nie ndert, wurden stets als \textit{final} deklariert. Attribute, die von Konfigurationen oder Einstellungen abhngig sind, die sich nur nach Konfigurationsnderung oder Vergrern beziehungsweise Verkleinern des Simulationsfensters ndern (Werte, die fr die Berechnung des Sekunden-Gatters notwendig sind), werden nur wenn es ntig ist neu berechnet. +Beim Starten des Simulators wird auf die Main-Methode, welche sich in \textit{VSMain} befindet, aufgerufen. Sie instantiiert ein \textit{VSDefaultPrefs}-Objekt, wo alle Standardeinstellungen des Simulators abgelegt sind. Anschlieend wird ein \textit{VSSimulatorFrame} erzeugt, welches ein Simulatorfenster (wie es schon auf Abbildung \ref{fig:NeuesFenster} zu sehen war) implementiert. Das Simulatorfenster erstellt fr jede neue Simulation jeweils ein Objekt von \textit{VSSimulator}. Jede Simulation hat im Simulationsfenster einen eigenen Tab. Auf Abbildung \ref{fig:NeuErstellteSimulation} wurde bereits eine neue Simulation erstellt, wo auch unten links der dazugehrige Tab mit der Beschriftung ``Simulator 1'' zu sehen ist. Jede Simulation besitzt dabei eine eigene Simulationsnummer, die bei jeder neuen Simulation um eins inkrementiert wird. Jedes \textit{VSSimulator}-Objekt greift auf \textit{VSSimulatorVisualization} zurck, was die Simulationsvisualisierung (Abbildung \ref{fig:Visualisierung}) implementiert. \begin{figure}[h] \centering @@ -546,6 +547,8 @@ Beim Starten des Simulators wird auf die Main-Methode, welche sich in \textit{VS \label{fig:PackageProtocols} \end{figure} +\textit{VSSimulatorVisualization} greift auf Java's Grafikbibliothek Java2D zurck und ist aus Performancegrnden mit dem Simulationsverlauf stark verzahnt \cite{Games}. Klassenattribute, dessen Wert sich nie ndert, wurden stets als \textit{final} deklariert. Attribute, die von Konfigurationen oder Einstellungen abhngig sind, die sich nur nach Konfigurationsnderung oder Vergrern beziehungsweise Verkleinern des Simulationsfensters ndern (Werte, die fr die Berechnung des Sekunden-Gatters notwendig sind), werden nur wenn es ntig ist neu berechnet. + Die Klasse \textit{VSMenuItemStates} wird fr die Synchronisierung des Simulationsstatusses, der Toolbar und des Simulations-Mens (beide Letztere auf Abbildung \ref{fig:Toolbar} zu sehen) verwendet. Abhngig davon kann der Benutzer bestimmte Aktionen durchfhren oder nicht (beispielsweise kann eine Simulation nur pausiert werden, wenn sie aktuell abgespielt wird). Alle hier mglichen Aktionen wurden bereits in Kapitel 2.1 im Abschnitt ``Die Toolbar'' behandelt. Die Klasse \textit{VSCreateTask} wird vom Ereigniseditor verwendet. Der Ereigniseditor (Abbildung \ref{fig:SidebarMitEreignissen}) wird in der Klasse \textit{VSSimulator} implementiert. Hinter jeder Ereignisauswahl verbirgt sich intern ein \textit{VSCreateTask}-Objekt, welches definiert wie das jeweilige Ereignis anzulegen ist. @@ -639,7 +642,7 @@ Wenn der Anwender \textit{Datei $\rightarrow$ Simulation speichern} w \begin{figure}[h] \centering - \includegraphics[width=11cm]{images/utils} + \includegraphics[width=10cm]{images/utils} \caption{Das Paket \textit{utils}} \label{fig:PackageUtils} \end{figure} @@ -647,7 +650,7 @@ Wenn der Anwender \textit{Datei $\rightarrow$ Simulation speichern} w Es wurden noch nicht die Klassen der Pakete \textit{utils} (Abbildung \ref{fig:PackageUtils}) sowie \textit{exceptions} (Abbildung \ref{fig:PackageExceptions}) vorgestellt. \textit{utils} fasst lediglich einige Helferklassen zusammen, die vom restlichen Quelltext verwendet werden. \begin{itemize} - \item \textit{VSFrame}: Alle Objekte, die ein eigenes Swing-Fenster besitzen, erben von der Klasse \textit{VSFrame}. Sie stellt sicher, dass neue Fenster an der richtigen Position der Bildflche platziert werden und dass Unterfenster (Fenster, die aus einem anderen Fenster aus geffnet wurden) automatisch mit-geschlossen werden, sobald ihre ``Erzeugerfenster'' geschlossen werden. + \item \textit{VSFrame}: Alle Objekte, die ein eigenes Swing-Fenster besitzen, erben von der Klasse \textit{VSFrame}. Sie stellt sicher, dass neue Fenster an der richtigen Position der Bildflche platziert werden und dass Unterfenster (Fenster, die aus einem anderen Fenster aus geffnet wurden) automatisch mit-geschlossen werden, sobald eines ihrer ``Erzeugerfenster'' geschlossen wird. \item \textit{VSAboutFrame}: Dieses Fenster implementiert die ``About-Anzeige'' die im Simulator ber das Datei-Men aufgerufen werden kann. \item \textit{VSInfoArea}: Ist fr die Textanzeige in \textit{VSAboutFrame} zustndig. \item \textit{VSClassLoader}: Diese Klasse wird fr die automatische Instantiierung von Ereignisobjekten bentigt, wenn dem Simulator lediglich die Klassennamen (aus \textit{events.VSRegisteredEvents}) bekannt sind. @@ -664,7 +667,7 @@ Es wurden noch nicht die Klassen der Pakete \textit{utils} (Abbildung \ref{fig:P \label{fig:PackageExceptions} \end{figure} -Im Paket \textit{exceptions} befinden sich lediglich einige Objekte die fr Ausnahmebehandlungen verwendet werden. \textit{VSNotCopyableException} wird whrend einem Kopierversuch eines nicht-kopierbaren Ereignis geworfen. \textit{VSNegatieNumberException} wird geworfen, wenn intern negative Zahlen dort auftreten wo sie es nicht sollten. Wenn ein Editorobjekt die Benutzereingabe einer Integer-Vektor-Variable nicht parsen kann, so greifen es auf \textit{VSParseIntegerVectorException} zurck. +Im Paket \textit{exceptions} befinden sich lediglich einige Klassen die fr Ausnahmebehandlungen verwendet werden. \textit{VSNotCopyableException} wird whrend einem Kopierversuch eines nicht-kopierbaren Ereignis geworfen. \textit{VSNegatieNumberException} wird geworfen, wenn negative Zahlen dort auftreten wo sie es nicht sollten. Wenn ein Editorobjekt die Benutzereingabe einer Integer-Vektor-Variable nicht parsen kann, so greifen es auf \textit{VSParseIntegerVectorException} zurck. \begin{figure} \centering @@ -677,19 +680,24 @@ Im Paket \textit{exceptions} befinden sich lediglich einige Objekte die f \section{Programmierrichtlinien} -Die Programmierrichtlinien \cite{Richtlinien} entsprechen in den meisten Fllen denen aus der Vorlesung \cite{OOS}. Die Main-Methode befindet sich in der Klasse \textit{simulator.VSMain}. +Die Programmierrichtlinien \cite{Richtlinien} entsprechen in den meisten Fllen denen aus der Vorlesung \cite{OOS}. + +Die Main-Methode befindet sich in der Klasse \textit{simulator.VSMain}. \begin{itemize} + \item Es wird kein Gebrauch vom Java-Standardpaket gemacht. Alle Klassen befinden sich somit in explizit angegebenen Paketen (zum Beispiel \textit{events.implementations}). \item Alle Klassen- und Interfacenamen beginnen mit groen Buchstaben, whrend alle Variablen-, Methoden- und Attributnamen mit kleinen Buchstaben beginnen. Namen finaler Variablen und Attribute sind komplett in Grobuchstaben gehalten. \item Alle Quelltext-Dateien besitzen einen Header, der Informationen der verwendeten Lizenz angibt. - \item Alle Quelltext-Dateien sind vollstndig mit Javadoc dokumentiert worden. + \item Alle Quelltext-Dateien werden vollstndig mit Javadoc dokumentiert. \item Der komplette Quelltext inklusive Dokumentation werden in englischer Sprache verfasst. - \item Eine Quelltext-Datei hat eine maximale Zeilenlnge von 80 Zeichen. Eine Ausnahme stellt die Klasse \textit{prefs.VSDefaultPrefs} dar, denn hier befinden sich auch lngere Texte die in Strings abgespeichert werden, wo manuelle Zeilenumbrche wenig Sinn ergeben. + \item Eine Quelltext-Datei hat eine maximale Zeilenlnge von 80 Zeichen, was der Standardbreite eines UNIX-Terminals entspricht. Eine Ausnahme stellt die Klasse \textit{prefs.VSDefaultPrefs} dar, denn hier befinden sich auch lngere Texte die in Strings abgespeichert werden, wo manuelle Zeilenumbrche wenig Sinn ergeben. \item Es werden zuerst Klassen aus der Java-Standardbibliothek importiert, bevor Klassen aus dem VS-Simulator selbst importiert werden. \item Fr die Einrckung des Quelltextes wird das Tool \textit{astyle} mit den Aufrufparametern \textit{--style=java --mode=java} verwendet. Hierbei wird eine Einrckungslnge von 4 Zeichen verwendet. - \item Namen abstrakter Klassen tragen stets das Prefix \textit{VSAbstract}. \item Namen aller Klassen und Interfaces tragen als Prefix stets \textit{VS}, was fr Verteilte Systeme steht. + \item Namen abstrakter Klassen tragen als Prefix stets \textit{VSAbstract}. \item Namen aller Protokollklassen tragen als Postfix \textit{Protocol} (zum Beispiel \textit{VSPingPongProtocol}). + \item Namen aller Ereignisklassen, die keine Protokolle implementieren, tragen als Postfix \textit{Event} (zum Beispiel \textit{VSProcessCrashEvent}). + \item Namen aller dejenigen Klassen die ein Fenster implementieren tragen als Postfix \textit{Frame} (zum Beispiel \textit{VSSimulatorFrame}). \item berall wo es Sinn ergibt werden Java-Generic-Datentypen verwendet (z.B. \textit{java.util.Vector} anstelle von \textit{java.util.Vector}. \end{itemize} diff --git a/LaTeX/diplomarbeit.pdf b/LaTeX/diplomarbeit.pdf index 42a6c51..ad6ef63 100644 --- a/LaTeX/diplomarbeit.pdf +++ b/LaTeX/diplomarbeit.pdf @@ -823,7 +823,7 @@ endobj /ProcSet [ /PDF /Text ] >> endobj 287 0 obj << -/Length 2232 +/Length 2231 /Filter /FlateDecode >> stream @@ -831,10 +831,14 @@ x կn^;2I:ڹҔ[ 0pZ!- :ubi$uȈ EyS^Ỗmq9ӃPde(|R6$4բPCZ~[jGOχ;"2T݇H58)ojV<Fl]E"*Rc3Pl$ƣ&"y0Z'i AC+qz3ƾLߗw)x S1)d+Rkf`NoD>֖yNcvl9JWBZ)Ϥ#L*$y TNWy}Z]cy^2$v/ƯzcSvǵH vQlx'$@pEc8LP0<>߿V"h,v\"0/<1팲Сh*7UfS`8pģp(<duVfQkܵ?[0ֶ´}Stq\jz,6oG'En|a]o-C<휉rkmOZ<:ǣU$i!3>">/4&r4ILiJJxE1w`}ҢrT(`RBV*,T<]u~a[>2\YI,twdlTY5K/;ǣUI@s [QMoer[ڬzEkD8xQ'm~` ~&gVQzQ͛h|3Q8{ݯ8_.ì+(Қ,t'N^J3ߣԜ +\%x +K CV-8:uE+h>p'4l^S?=P@wGK +Z׸pE$U.2/ov|=]st,ӎEh`ciT wۖ߭eC0*bPN3Yą@p +VT'!f>gPۊMHdq1U1j#GmWӛZ8_.M=,b\~˭BYR%is +tcE\c{! o'h +udG&vP&AQ\9|PUI&Mv~}pR{U.?FNu2(K|ɐ:RrSxiC*0^;UJCl22 mxݨt }1z2 Ÿiy`8vp2*7WM8S\ru/>۫8fpl 7~%\k͘:b&vՇDF|; 5n yUYLLXC5endstream endobj 286 0 obj << /Type /Page @@ -1272,8 +1276,7 @@ x '|erAPj T3V/>2꒱:v]_jY9Y)geFhlh4V3w .`S`*  My'{38$a61f&f0/Z6%~@6)&[LME]Dv L:wB:#O64de;eΦYYnﲑEs -eXySWMy;8.|iDZwV3ILھr=S%%jK*꒹CNzY< z:I0L 8J4!v4vRMhʐ55G4?4X3r߂Ǧ 4pڨ#זyV\ofyN~8RcK7hF N3>&E @&U(OQuf@:Ӛ[eSSw&aB#{Lqc/ˮ&叽Ut2J)I;o埛UH̹Åp!ŜV3g -.g=IDBjwɨKeSVm;@76 ϲ`?T?q-cq%uD=l:L.)%D T|ՈNo%S!4`HDŔ}ﭭeytZ@ZU Bl_fyendstream +eXySWMy;8.|iDZwV3ILھr=S%%jK*꒹CNzY< z:I0L 8J4!v4vRMhʐ55G4?4X3r߂Ǧ 4pڨ#זyV\ofyN~8RcK7hF N3>&E @&U(i:3f iͭQ2_)Ǎ;g0=j&eW xSx*i:u Yf$ޝQXw}MP*$BVb[ڳ^Ѥgico5;d%Ç)Hg^i0_ر: "W6tZA^J"R*GjDJS0tb>ֲT<- i]!p6/fzendstream endobj 375 0 obj << /Type /Page @@ -1656,8 +1659,8 @@ endobj 469 0 obj << /Producer (GPL Ghostscript 8.61) -/CreationDate (D:20080810233611Z00'00') -/ModDate (D:20080810233611Z00'00') +/CreationDate (D:20080811133908Z00'00') +/ModDate (D:20080811133908Z00'00') >> endobj 470 0 obj @@ -1748,8 +1751,8 @@ endobj 479 0 obj << /Producer (GPL Ghostscript 8.61) -/CreationDate (D:20080810233611Z00'00') -/ModDate (D:20080810233611Z00'00') +/CreationDate (D:20080811133908Z00'00') +/ModDate (D:20080811133908Z00'00') >> endobj 480 0 obj @@ -6650,8 +6653,8 @@ endobj 824 0 obj << /Producer (GPL Ghostscript 8.61) -/CreationDate (D:20080810233611Z00'00') -/ModDate (D:20080810233611Z00'00') +/CreationDate (D:20080811133907Z00'00') +/ModDate (D:20080811133907Z00'00') >> endobj 825 0 obj @@ -6685,27 +6688,22 @@ endobj /ProcSet [ /PDF /Text ] >> endobj 830 0 obj << -/Length 2789 -/Filter /FlateDecode ->> -stream -xZm۸_/I@MCkv/k++ ID284- -93|f8|~t$2H2 Jbew];/HHI&e}X0.KkcT\Y.9YE- e2JuPU[zbyvm/XDR)ϵemǀH$([ML,jqlMLunyeU4O*V4ZBLu]M**΄,2#2DPέĩڎe P…pXf -LDıU`[HHJ\.4!~X%27-͊EҚQ{T ;.UH͕{+[pǓ6jkZO{-U^*+j}b37;<~Ik`G5$I{ --"|y!_y<ʼ=^m9گ@3_܊Ҵ -SqńӘ9WM YbHS HD<5ڎ '5h zKBRMo9 @FoP1>l X;?}11@Ȧ:e? ߻aI|Ni  -A?hCL֧6L Ӧ(s `2[AR3E[{oJ3ygFk!C-F3['5 LX,Fyu  J6\}?V -FBe.3Jk-_Vf,v:;wDz qN:mZ YE/=[9vܺ_Ok[S ک8Xe Ds,wv\no E*0Md zP'ʔosS-u+d!i񄻓Txj#~we_F=QlX.+j|]o7`z[X Tv1v$oթŵOkxcke9 U;#wEsHU޴56 ㎘7gZUw';4R-sŃdw?C -<!ݻ/̄`dq)iߘYd%vq 6$fPl&v%٫~f xcSM8p0TNl j4oš-:k}$8ɈdIvbP{ǨQU|N8ϓ -f Q/~ ~s,fB:YrC=c AXDx"<KNljK>j>g{_(&3xR!z,=!Ԟ1z|ԏy.@NmQc/c~3C"!xBa|__AԎ3iÈVTŷ`K(gb@O*D%08F@Ms)i܀xzLJ RFLeFBs& -uMqx8ZkqkT]  շ3C lۍёӚeI [f[BuϞk 42D}>&^H$݁3,h- -c6Bxi3!&\Hwf鞂 Kcj.-KӔDd{ OG2LvM"25ndstream +/Length 2791 +/Filter /FlateDecode +>> +stream +xZ[۸~ϯK60fER(`mvvMAsledy^$ZiQC~9,n1*ZU,I"ׅ2oO:-TZS߷?x} TJ܀ 13)K{2Q< +&ʭ~v8lqj|j׶@7SdW,xͱqq&p4EOP.d4C+SM ĎƶdYFL?:@cTxjIG8kʎ1(6zZi5ì%M2ުƴֈ;U]nL[յio`ͼ,'Wjgp}ʛv&a#pLݟez#F ++zx̴yqpXA3Bї"Dt7 .<3ZQF?:sޓ)+[Ol]pmkbخE$)ڦk YFxC_*a/6a uoš-:k}$8ɈdIvbPǨQU|N8ϓ +f Q/~ ~s,fB:YrCc '#ws9z,D3,yR!,K!ԁ1|}v =Q!MfB8YzB=c \tmQc/c~33C"!xBa|__AԞ3iNPO#ZQzJ},=Nl@>7!w <̪ڗ +f Q/qCQ]=Cy/ZYR!8YPQ/XGN_tz03Y_*d='6k`1Sكqx(D>܀xzLJ RFLdFBs& +Mqx8ZkqkT] 'dhkhgضe#5[Ͷ௅&;=?0id]|L< $I5gX[tjmf9BLT=y,CߩopZB+A4BEc"s״8pסdi|ݘ.~&x +Mkzˍw+T QG5d;u(ڢEJN] yISG4|8}*Zg4#dۋӏ`$Ba-"4]yHkLy#0Cz 1bLZNu잂"qs€ #ߐbD5SEQD8Nș-x_+l2E$K9eaP7 S$e4EX]^u7TYCzSּoW&ߩLQڏ~'sP2Q;05VMCpVQau`(ۮ`l)Yz[g**w7I5ы@ nq{V2CY_)3ZUQĔ3, $}\Z)bɞrzdDe|j7,endstream endobj 829 0 obj << /Type /Page @@ -6744,30 +6742,26 @@ endobj /ProcSet [ /PDF /Text ] >> endobj 837 0 obj << -/Length 3219 -/Filter /FlateDecode ->> -stream -xڭZm~B% wIm'紎ԩɇ\PPҚ"/";٥Hԝ[o.gwR88bO,N,w7|õt]eۻ|o,a1L*d"лͯ7crq2WlԜo Kw٪-~z~ow?ܼ랯%g1yFa6l)3&ԁϖ4x_ pw?D&Rqe)o?JHFew𰣪MBuڣä1, J^>EZ>/m|ϧ:eI~Œ4U_9pes΅AomF{[YIy|g$KH2]4X /Hl=y-Ñ(bi%݊L\4*e\<4gFu.!KgӶp-{p@GK ]]o(*[#9>T7Yk>(+xN -xc=SqUzg^O"2u,5o|P?[K*hϋ Wx{]6٧ ^Vy_pV{g: @~@UXOZ)  Q׍ݽ3/q:czz[5m^ўt嫃VjbT =b`dnFfWo7(X$CS)gRb_5ϼ`CԄrkM)sK[+[T۬l/=8_= -Eì=β1#qviN&ի;s`hzi[c%&hSAaH:#=z1-RN pΙԞHX\ޙ{Wn_SoB{&W 93yZ.k8 гMc%Ԑ[ kO/24BK Hܬ^EK0l>;C1[B]vhA;Q^rT gPआ:DQDpt@pR6z;"FT^ƶXl~4& (k≊t p "gƕ< -; 3^8Da% d)p1!!39v?-D]V.4 -[ -m4m>#>` -'GR)Dnj@jڬ -93Gc{ -14'ȋo3mDiTŒ /^gRWEޡtJ+&87ERu2R0,e f{ma7pk {6>%x֣h"{<,/ - &bԕM|.))i?Fs =szW)MCrI --N[ -4<HT_ -=,d_Ec8/Q;t,\@f("U'/.nmsN3}y.F=E ->#omȫC:maכةQo [s# 9|e;ezfL%}vwK}ٺ.z101 뮣þ˟0Ut`A0a=yٛit`x|WEW:R (ہM s+m}|=tox#%p -쀶V-m׮>X 2eJBWBRJ*(ԍ m)^^2\s7R -pc2@By{t"_o9:i0KFG}Tܫ",wvwd_tKTGE`uSFo@"*]l8<@TV]¶ֳB98*71caEEvhlTǦi*pABgEΣ>f7c|B!ޠj~8SCa#O ->L;KESy⴫K(~XeZGc=[S⹧,l2ON:8W]A2%Klus+0>2nX삟 R).edqξ {-yWo {I`ucu1)LL\Ѻ NyRfѽhlDŽ,1:k#Bg0NTJP»H//z?eյgx2Uf/JpYe*|e)vaJl IIՠ7I `G$~Njzt*a[_\`I 5]銦q^CT+m" -"$6_\"'.NJn+zC}*|iB!p!}YX ܳ4l#yTvB{&S)2QK:63n=b+ppn8QQ aQdjm3 ucW^XXqa*ؖSN1i?RɌ/-=>/<^endstream +/Length 3250 +/Filter /FlateDecode +>> +stream +xڭZ[~_G s':SHAAIc^܈T|=g.Ԑ"u+FÙ3;(cDI35K2f mt_ odZӦ5bɓt.b(M?fo0Œ.~}w┤Z +&Rdh&갊Ζ,U7NgX㍟(aYg)40SoLr={f~=j-3xNհTu6KTJNӿ,4"_-Z=JǡFH*|^4HJ\{K4g5ʼ;bt +\uʯ(sdTJ1h +쁠)/Ȅl=}q ZjĖae2&H[飜뺜_d*uUO[:McPh?\؆4dn y%d +{>YB|5JE>jcYkKkqy}'KBEГyѭ}|<8]yv٪*p*v*מ#Vq F.o2,-A&,J?)lqe*K!8 6z7r-(2.+{bd_Zo¢vEEU\\8+Uc)a6ߚf3fq}Wq/}ض~Ab9b`@|U4?w;o863вTZ8@r-d*؅mG3'_xz 蔂$`{mP0Jpdx&x +Ղšr"uVx ޏvǰuS~Čr1ӡ5dv T /^ܻ#80zp^#E;KqJxuڮBx#T0~z|@ep <1X8Ÿc8`Xy燥)d.GpKBaYgr-n- +o "r>a{B#9S:@㪭7G\lΒw\BxO +^UMWE؞x@hf`XmMi.ճ]m0oHCMY7 8lkZx{Cje? +?s̫ 8Vl`ډl +4pֽ;vT,)=k@؛o>9 Wϴn= Q0;  ++¯H$=rLw~\w F_|ߖF`j Jw Zcn!v`ncF38xϐ*Cr~VT0F 9k 002ȴ +C_ {ޛgO9ȏ6_5riѦ*"fj:`'}~zw>|ʧ"z̷?6#YȜ,Q(3c:2$uxu^Qe+5_l+^Q]칻wC)$@,O57i";TKuun!^щxqcxg K)ҾR_`0Dg5ˉ0*<锝ظy,B`_R.: Ɩ-XO0W{KHU*ʖ4v hv>T^w* HS/h# V]exPK87ECk h/9UZľ99z[$dTIb8 PvYxtו)MZt/$~E) k0vM\W4tW Vh)p+yae`I~޶`~TJr|Q"5+ʡ'WE \g6E)|Uf, _,F/숟 5>!5ª/ˁ^Du +Bة<v+G[#ޚ6v> endobj 844 0 obj << -/Length 1910 +/Length 1907 /Filter /FlateDecode >> stream -xڝ]sFݿBo m^vSWI>${!@quO $!{s*1t|/RTEKXpx]%~9b__pk"c1jqY?0_\jPnsrWGZ$,3F|#"h;Z@,MS]نx`%kw\DE_䑭{8m=ƚxT[$*{Neld{?? $#ɳnWFgjr(n0_V?G*;2匧6,Ee -naom+8Lq \jGϟ~V<6/V}X"V@p%n%A]!꿿JcP\Bd4\]:=Rh}:v "vh{B8ESbd*7.1Ν$rӸȠU̸H1}hm^ O=ޝ⣴%*-,%h'Eᔵ`qrpu)~;h9nleq=8K \1"Y:`ٞ?_>+swUSɭakP`~*jU@a7+[bnDžwӶsI`D{K!{Je:Pq,OQ>L:|C%Il`I;$"y߭-^wTT;Ey:%^3G-Ntf\J>ds^,9$|&BM:(!H)f!Aw1L&:Z@b܉Yt`QlUpoB XgNYzȮ /*4c&q U7 -}:gZ޳j]K>g ¶&UF7Kh)< -+-!/|eP2)t vZGaaҋ\ڔ敬j˩ -9gpJBsŴX( .[=Iraꪒ1y: Z"bONJNB^u4dH/4oX윷<~ -HoI $KbU)f1TLB@p{iNo6AldGV| -~bl<47'eUUA \jE!63?QS nQs'M& P\pCVtBqq `x3p 噸4fnWUS5=N3+f㑯ZawX!({0@6bY5ICs} -Fwa qjzt$>>sux)IiJѳ*7$\`>v~iigo#Ft|8WeKu<3D MBs+Nendstream +xڝ]sFݿBo m^vSWI>${!@quO $!{s*1t|/RTEKXpx]%~9b__pk"c1jqY?0_\jPnsrWGZ$,3F|#"h;Z@,MS]نx`)q#[5'u5pz5XCIT<u11,@r~$~HQG0g'ZR';ݍ:ԊRQޯ3"aF G̗U6v&eO!lxr-Pe}Zٮy5qz4L-A^ +nU1o] }X$/I1W+ܬ3V 1q$*/&CPՎ?)X *ryl&_8E*;؁emt/K݂K`CƔ5<htz7uZ7"E.qI,Unn3ƹDY`*r=mvm٫