DiveJustIdeas

Chair for Computer Aided Medical Procedures & Augmented Reality
Lehrstuhl für Informatikanwendungen in der Medizin & Augmented Reality

Dive Just Ideas

Starten von Services per DIVE

Idee: DIVE soll über Buttons zum Starten von Services verfügen. Die zur Verfügung stehenden Services lassen sich über die XML-Dateien im Shared-Verzeichnis bestimmen. Alles Services mit der Eigenschaft startOnDemand=true kommen hierfür in Frage. Bei diesem Ansatz treten folgende Probleme auf:
Problem 1: Services lassen sich nur auf localhost starten.
Lösungs-Vorschlag: Nicht DIVE sondern der Service-Manager startet die Services. Er implementiert dazu eine Ability. Der Startbefehl oder auch Stoppbefehl wird über ein Event gegeben. Das hat folgende Vorteile:

  • Der Servicemanager hat die XML-Dateien bereits geparst
  • Da er auf (theoretisch ) allen Rechnern läuft, lassen sich so, zentral von DIVE aus alle verfügbaren Services für jeden verfügbaren Rechner starten
  • DIVE kann daher alle benötigten Services für eine Applikation speichern, die dann durch einen einzigen Befehl ausgeführt werden kann. Dies spart beim Testen von Applicationen viel Zeit. An dieser Stelle ließe sich auch die Konfiguration der einzelnen Services speichern, in einer Art einfacher Scriptsprache oder XML zum Beispiel.
  • Letztlich könnten auch andere Services dieses Interface nutzen.
Kommentar dazu: (AsaMacWilliams - 10 Nov 2003)
  • Prinzipiell eine sehr gute Idee!
  • Anstatt der Events könnte man auch den Services eine Spezielle "start mich"-Ability verpassen, dass dann von DIVE gebraucht wird, genauso wie im Moment die Events debuggt werden. Sobald die Ability gebraucht wird, wird der Service automatisch gestartet. Diese Ability kann dann das Null-Protokoll verwenden, da sie nicht wirklich kommunizieren muss. So z.B. geschehen bei ARCHIE; FranzStrasser kennt die details. smile

Aus dieser Lösung erwächst Problem2, welches sich jedoch leicht lösen lässt.
Problem 2: Der Debug-Output der Services geht verloren.
Lösungs-Vorschlag: Der Servicemanager startet den Service und leitet den stdout und stderr an einen TCP-Sender um, welcher die Daten an einen Debugserver auf dem gewünschten Rechner schickt. Der Debugserver nimmt in einfachster Ausführung nur Verbindungen auf einem bestimmten Port an und zeigt die empfangenen Daten für jede Verbindung in einem eigenen Fenster an. Das hat folgende Vorteile:

  • Nicht nur lassen sich Remote-Services zentral von einem Rechner mit DIVE aus starten, sondern auch der Debug-Output wird zentral angezeigt. (Wenn ich mich recht erinnere, äußerte Gudrun diesen Wunsch auf dem Coordinationmeeting am 26.09)
  • Der Debug-Server ermöglicht es nun auch die Debugdaten on-the-fly weiterzuverarbeiten. Man könnte zum Beispiel die Daten Filtern oder nach Regeln einfärben. Letztlich ließen sich die Daten auch aufzeichnen.
  • Bestehende Services müssen nicht verändert werden.
Kommentar dazu: (AsaMacWilliams - 10 Nov 2003)
  • Gute Idee, würde vieles vereinfachen.
  • Vielleicht sollte man die Debug-Meldungen auch als Events verschicken, d.h. Services hätten eine Debugmeldung-Ability? Implementierungsideen dazu:
    • die DefaultSvcLoad - Klasse im Service Manager, die die Services automatisch startet, fügt dem Service eine neue Ability namens trace vom Typ StringData hinzu.
    • Dann fängt sie alle Ausgaben des Services (per Unix Pipes) ab; dazu gibt es übrigens in DIVE eine Hilfsklasse, die dot anspricht.
    • Jede Zeile wird dann als Event verschickt.
    • Der Entwickler kann dann in DIVE auf "View Events" klicken, um die Meldungen zu sehen.
    • Dazu sollte man evtl. einen zweiten "View Events"-Dialog einführen, der eine Liste von Events durchscrollt, anstatt immer nur das letzte Event anzuzeigen.
  • Andererseits: vielleicht ist es gerade sinnvoll, eine möglichst einfache Lösung wie TCP zu verwenden.
    • Im Moment werden sowieso schon die Ausgaben in eine Datei in /tmp mitgeloggt; ein TCP-Sender-Progrämmchen dazwischenzuhängen wäre ziemlich einfach.
  • Es gibt natürlich auch Log4J und Log4Cpp; ChristianSandor kennt sich hier aus. Problem: man hat verschiedene Bibliotheken für verschiedene Sprachen.

Servicebeschreibungen verändern per DIVE

Idee: Die Servicebeschreibungen lassen sich in DIVE zur Laufzeit verändern.
Die Veränderungen lassen sich verhältnismäßig einfach über das Interface des Servicemanagers verändern. Will man die Konfiguration Abspeichern müsste der entsprechende Servicemanager nur die Konfiguration zurück in XML verwandeln und die alte XML-Datei überschreiben. Dabei tritt jedoch ein Problem auf!
Problem: Will man zwei unterschiedliche Servicebeschreibungen mit ein und derselben Implementation verwenden, ist dies nicht möglich. Zum Beispiel ist es sinnvoll den Manualtracker zweimal mit unterschiedlicher Konfiguration zu starten. Einmal soll die Ability PoseData das Prädikat Thing-Type=Viewpoint haben und ein zweites Mal einen anderen Thing-Type. Im Moment ist dieses spezielle Problem durch eine GUI gelöst, die den Thing-Type wählen lässt. Das ist meiner Meinung nach eher ein Workaround als eine Lösung denn 1. die Eingabe in die GUI lässt sich nicht durch DIVE steuern und 2. die Eingabe lässt sich auch nicht Automatisieren, was im Testbetrieb Zeit kostet. Meiner Ansicht nach liegt das Problem in der Art der Service Registrierung begründet: Der Servicename ist meist in der Implemetation fest codiert. So ist es nicht möglich eine Executable für mehrere Service Beschreibungen zu verwenden. Vielleicht ist es möglich standardmäßig den Servicenamen als Parameter zu übergeben???

Kommentar dazu: (AsaMacWilliams - 10 Nov 2003)

  • Dieses Problem in der Service-Registrierung ist schon (zumindest teilweise) durch Template Services gelöst. Wenn es von einem Template-Service verschiedene Ausprägungen gibt (die automatisch über *-Attribute generiert worden sind), dann wird der Service beim Registrieren mit einer speziellen Ausprägung verbunden. Damit gäbe es dann die Services ManualTracker1, ManualTracker2 usw.
  • Wenn aber die verschiedenen Ausprägungen von Hand erzeugt worden sind (also vom Entwickler mit verschiedenen XML-Datein bzw. DIVE++), dann ist dies tatsächlich ein Problem. Man könnte in die CorbaInit?-Helper-Klassen einen Parameter -DserviceName=MyServiceName einbauen, analog zu -DserviceManager=myhost. Diesen Parameter könnte der Service Manager auch beim automatischen Starten des Services angeben.
  • Eine andere Methode wäre, die Template-Instanziierung, also das Klonen von Template-Services durch den Service Manager, von aussen steuerbar zu machen; dann kann der Service Manager den neu gestarteten Service mit dem frisch erzeugten Klon verbinden.
  • Zum Problem "wie speichere ich die Konfiguration meiner Dienste": man verwendet spezielle Konfigurationsdienste, in denen die einzelnen Services (z.B. Filter) ihre Daten speichern. Sowas gab's schon bei ProjectArchie, siehe auch ToennisDADatamanagement. Zu jeder unterschiedlichen Konfiguration gibt es einen Konfigurationsdienst, oder jeweils eine Ability eines großen Konfigurationsdienstes. Dann werden verschiedene mögliche Templates von dem Filter-Service erzeugt (siehe dieses Paper). Der Benutzer muss nun nur noch angeben, welche er starten will. -- Main.Main.AsaMacWilliams - 13 Nov 2003
  • Zum Problem "wie speichere ich die Verbindungsstruktur meiner Dienste": evtl. kann man dem Service Manager auch beibringen, dass er neben der Beschreibung des Templates (MyFilter.xml) auch Beschreibungen konkreter Klone akzeptiert (MyFilter7.xml). Oder: man verwendet sich ver'ndernde Attribute, wie im obigen Paper. -- Main.Main.AsaMacWilliams - 13 Nov 2003

TIP Konkreter Umsetzungsplan unter DivePlanedExtensions

Komponentenkonzept für Services in Java basierend auf der Servicebeschreibung in XML

Die Redundanz im Code von Services ist sehr hoch. Copy-and-Paste Programmierung ist eine Fehlerquelle und erschwert die Wartung. Daher folgende Idee: Die Services teilen sich ganz natürlich in folgende Module:

  • ein oder mehrere Needs
  • ein oder mehrere Abilitys
  • manchmal einen Programmteil, der in bestimmten Intervallen ausgeführt wird.
  • Einen Programmteil, der die Serviceanmeldung und Init erledigt und das Sessioninterface implementiert. Dieser Teil ist praktisch für jeden Service gleich. Er bildet daher die Main-Klasse.
Dieser Main-Klasse wird nun die XML-Servicebeschreibung übergeben. In ihr wird festgelegt welche Klassen die Needs und welche die Abilies implementieren. Diese werden per Classloader geladen und instanziiert. Sie lassen sich als Hashtable organisieren, wobei ihre Namen in der XML-Beschreibung die Schlüssel bilden. Jede Instanz bekommt im Konstruktor einen Zeiger auf die Main-Klasse übergeben wodurch ein Zugriff auf den Hashtable ermöglicht wird. Vorteile:
  • neue Services erfordern kaum schreibaufwand (eventuell reicht schon eine Änderung im XML aus)
  • keine Redundanz (sowohl in einem Service als auch Serviceübergreifend, da die Mainclass immer die gleiche ist)
  • hohe Wiederverwertbarkeit (einzelne Needs und Abilities können in mehreren Services verwendet werden, zB. ein Pose-Sender)
  • Die von Chris angesprochenen Filterservices ließen sich damit sicher schnell und pflegeleicht umsetzen.

Wenn man das ganze nun weiterdenkt, könnte man ja die Services aus DIVE heraus erzeugen. Man klickt "neuer Service", gibt die Needs und Abilities ein und kann dann die Implementierenden Klassen aus einem File-Dialog holen. Existiert noch keine passende Klassen, klick man auf "erzeugen" und DIVE legt schon mal ein Javafile mit "class ??? implements DwarfServiceAbility{};" an.

Kommentar dazu: (AsaMacWilliams - 10 Nov 2003)

  • Eine generelle Lösung für solche Basisklassen ist sehr schwierig...
  • Man muss darauf achten, dass man Services nicht eine bestimmte Klassenstruktur aufzwingt, die vielleicht nicht jeder verwenden will - oder kann, etwa weil der Kontrollfluss schon von aussen vorgegeben ist.
  • Ausserdem muss berücksichtigt werden, dass solche Lösungen soweit wie möglich in allen Programmiersprachen (Java, C++, Python) umsetzbar sind. Das Classloader-Konzept geht z.B. nicht in C++; Lösungen, die Templates verwenden, gehen nicht in Java.
  • MartinWagner hat sich mit einem allgemeinen Service für C++ beschäftigt; der macht etwas ganz ähnliches zu diesem Vorschlag.
  • Man muss übrigens nicht die XML-Beschreibung selbst parsen; das macht schon der Service Manager. Man muss also einfach in der ServiceDescription nachschauen.

Dive untereinander verschalten

Sobald mehrere Services laufen wird DIVE schnell extrem langsam, das liegt wohl an den Servicemanagern die die Anfragen nicht zeitnah behandeln, da aber meistens mindestens soviele DIVEs wie Service Manager offen sind sollte es doch einen Performance gewinn bringen, aktuelle Informationen zuerst bei anderen DIVEs abzufragen und dann je nach Aktualisierungsstand vielleicht gar keine Abfrage auf die Servicemanager mehr machen zu müssen.

Kommentar dazu: (FabianSturm? - 21 Jan 2004) Ich hab die Kommunikation zwischen DIVE und Servicemanager nicht gelesen, aber wenn ich das hier richtig verstehe muss jeder DIVE von sich aus eine Anfrage an den Servicemanager machen? Warum nicht umgekehrt? In dem Moment wo ein DIVE existiert sendet der Servicemanager periodisch Events raus mit den Update Daten. Wer will kann sich nun zu diesem Channel subscriben was keinen weiteren Overhead fuer den Servicemanager bedeuten wuerde.

-- MarkusGeipel - 09 Nov 2003


Edit | Attach | Refresh | Diffs | More | Revision r1.15 - 15 Jul 2005 - 13:20 - MarcusToennis

Lehrstuhl für Computer Aided Medical Procedures & Augmented Reality    rss.gif