Diplomarbeit DIPL – WIRTSCH – INF Integration eines relationalen Datenbanksystems als Nachrichtenspeicher in das Demaq-Ausführungssystem vorgelegt bei Prof. Dr. Carl-Christian Kanne Juniorprofessur für Praktische Informatik (Informationssysteme) Universität Mannheim von Dennis Knochenwefel Mannheim, im August 2008 INHALTSVERZEICHNIS INHALTSVERZEICHNIS Inhaltsverzeichnis Abkürzungsverzeichnis vii Abbildungsverzeichnis viii Tabellenverzeichnis x 1 Einleitung 1 1.1 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Gliederung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 Darstellungskonventionen . . . . . . . . . . . . . . . . . . . . . . . 3 2 Grundlagen 2.1 2.2 2.3 4 Demaq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1.1 Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1.2 Bestandteile . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1.2.1 Die Sprache Demaq . . . . . . . . . . . . . . . . 5 2.1.2.2 Das Demaq-Ausführungssystem . . . . . . . . . . 5 Natix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.2.1 Konzepte . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.2.1.1 Fragmente . . . . . . . . . . . . . . . . . . . . . . 7 2.2.1.2 Requests . . . . . . . . . . . . . . . . . . . . . . 8 2.2.1.3 Views . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2.1.4 XQuery-Auswertung . . . . . . . . . . . . . . . . 9 2.2.2 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.3 Einschränkungen . . . . . . . . . . . . . . . . . . . . . . . 10 DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.3.1 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.3.2 Einschränkungen . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.2.1 Allgemeine Einschränkungen . . . . . . . . . . . 12 2.3.2.2 XQuery Einschränkungen . . . . . . . . . . . . . 13 3 Problemstellung 14 3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.2 Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 i INHALTSVERZEICHNIS 3.3 3.4 INHALTSVERZEICHNIS Anforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.3.1 Korrektheit . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.3.2 Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . 17 3.3.3 Leistungsverhalten . . . . . . . . . . . . . . . . . . . . . . 17 Herausforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.4.1 Überprüfung der Korrektheit . . . . . . . . . . . . . . . . 18 3.4.2 Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . 18 3.4.3 Modellierung der Datenstrukturen und Features . . . . . . 19 3.4.4 Physische Optimierung des Leistungsverhaltens . . . . . . 20 3.4.4.1 Parallelisierung . . . . . . . . . . . . . . . . . . . 20 3.4.4.2 Nebenläufigkeit . . . . . . . . . . . . . . . . . . . 20 3.4.4.3 Anfrageoptimierung . . . . . . . . . . . . . . . . 21 3.4.4.4 Indizes . . . . . . . . . . . . . . . . . . . . . . . . 21 3.4.5 Untersuchung des Leistungsverhaltens . . . . . . . . . . . 4 Architektur 4.1 4.2 23 Demaq System-Varianten . . . . . . . . . . . . . . . . . . . . . . . 23 4.1.1 Übersicht der System-Varianten . . . . . . . . . . . . . . . 23 4.1.2 Demaq mit NATIX und Saxon . . . . . . . . . . . . . . . 25 4.1.3 Demaq mit der DB2 und Saxon . . . . . . . . . . . . . . . 26 4.1.4 Demaq mit der DB2 . . . . . . . . . . . . . . . . . . . . . 29 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.2.1 DB2-Datenbankmodul: Konzeptuelles Design . . . . . . . . 32 4.2.2 Schnittstelle zum Nachrichtenspeicher . . . . . . . . . . . . 32 4.2.3 Schnittstelle zur Regelauswertung: Saxon . . . . . . . . . 34 4.2.4 DB2-Fassade . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.2.5 DB2-Datenbankmodul: Varianten der Abbildung von Slices 37 5 Feinentwurf 5.1 21 39 Demaq mit der DB2 und Saxon . . . . . . . . . . . . . . . . . . . 39 5.1.1 Überführung des ER-Diagramms in ein logisches Schema . 40 5.1.1.1 Regeln . . . . . . . . . . . . . . . . . . . . . . . . 40 5.1.1.2 Warteschlangen . . . . . . . . . . . . . . . . . . . 40 5.1.1.3 Nachrichten . . . . . . . . . . . . . . . . . . . . . 41 5.1.1.4 Eigenschaften . . . . . . . . . . . . . . . . . . . . 42 ii INHALTSVERZEICHNIS 5.1.2 INHALTSVERZEICHNIS 5.1.1.5 Slicings . . . . . . . . . . . . . . . . . . . . . . . 42 5.1.1.6 Schemata . . . . . . . . . . . . . . . . . . . . . . 42 5.1.1.7 Beziehung Warteschlangen-Regel . . . . . . . . . 42 5.1.1.8 Beziehung Slicing-Regeln 43 5.1.1.9 Beziehung . . . . . . . . . . . . . Warteschlange zu Antwort- Warteschlange . . . . . . . . . . . . . . . . . . . 43 5.1.1.10 Beziehung -Warteschlange zu Regeln . . . . . . . 44 5.1.1.11 Beziehung Schema zu Warteschlangen . . . . . . 44 5.1.1.12 Beziehung Nachricht-Warteschlange . . . . . . . . 44 5.1.1.13 Beziehung Eigenschaftswerte-Nachricht . . . . . . 44 5.1.1.14 Beziehung Eigenschaften-Warteschlangen . . . . . 45 5.1.1.15 Beziehung Eigenschaft-Slicing . . . . . . . . . . . 46 Verfeinerung der DDL . . . . . . . . . . . . . . . . . . . . 46 5.1.2.1 Zusammenfassung Regeln und Error-Queues . . . 46 5.1.2.2 Zusammenfassung Warteschlangen mit der Queue-Resonsequeue-Beziehung . . . . . . . . . . 5.1.2.3 Zusammenfassung Nachrichten und NachrichtWarteschlange-Beziehung . . . . . . . . . . . . . 5.1.2.4 5.1.2.5 5.1.3 5.1.4 47 47 Zusammenfassung von Slicings und SlicingProperty-Beziehung . . . . . . . . . . . . . . . . 48 Wegfall Schemata und Schema-Queue-Beziehung 48 Weitere Anpassungen des logischen Designs . . . . . . . . 48 5.1.3.1 Anpassungen an das Demaq-Ausführungssystems 48 5.1.3.2 Anpassungen an DB2 . . . . . . . . . . . . . . . 49 Varianten der Warteschlangenabbildung . . . . . . . . . . 49 5.1.4.1 Variante 1: Einfache Relation . . . . . . . . . . . 51 5.1.4.2 Variante 2: Mehrere Einfache Relationen . . . . . 55 5.1.4.3 Variante 3: Paarweise Relationen . . . . . . . . . 58 5.1.4.4 Variante 4: Einfache Relation mit Pointern . . . . 63 5.1.4.5 Variante 5: Einfache Relation mit Verkettung . . 65 5.1.4.6 Variante 6: Trennung von Daten und Statusinformationen . . . . . . . . . . . . . . . . . . . . . . 5.1.4.7 68 Variante 7: Einfache Relation mit redundanter Queue im Hauptspeicher . . . . . . . . . . . . . . iii 71 INHALTSVERZEICHNIS 5.1.4.8 Tabellarische Übersicht der Varianten . . . . . . 75 DB2-Datenbankmodul: Varianten der Abbildung von Slices 76 5.1.5.1 Slicing Zugriffe über einen Index . . . . . . . . . 76 5.1.5.2 Slicings mit Materialized Views . . . . . . . . . . 77 5.1.5.3 Slicings als eigene Tabellen . . . . . . . . . . . . 78 Änderung des Demaq-Codes . . . . . . . . . . . . . . . . . 79 5.1.6.1 Umstrukturierungen . . . . . . . . . . . . . . . . 80 5.1.6.2 Neue C++ Klassen . . . . . . . . . . . . . . . . . 81 Erweiterung des NATIX-Codes . . . . . . . . . . . . . . . 82 5.1.7.1 Umstrukturierungen . . . . . . . . . . . . . . . . 82 5.1.7.2 Änderungen des bestehenden Codes . . . . . . . 83 5.1.7.3 Neue C++ Klassen . . . . . . . . . . . . . . . . . 83 DB2-Fassade . . . . . . . . . . . . . . . . . . . . . . . . . 85 5.1.8.1 Kommunikationstechnik . . . . . . . . . . . . . . 86 5.1.8.2 Implementierung . . . . . . . . . . . . . . . . . . 86 5.1.8.3 Neue C++ Klassen . . . . . . . . . . . . . . . . . 87 Demaq mit der DB2 . . . . . . . . . . . . . . . . . . . . . . . . . 88 5.2.1 Änderung des Demaq-Kerns . . . . . . . . . . . . . . . . . 88 5.2.1.1 Umstrukturierungen . . . . . . . . . . . . . . . . 88 5.2.1.2 Änderungen des bestehenden Codes . . . . . . . 89 5.2.1.3 Neue C++ Schnittstellen . . . . . . . . . . . . . 90 Erweiterung der DB2-Fassade . . . . . . . . . . . . . . . . 91 5.1.5 5.1.6 5.1.7 5.1.8 5.2 INHALTSVERZEICHNIS 5.2.2 6 Implementierung 6.1 6.2 94 Optimierung der DB2 als Nachrichtenspeicher . . . . . . . . . . . 94 6.1.1 Indizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 6.1.2 Datenblöcke für große XML-Nachrichten . . . . . . . . . . 95 6.1.3 Parallelisierung von Lese- und Schreibzugriffen . . . . . . . 97 6.1.4 Nebenläufige Verarbeitung von Nachrichten . . . . . . . . 99 Optimierung der Regelauswertung mit der DB2 . . . . . . . . . . 100 6.2.1 Vermeidung von Serialisier- und Parsingvorgängen . . . . . 100 6.2.2 Implementierung der Regelauswertung mit DB2 . . . . . . 103 6.2.2.1 Regelauswertung mit Stored Procedures . . . . . 104 iv INHALTSVERZEICHNIS 6.2.2.2 INHALTSVERZEICHNIS Regelauswertung durch ein atomares SQLStatement . . . . . . . . . . . . . . . . . . . . . . 107 6.2.3 Steuerung der Weiterverarbeitung von Nachrichten mit Triggern . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 7 Evaluation 7.1 7.2 111 Qualitative Evaluation . . . . . . . . . . . . . . . . . . . . . . . . 111 7.1.1 Korrektheit . . . . . . . . . . . . . . . . . . . . . . . . . . 111 7.1.2 Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . 112 7.1.3 Leistungsverhalten . . . . . . . . . . . . . . . . . . . . . . 112 Quantitative Evaluation . . . . . . . . . . . . . . . . . . . . . . . 113 7.2.1 Erfüllung der Anforderungen für formale Experimente . . . 114 7.2.2 Konzeption der Experimente . . . . . . . . . . . . . . . . . 115 7.2.3 7.2.2.1 Ziele des Experiments Warteschlange . . . . . . . 115 7.2.2.2 Ziele des Experiments Regelauswertung . . . . . 116 Testanwendungen . . . . . . . . . . . . . . . . . . . . . . . 116 7.2.3.1 Testanwendung 1: Client/Server-Simulation . . . 118 7.2.3.2 Testanwendung 2: Client/Server-Simulation mit qs:queue() . . . . . . . . . . . . . . . . . . . . . . 119 7.2.4 7.2.5 7.2.3.3 Testanwendung 3: Prozesskette mit Überkreuzung 119 7.2.3.4 Testanwendung 4: Prozess-Simulation Split/Join . 121 Design des Experiments Warteschlange . . . . . . . . . . . 122 7.2.4.1 Unabhängige Variable . . . . . . . . . . . . . . . 123 7.2.4.2 Abhängige Variablen . . . . . . . . . . . . . . . . 123 7.2.4.3 Andere konstante Faktoren . . . . . . . . . . . . 124 7.2.4.4 Hypothesen . . . . . . . . . . . . . . . . . . . . . 125 7.2.4.5 Beschränkungen . . . . . . . . . . . . . . . . . . 125 Design des Experiments Regelauswertung . . . . . . . . . . 125 7.2.5.1 Unabhängige Variable . . . . . . . . . . . . . . . 126 7.2.5.2 Abhängige Variablen . . . . . . . . . . . . . . . . 126 7.2.5.3 Andere konstante Faktoren . . . . . . . . . . . . 126 7.2.5.4 Hypothese . . . . . . . . . . . . . . . . . . . . . . 126 7.2.6 Beschränkungen . . . . . . . . . . . . . . . . . . . . . . . . 126 7.2.7 Vorbereitung der Experimente . . . . . . . . . . . . . . . . 127 v INHALTSVERZEICHNIS INHALTSVERZEICHNIS 7.2.8 Durchführung der Experimente . . . . . . . . . . . . . . . 127 7.2.9 Analyse der Ergebnisse . . . . . . . . . . . . . . . . . . . . 128 7.2.9.1 Ergebnisse des Experiments Warteschlange . . . . 129 7.2.9.2 Ergebnisse des Experiments Regelauswertung . . 129 7.2.10 Zusammenfassung der Ergebnisse . . . . . . . . . . . . . . 130 8 Zusammenfassung und Ausblick 137 8.1 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 8.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 8.2.1 Konvertierungen vermeiden . . . . . . . . . . . . . . . . . 139 8.2.2 Auf Properties und Slicekeys beliebiger Nachrichten zugreifen139 8.2.3 Nebenläufigkeit . . . . . . . . . . . . . . . . . . . . . . . . 139 8.2.4 Untersuchung der Slicing-Abbildungen . . . . . . . . . . . 140 8.2.5 Parallelisierung der Aktionen . . . . . . . . . . . . . . . . 140 8.2.6 Abgleich der Verbindungen der DB2-Fassade mit den Processing-Threads . . . . . . . . . . . . . . . . . . . . . . 140 8.2.7 Nachrichten-Validierung . . . . . . . . . . . . . . . . . . . 140 8.2.8 Rewrites für die DB2 . . . . . . . . . . . . . . . . . . . . 141 Literaturverzeichnis 142 A Anhang 150 A.1 Quellcodes der Tests . . . . . . . . . . . . . . . . . . . . . . . . . 150 A.1.1 Testfälle Entwicklungsphase / Korrektheitsüberprüfung . . 150 A.1.1.1 demaqTestcase1.dql . . . . . . . . . . . . . . . . 150 A.1.1.2 demaqTestcase2.dql . . . . . . . . . . . . . . . . 150 A.1.1.3 demaqTestcase3.dql . . . . . . . . . . . . . . . . 151 A.1.1.4 demaqTestcase4.dql . . . . . . . . . . . . . . . . 151 A.1.1.5 demaqTestcase5.dql . . . . . . . . . . . . . . . . 152 A.1.2 Testanwendungen Experimente . . . . . . . . . . . . . . . 154 A.1.2.1 test1ClientServer.dql . . . . . . . . . . . . . . . . 154 A.1.2.2 test2ClientServer2.dql . . . . . . . . . . . . . . . 160 A.1.2.3 test3ProcessChain.dql . . . . . . . . . . . . . . . 166 A.1.2.4 test4SplitJoin.dql . . . . . . . . . . . . . . . . . . 172 vi ABKÜRZUNGSVERZEICHNIS Abkürzungsverzeichnis ACID Atomicity, Concurrency, Integrity, Durability AST Abstract Syntax Tree CLI Das Call Level Interface der DB2 CLOB Character Large Object (siehe auch LOB) DB2 IBM DB2 Universal Database DBMS Datenbank-Management-System DDL SQL-Data Definition Language DOM Document Object Model DQL Demaq Querying Language: Besteht aus der QDL und der QRL ER Entity-Relationship ERM Entity-Relationship-Model FIFO First-In-First-Out I/O Input/Output JDBC Java Database Connectivity LOB Large Objects in relationalen Datenbanken (bis 2GB [35]) MDC Multidimensional Clustering ODBC Open Database Connectivity (Microsoft Standard) OTL Oracle, Odbc and DB2-CLI Template Library [32] QDL Queue Definition Language QRL Queue Rule Language REST Representational State Transfer RPM Revolutions Per Minute RSS Really Simple Syndication SOA Service Oriented Architecture SOAP Simple Object Access Protocol UDF User Defined Function UML Unified Modeling Language URI Uniform Resource Identifier vii ABBILDUNGSVERZEICHNIS Abbildungsverzeichnis 1 Varianten des Demaq-Systems . . . . . . . . . . . . . . . . . . . . 2 Varianten des Demaq-Systems: Komponenten und deren individu- 19 elle Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3 Schematischer Kontrollfluss im Demaq-System . . . . . . . . . . . 25 4 Bisheriges Demaq-System: Detailansicht der wichtigsten Module in den Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . 5 Demaq-System mit der DB2 und Saxon : Detailansicht der wichtigsten Module in den Komponenten . . . . . . . . . . . . . . . . 6 28 Demaq-System mit der DB2 : Detailansicht der wichtigsten Module in den Komponenten . . . . . . . . . . . . . . . . . . . . . . . . . 7 27 30 Detailansicht der Vererbungshierarchien im Kontext der Kontrollflüsse im Demaq-Kern . . . . . . . . . . . . . . . . . . . . . . . . 31 8 Das ER-Modell vom Demaq-System . . . . . . . . . . . . . . . . . 33 9 Abhängigkeiten von Komponenten und Modulen im Demaq-System 37 10 Varianten der Implementierung einer Warteschlange [9] . . . . . . 50 11 Warteschlangen als einfache Relation . . . . . . . . . . . . . . . . 52 12 Warteschlangen als einfache Relation (optimiert) . . . . . . . . . . 54 13 Warteschlangen als mehrere einzelne Relationen . . . . . . . . . . 55 14 Warteschlangen als mehrere einzelne Relationen (optimiert) . . . 57 15 enqueue und dequeue auf paarweisen Relationen . . . . . . . . . 58 16 Warteschlange als paarweise Relationen . . . . . . . . . . . . . . . 60 17 Warteschlange als paarweise Relationen (optimiert) . . . . . . . . 61 18 Warteschlange als paarweise Relationen blockiert vor der Rotation 61 19 Warteschlangen als einfache Relation mit Pointern . . . . . . . . 62 20 Warteschlangen als einfache Relation mit Pointern (optimiert) . . 64 21 Warteschlangen als einfache Relation mit Verkettung . . . . . . . 66 22 Warteschlange mit Statusinformationen in Form einer extra Tabelle 69 viii ABBILDUNGSVERZEICHNIS 23 ABBILDUNGSVERZEICHNIS Warteschlange mit Statusinformationen in Form einer extra Tabelle (optimiert) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 24 Warteschlange mit Informationsverwaltung im Hauptspeicher . . . 73 25 Warteschlange mit Informationsverwaltung im Hauptspeicher (optimiert) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 26 Räumlich getrennt gespeicherte Daten auf der Festplatte . . . . . 96 27 Automatische Speicherverwaltung über mehrere Festplatten . . . 99 28 Serialisierungs- und Parsing-Vorgänge im Demaq-System mit der DB2 und Saxon 29 . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Serialisierungs- und Parsing-Vorgänge im Demaq-System mit der DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 30 Serialisierungs- und Parsing-Vorgänge im Demaq-System mit der DB2 (optimiert) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 31 Übersicht der Testanwendungen für die Experimente und deren benutzte Demaq-Features . . . . . . . . . . . . . . . . . . . . . . 116 32 Testanwendung 1 und 2: Simulation mit einem Server und mehreren Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 33 Testanwendung 3: Prozesskette mit Überkreuzung . . . . . . . . . 119 34 Testanwendung 4: Prozess-Simulation Split/Join . . . . . . . . . . 121 ix TABELLENVERZEICHNIS Tabellenverzeichnis 1 Matrix der unterstützten Views für Fragment Types (Adaptiert von [45]) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2 Erweiterung der Fragment/View -Matrix von Seite 8 . . . . . . . . 35 3 Übersicht der Varianten der Warteschlangenabbildung in einem relationalen DBMS . . . . . . . . . . . . . . . . . . . . . . . . . . 76 4 Rewrites für Demaq-spezifische Funktionen . . . . . . . . . . . . . 90 5 Eigenschaften von Experimenten 6 Varianten der Testanwendungen 1 und 2 . . . . . . . . . . . . . . 118 7 Varianten der Testanwendung 3 . . . . . . . . . . . . . . . . . . . 120 8 Varianten der Testanwendung 4 . . . . . . . . . . . . . . . . . . . 122 9 Testergebnisse Teilexperiment A: Erster Teil . . . . . . . . . . . . 131 10 Testergebnisse Teilexperiment A: Zweiter Teil . . . . . . . . . . . 132 11 Testergebnisse Teilexperiment B: Erster Teil . . . . . . . . . . . . 133 12 Testergebnisse Teilexperiment B: Zweiter Teil . . . . . . . . . . . 134 13 Testergebnisse Experiment Regelauswertung: Erster Teil . . . . . 135 14 Testergebnisse Experiment Regelauswertung: Zweiter Teil . . . . . 136 x . . . . . . . . . . . . . . . . . . 114 Einleitung 1 Einleitung Verteilte und serviceorientierte Anwendungen spielen eine zunehmend wichtige Rolle für Unternehmen [40]. In diesem Teilbereich der Informationssysteme wurden viele Neuerungen hervorgebracht, denen heute eine zentrale Bedeutung im Bereich der Informationssysteme zukommt. Beispiele hierfür sind Technologien wie Web Services, RSS oder REST. Für Technologien, die in der Vergangenheit einen hohen Grad der Verbreitung erreicht hatten, bestand regelmäßig eine Nachfrage nach einer Vereinfachung der Handhabung und Steigerung der Effizienz im Umgang mit diesen Technologien. Als Beispiel kann hier SQL angeführt werden: SQL entstand, weil die weitläufige Nachfrage nach Zugriff auf Daten und deren Persistenzierung eine Vereinfachung der Handhabung durch eine zusätzliche Abstraktion mithilfe einer deklarativen Sprache notwendig machte [7]. Eine solche Vereinfachung der Handhabung sowie Steigerung der Effizienz bei der Entwicklung und Ausführung serviceorientierter verteilter Anwendungen bietet Demaq [6]. Demaq ist zum einen eine deklarative Sprache zur Entwicklung verteilter Anwendungen, die auf dem Austausch und der Verarbeitung standardisierter XML-Nachrichten basiert. Zum anderen ist es ein System, das Anwendungen ausführen kann, die mit der Sprache Demaq entwickelt wurden. Im Rahmen dieser Diplomarbeit wird das Demaq-System flexibler gestaltet, indem es modularisiert und einzelne Komponenten austauschbar gemacht werden. Beispielhaft wird untersucht, inwiefern eine Integration von Demaq mit einem kommerziellen relationalen Datenbanksystem praktikabel und effizient ist. Auf diese Weise soll die Eignung des Systems für einen möglichen zukünftigen Einsatz in Unternehmen erhöht werden. Die Problemstellung dieser Arbeit liegt im Bereich des Software-Engineerings. Dabei sollen die Anforderungen für die zu entwickelnden System-Veränderungen analysiert, designt und implementiert werden. Anschließend wird die Effizienz 1 1.1 Zielsetzung Einleitung der aus der Veränderung entstehenden System-Varianten mithilfe von Tests untersucht. 1.1 Zielsetzung Ziel dieser Diplomarbeit ist es, den Nachrichtenspeicher und den Mechanismus der Regelauswertung im Demaq-System zu modularisieren und dadurch austauschbar zu machen. Beispielhaft soll die relationale Datenbank DB2 in das Ausführungssystem integriert werden. Ferner soll die Leistungsfähigkeit der implementierten System-Varianten untersucht werden. 1.2 Gliederung Im Rahmen dieser Diplomarbeit soll Software verändert sowie einige Teile neu entwickelt und getestet werden. Die Aufgabenstellung fällt demnach in den Bereich des Software-Engineerings. Aus diesem Grund wird eine Gliederung wie folgt gewählt: 1. Grundlagen In Kapitel 2 werden die theoretischen Grundlagen für diese Arbeit geschaffen, die Voraussetzung für das Verständnis sind. 2. Problemstellung Kapitel 3 erläutert die Motivation und Ziele dieser Arbeit. Als Konsequenz werden die Anforderungen des zu entwickelnden Systems analysiert und als Herausforderungen problemorientiert formuliert. 3. Architektur Die umzusetzenden Änderungen am System werden grob auf konzeptioneller Ebene entworfen (Kapitel 4). 4. Feinentwurf Der Grobentwurf wird verfeinert und auf logischer Ebene betrachtet (Kapitel 5). 5. Implementation Der System-Entwurf wird im Detail auf physischer Ebene optimiert (Kapitel 6). 2 1.3 Darstellungskonventionen Einleitung 6. Evaluation Die Integration der entwickelten Komponenten wird in Kapitel 7 zunächst qualitativ anhand von Tests und anschließend mithilfe geeigneter Experimente quantitativ evaluiert. 7. Zusammenfassung und Ausblick Zum Abschluss werden die Ergebnisse in Kapitel 8 zusammengefasst sowie ein Ausblick auf zukünftige Untersuchungen und Weiterentwicklungsmöglichkeiten gegeben. 1.3 Darstellungskonventionen Einige Ausdrücke, die in dieser Diplomarbeit verwendet werden, werden im wissenschaftlichen und/oder allgemeinen Sprachgebrauch in Englisch verwendet. Um Missverständnisse zu vermeiden, werden diese in dieser Arbeit nur übersetzt sofern dies die Verständlichkeit nicht einschränkt. Fachausdrücke, die wörtlich aus dem Englischen übernommen werden, werden kursiv dargestellt. Programm-Code jeglicher Art, wie beispielsweise Variablen, Funktionen, Klassen oder andere Ausschnitte im Speziellen der Programmiersprachen C++, SQL, XQuery und DQL, werden in Schreibmaschinen-Schrift dargestellt. Ebenso werden Dateien und Pfade im Dateisystem durch Schreibmaschinen-Schrift kenntlich gemacht. 3 Grundlagen 2 Grundlagen Bevor die eigentliche Aufgabenstellung dieser Arbeit in nachfolgenden Kapiteln behandelt wird, widmet sich dieses Kapitel den Grundlagen, welche notwendiges Wissen zum Verständnis enthalten. Die Grundlagen erläutern Konzepte, Bestandteile, Funktionalitäten sowie Vor- und Nachteile bezogen auf Demaq selbst sowie auf konkret verwendete und zu verwendende Systemkomponenten im DemaqUmfeld. Dieses Kapitel soll im Speziellen dem unbedarften Leser den Zugang zu dieser Arbeit erleichtern. 2.1 Demaq In diesem Abschnitt wird das Demaq-System ganzheitlich abstrakt betrachtet. Dabei soll auf metakonzeptioneller Ebene beschrieben werden, welches Konzept hinter Demaq steht (Kapitel 2.1.1) und welche Bestandteile es ausmachen (2.1.2). 2.1.1 Konzept Das Konzept von Demaq basiert auf der Bearbeitung von XML-Nachrichten, die in Warteschlangen eingereiht und anschließend regelbasiert weiterverarbeitet werden. Dabei wird das Verhalten durch XQuery-basierte deklarative Regeln definiert. Auf diese Weise können komplexe Anwendungen auf einfache Weise erstellt werden. 2.1.2 Bestandteile Demaq setzt sich aus zwei Teilaspekten zusammen. Einerseits stellt Demaq eine deklarative Sprache zur Erstellung von Warteschlangen für XML-Nachrichten dar sowie zur Beschreibung der XML-Nachrichten. Auf der anderen Seite umfasst Demaq ein Ausführungssystem, welches diese deklarative Sprache interpretieren und umsetzen kann. Im Nachfolgenden werden beide Teilaspekte einzeln vorgestellt. 4 2.1 Demaq 2.1.2.1 Grundlagen Die Sprache Demaq Die deklarative Sprache Demaq ist wesentli- cher Bestandteil des Demaq-Konzeptes. Die Sprache unterteilt sich in zwei Teilsprachen für unterschiedliche Zwecke: Die Definitionssprache QDL und die Manipulationssprache QRL. Der jeweilige Zweck der Sprachteile kann wie folgt beschrieben werden: QDL: Mit den Sprachkonstrukten von QDL werden Queues (Warteschlangen), Slicings (Gruppen von Nachrichten mit bestimmten Properties) und Properties (Attribute) definiert. QRL: QRL wird verwendet, um Regeln anzulegen, die beschreiben wie Nachrichten in einer Warteschlange oder in einem Slicing weiterverarbeitet werden. Da die Regeln auf XML-Nachrichten angewandt werden, besteht QRL zum größten Teil aus XQuery. 2.1.2.2 Das Demaq-Ausführungssystem Das Demaq-Ausführungssystem ist bezüglich der Prozesse und Abläufe im System detailliert spezifiziert [6]. Die wichtigsten Bestandteile im Kontext dieser Diplomarbeit werden im Folgenden kurz erläutert: Nachrichtenspeicher Im Nachrichtenspeicher werden Warteschlangen für XML-Nachrichten angelegt und verwaltet. Außerdem werden hier die meisten vom System benötigten Daten gespeichert, wie z.B. Properties, Regeln oder andere Metadaten. RuleProcessor Der Regelauswerter (RuleProcessor) wendet Regeln auf einzelne Nachrichten an und generiert als Ergebnis eine Liste auszuführender Aktionen (QueryResult). QueryResult Das QueryResult ist eine Liste von Aktionen (Pending Action List), die durch die Anwendung von Regeln auf eine Nachricht entsteht und zur Ausführung bestimmt ist. 5 2.1 Demaq Grundlagen Actioninterpreter Der Actioninterpreter bekommt ein QueryResult übergeben und führt die darin enthaltenen Aktionen aus. Dispatcher Im Demaq-Ausführungssystem kann ein Dispatcher für eine oder mehrere Warteschlangen verantwortlich sein. Eine Warteschlange ist genau einem Dispatcher zugeordnet. In jedem Dispatcher können ein oder mehrere ProcessingThreads laufen, die für die Steuerung des Kontroll- und Datenflusses bei der Abarbeitung einer Nachricht verantwortlich sind. Die abzuarbeitende Nachricht wird einer Warteschlange entnommen, für die dieser Dispatcher zuständig ist. ProcessingThread Die ProcessingThreads holen sich Informationen über neu eingereihte Nachrichten von dem QueueScheduler und starten die Regelauswertung für diese mithilfe eines RuleProcessors. Nach der Regelauswertung übergeben sie das resultierende QueryResult an den Actioninterpreter. Dieser widerum gibt eine ConsequenceList als Ergebnis seiner Arbeit zurück. Die ConsequenceList leitet der ProcessingThread an den QueueScheduler weiter, der diese interpretiert. Die interpretierten Informationen stellt der QueueScheduler den ProcessingThreads zur weiteren Verarbeitung zur Verfügung. QueueScheduler Der QueueScheduler bestimmt die Reihenfolge der abzuarbeitenden Nachrichten innerhalb einer Warteschlange. Er bekommt vom Actioninterpreter in Form einer ConsequenceList mitgeteilt, welche Nachrichten neu aufgenommen wurden. ConsequenceList Eine ConsequenceList ist das Resultat der Ausführung von Aktionen. Wurde z.B. eine neue Nachricht in eine Warteschlange eingereiht, wird dies dem QueueScheduler in einer solchen Konsequenzen-Liste mitgeteilt. 6 2.2 Natix 2.2 Grundlagen Natix NATIX [11] ist ein natives XML-DBMS, dass zu Forschungszwecken entwickelt wurde, inzwischen aber auch kommerziell zum Einsatz kommt. Die Datenbank zeichnet sich dabei durch Konzepte aus, die für diese Diplomarbeit eine besondere Rolle spielen. Diese Konzepte werden im Nachfolgenden beschrieben. Des Weiteren unterstützt die Datenbank Features für die Speicherung von XML-Daten, die in Kapitel 2.2.2 eingehender beschrieben werden. Schließlich werden in Kapitel 2.2.3 einige Einschränkungen erläutert, denen NATIX unterliegt. 2.2.1 Konzepte In NATIX existieren einige neuartige Konzepte, die den Umgang mit XML-Daten vereinfachen. Diese Konzepte werden in diesem Kapitel kurz erläutert. 2.2.1.1 Fragmente Fragmente stellen in NATIX eine Abstraktion von XML- Daten dar [45]. Diese Daten können in verschiedenster Form vorliegen, z.B. als Datei im Dateisystem, gespeichert in NATIX oder als Ergebnis einer XQueryAuswertung. Dementsprechend können Fragmente in verschiedene Fragmenttypen (Fragment Types) unterteilt werden, je nachdem in welchem Container sie sich befinden. NATIX sind diese Typen bekannt und das System reagiert entsprechend auf die Daten eines Fragmenttypes. Repräsentiert werden die Fragmente durch Fragment Descriptors. Diese beinhalten nicht die eigentlichen Daten des Fragments, sondern Informationen, um auf diese Daten zuzugreifen. Beispielsweise genügt es für XML-Daten, die in einer Datei gespeichert sind, den absoluten Dateipfad zu kennen. Oder für ein XMLFragment, das in NATIX gespeichert ist, genügt die Dokument-ID. Ähnlich wie ein FileHandle kann ein Fragment Desctiptor wie ein Zeiger auf die eigentlichen Fragment-Daten verstanden werden. 7 2.2 Natix Grundlagen Tabelle 1: Matrix der unterstützten Views für Fragment Types (Adaptiert von [45]) 2.2.1.2 Requests Ein Request wird benötigt, um NATIX zu steuern [45]. Sollen beispielsweise Daten von NATIX angefordert werden, so muss die dazu notwendige Operation in NATIX mit Hilfe eines Requests ausgelöst werden. Dem Request-Objekt werden dabei alle erforderlichen Daten übergeben. Ausgeführt werden kann der Request zum einen, indem er der Funktion process() einer natix::Transaction übergeben wird. Zum anderen wird er automatisch nach dem Erzeugen ausgeführt, wenn dem Konstruktor des Requests eine natix::Transaction übergeben wurde. In den Fällen, in denen ein Request nur ein atomares Ergebnis liefert, wird dieses Ergebnis durch eine automatische Konvertierung bei der Ausführung zurückgeliefert. Ein Beispiel soll dies verdeutlichen: 1 n a t i x : : F r a g m e n t D e s c r i p t o r doc=n a t i x : : OpenDocument ( n a t i x T r a n s a c t i o n , docid ) ; In dem Beispiel wird ein Request mit dem Namen OpenDocument erzeugt, der eine Dokumenten-ID benötigt. Durch diese ID kann NATIX das Dokument eindeutig zuordnen. Durch die Übergabe des Objekts natixTransaction vom Typ natix::Transaction wird der Request sofort ausgeführt. Da es nur einen Ergebniswert für diese Operation gibt, wird dieser durch einen automatischen Konvertierungsmechanismus zurückgeliefert. In diesem Fall ist das Ergebnis ein natix::FragmentDescriptor. 8 2.2 Natix 2.2.1.3 Grundlagen Views Views werden in NATIX verwendet, um auf Fragmente und damit auf XML-Daten zuzugreifen [45]. Dabei verkörpern sie verschiedene Zugriffsformen auf XML-Daten. Beispielsweise kann ein XML-Dokument als DOMTree oder als Stream geöffnet werden. Tabelle 1 stellt in einer Übersicht dar, welche Fragmenttypen mit welcher View geöffnet werden können. Das Fragment, das zu dem natix::FragmentDescriptor ”doc“ aus dem Beispiel in Abschnitt 2.2.1.2 gehört, könnte z.B. wie folgt als Stream geöffnet werden: 1 n a t i x : : OpenView<n a t i x : : StreamView> streamView ( n a t i x T r a n s a c t i o n , doc ) ; s t d : : i o s t r e a m∗=streamView . getView ( )−>getStream ( ) ; Um eine bestimmte View auf ein XML-Dokument zu öffnen, muss ein entsprechender Request an NATIX übermittelt werden (vgl. Abschnitt 2.2.1.2). 2.2.1.4 XQuery-Auswertung In NATIX können verschiedene Engines zur Auswertung von XQuery eingesetzt werden. Standardmäßig wird Saxon [30] verwendet. Für Saxon gibt es in NATIX Erweiterungen (Callbacks), damit Demaqspezifische Sprachkonstrukte, wie beispielsweise qs:queue() oder qs:slice(), ausgewertet werden können. Diese Callbacks werden benutzt, um während der Regelverarbeitung dynamisch Daten aus dem Nachrichtenspeicher nachzuladen. Auf diese Weise können Nachrichten oder Properties durch Funktionsaufrufe innerhalb der QRL dynamisch in den Regeln verarbeitet werden. Ein Beispiel: create r u l e count f o r queue1 2 enqueue message <r e s u l t > { f n : count ( qs : queue ( ’ queue1 ’ ) ) } 4 </ r e s u l t > into r e s p o n s e q u e u e ; In obigem Beispiel wird eine Regel mit dem Namen count für die Warteschlange queue1 erzeugt. In dieser werden die Nachrichten, die sich in der Warteschlange befinden, gezählt und das Ergebnis in die Antwort-Warteschlange responsequeue übermittelt. An der Stelle mit dem Ausdruck “qs:queue(’queue1’)” wird 9 2.2 Natix Grundlagen bei Auswertung der Regel ein Callback ausgeführt, der auf den Nachrichtenspeicher zugreift. Als Resultat wird eine Sequenz aller Nachrichten der Warteschlange queue1 zurückliefert. Das Zwischenergebnis nach Auswertung des Callbacks sieht in dem Beispiel wie folgt aus: create r u l e count f o r queue1 2 enqueue message <r e s u l t > { f n : count((<xml i d= ’ 1 ’ />, <xml i d= ’ 2 ’ />) ) } 4 </ r e s u l t > into r e s p o n s e q u e u e ; Nach der Auswertung des Callbacks wird die Regel von Saxon weiter verarbeitet. 2.2.2 Features NATIX speichert XML-Daten nativ, d.h. XML-Dokumente werden nicht als flache Text-Strukturen gespeichert, sondern als Baumstruktur mit dem DokumentKnoten als Wurzel. Außerdem unterstützt NATIX die Verwaltung von XML-Daten mit Hilfe von Warteschlangen. Dabei sind die Warteschlangen in NATIX nativ implementiert, d.h. eine spezielle Datenstruktur wird genutzt, die explizit für diesen Zweck optimiert ist. 2.2.3 Einschränkungen NATIX unterliegt Einschränkungen in den folgenden Bereichen: Nebenläufigkeit In NATIX kann nur eine Transaktion gleichzeitig verarbeitet werden, die Updates auf Daten durchführt. Das ACID-Konzept [31] wird hierbei umgesetzt, indem Änderungen am Datenbestand seriell abgearbeitet werden. Datenformate Daten werden ausschließlich im XML-Format abgespeichert. 10 2.3 DB2 Grundlagen Anfrageoptimierung Eine automatische Anfrage-Optimierung, z.B. von XQuery-Ausdrücken, wird von NATIX nicht durchgeführt, da hierfür integrierte XQuery-Engines verwendet werden (vgl. Abschnitt 2.2.1.4). Aus diesem Grund können keine Indizes oder andere interne Strukturen, wie beispielsweise Dictionaries, ausgenutzt werden. 2.3 DB2 Für eine beispielhafte Integration einer relationalen Datenbank mit nativer XMLUnterstützung in das Demaq-System kommen eine Reihe kommerzieller DBMS in Frage. Die gängigsten relationalen Datenbanken sind (mit über 85% Marktanteil in 2006 [12]): • Database 11g (Oracle) • DB2 (IBM) • SQL Server (Microsoft) Für die Umsetzung dieser Diplomarbeit wurde DB2 gewählt. Die Gründe für diese Wahl werden in Kapitel 2.3.1 erläutert. In Abschnitt 2.3.2 werden anschließend die Einschränkungen von DB2 beleuchtet. 2.3.1 Features Folgende Kriterien waren entscheidend für die Wahl von DB2 als beispielhafte Integrationslösung in das Demaq-Ausführungssystem im Rahmen dieser Diplomarbeit: Unterstützte Sprachen Die DB2 unterstützt XQuery (einschließlich der XQuery Update Facility), SQL/XML und SQL. 11 2.3 DB2 Grundlagen Daten-Kompression XML-Daten können in der DB2 automatisch komprimiert werden. Die Kompression der Daten spielt im Hinblick auf das Leistungsverhalten eine wichtige Rolle. Automatische Optimierung Die DB2 Execution-Engine ist ein hybrides System [4]. Dieses kann sowohl XQuery, SQL/XML als auch SQL optimieren. Die Grenzen sind hierbei fließend, d.h. Ausdrücke, die beispielsweise XQuery und SQL enthalten, können sprachübergreifend optimiert werden. Parallelität DB2 unterstützt sowohl die parallele Ausführung auf Multiprozessor-Maschinen als auch die parallelisierte Speicherung auf mehreren Datenträgern mit automatisierter Speicherverwaltung (Automatic Storage) [1]. ACID Die Einhaltung des ACID-Konzepts [31] wird von DB2 auch für XMLbasierte Vorgänge zugesichert. 2.3.2 Einschränkungen Einschränkungen der Funktionalitäten von DB2, die diese Diplomarbeit betreffen, werden im nachfolgenden Kapitel aufgeführt. 2.3.2.1 Allgemeine Einschränkungen Einige allgemeine Einschränkungen begrenzen die Verwendung von DB2-Features, insbesondere im Umgang mit XML-Daten: • XML kann von DB2 nur serialisiert an externe Applikationen zurückgegeben werden. Eine Rückgabe z.B. als DOM-Tree ist nicht möglich [8]. • Der XML-Datentyp kann nicht als Rückgabewert und nicht als Parameter einer UDF verwendet werden [16]. 12 2.3 DB2 Grundlagen • XQuery-Ausdrücke können innerhalb einer Stored Procedure oder UDF nicht direkt, sondern nur mithilfe eines SQL/XML-Statements ausgeführt werden [38]. • In temporären Tabellen kann der XML-Datentyp nicht verwendet werden [21]. • XML-Spalten können nicht in Bereichs-Cluster - und MDC-Tabellen verwendet werden [21]. 2.3.2.2 XQuery Einschränkungen Folgende Sprachkonstrukte des aktuel- len XQuery Standards (Version 1.0) [5], die diese Diplomarbeit betreffen, werden von der DB2 XQuery Engine nicht unterstützt [28]: • declare module und import module • declare function • declare variable • qualifizierte Variablennamen (Beispiel: $demaq:systemVariable) • qualifizierte Funktionsnamen (Beispiel: qs:queue(); Ausnahme sind die qualifizierten Funktionsnamen, die aus dem statischen Kontext der DB2 XQuery Engine bekannt sind, wie z.B. db2-fn:sqlquery()) Außerdem existieren folgende Einschränkungen beim Zugriff auf relationale Daten aus XQuery heraus, beispielsweise mit der Funktion db2-fn:sqlquery [22]: • Es können nur reine Select-Statements und keine SQL-Update-Ausdrücke verwendet werden • Aus XQuery kann nicht mittels db2-fn:sqlquery auf Sequenzen zugegriffen werden 13 Problemstellung 3 Problemstellung Nachdem im vorangehenden Kapitel die Grundlagen zum Verständnis dieser Arbeit geschaffen wurden, wird in diesem Kapitel die eigentliche Problemstellung erarbeitet. Die zu lösenden Probleme werden anhand der folgenden stringenten Vorgehensweise identifiziert: Zunächst wird die Umsetzung des Vorhabens motiviert (Abschnitt 3.1). Aus der Motivation heraus werden anschließend die Ziele dieser Arbeit abgeleitet (Abschnitt 3.2). Aus den Zielen ergeben sich die Anforderungen für die Umsetzung (Abschnitt 3.3), aus denen letztendlich unmittelbar die Herausforderungen abgeleitet werden (Abschnitt 3.4). 3.1 Motivation Demaq ist ein Ausführungssystem für XML-nachrichtenbasierte verteilte Anwendungen. Es unterscheidet sich insbesondere durch seine vollständig deklarative Sprache und das warteschlangenbasierte Ausführungsmodel von der Architektur aktueller Systeme [6]. Für Unternehmen bedeutet die Einführung neuer Software mit eigenen Komponenten ein Risiko, da der daraus entstehende Wartungsaufwand schwer abzuschätzen ist. Besser ist es, wenn neue Software mit flexiblen Komponenten lauffähig ist, damit eine nahtlose Integration in bestehende Systemlandschaften im Unternehmen möglich ist. Bis dato wurde die native XML-Datenbank NATIX als Nachrichtenspeicher für das System benutzt. Dies begründet sich dadurch, dass hauptsächlich Daten im XML-Format gespeichert und verarbeitet werden. In gängigen DBMS war zum Zeitpunkt der Entwicklung von Demaq eine native Unterstützung des XMLDatentyps nicht implementiert. Ein weiterer Grund, weshalb NATIX als Nachrichtenspeicher für das Demaq-System gewählt wurde, ist, dass der Quelltext von NATIX vorliegt, so dass evtl. nötige Anpassungen im Nachrichtenspeicher ohne 14 3.1 Motivation Problemstellung Probleme vorgenommen werden können. Allerdings weist die Benutzung von NATIX innerhalb des Demaq-Systems mehrere Nachteile (vgl. Kapitel 2.2.3) auf, da die XML-Datenbank ursprünglich nicht explizit für diesen Zweck konzipiert wurde [11]. Zudem verfügen relationale Datenbanken inzwischen nicht nur über einen nativen XML-Datentyp, sondern auch eine Verarbeitung von XML-Daten mit XQuery oder SQL/XML ist möglich. Zusammenfassend soll das Demaq-System im Rahmen dieser Diplomarbeit modularer und damit flexibler gestaltet werden. Zu diesem Zweck wird die Integration eines relationalen DBMS (beispielhaft mit der DB2 (vgl. Kapitel 2.3.1)) sowohl als Nachrichtenspeicher als auch zur Regelauswertung im Demaq-System untersucht. Hierbei wird insbesondere auf folgende Punkte näher eingegangen: • Ist das Demaq-Ausführungssystem geeignet, um eine relationale Datenbank als Nachrichtenspeicher/Regelauswerter zu verwenden? • Welche Anpassungen sind notwendig, damit dies möglich wird? Ist dies praktikabel? • Ist die DB2 zur Integration als Nachrichtenspeicher und Regelauswerter im Demaq-System geeignet? • Wie können Mechanismen (Indizes, Anfrageoptimierung, Parallelität1 , Nebenläufigkeit2 ) der DB2 zur Optimierung genutzt werden? • Wie lassen sich ggf. Funktionalitäten des Demaq-Systems in das relationale DBMS verlagern? 1 Parallelisierung bedeutet, dass mehrere Programmteile physisch gleichzeitig ausgeführt wer- den: ”A condition that arises when at least two threads are executing simultaneously.“ [44, S.16]. 2 Nebenläufigkeit (Concurrency) bezeichnet die Abarbeitung verschiedener Aufgaben in unterschiedlichen Threads. Dabei muss die Bearbeitung nicht unbedingt physisch gleichzeitig erfolgen: ”A condition that exists when at least two threads are making progress. A more generalized form of parallelism that can include time-slicing as a form of virtual parallelism.“ [44, S.16]. 15 3.2 Ziele 3.2 Problemstellung Ziele In dem Demaq-Ausführungssystem soll der Nachrichtenspeicher NATIX durch eine relationale Datenbank – im konkreten Fall die DB2 (vgl. hierzu Kapitel 2.3.1) – ersetzt werden. Hierzu werden zunächst die Möglichkeiten zur Abbildung der eingesetzten Warteschlangen auf das relationale Datenmodell evaluiert, um anschließend die hieraus resultierenden Änderungen in Bezug auf das Leistungsverhalten mit geeigneten Experimenten auszuwerten. Ebenso wird deren Leistungsverhalten mit der nativen Warteschlangenimplementierung in NATIX verglichen. Ein weiteres Ziel ist es, die Ausführung der Regeln in das relationale Datenbanksystem zu verlagern. Anstelle von Saxon soll hierbei die XQuery-Engine der DB2 zur Regelauswertung verwendet werden. Über eine Kompilier-Option soll steuerbar sein, mit welchem Regelauswerter das Demaq-System ausgeführt wird. Im Rahmen der vorliegenden Arbeit wird gezeigt, wie das DemaqAusführungssystem für einen Austausch des Nachrichtenspeichers und des Regelauswertungsmechanismus anzupassen ist. 3.3 Anforderungen Im Nachfolgenden werden weitere Anforderungen dargestellt, die im Rahmen der Implementierung zu berücksichtigen sind. 3.3.1 Korrektheit Die Korrektheit der Funktionsweise des Systems nach dem Austausch des Nachrichtenspeichers bzw. des Regelauswertungsmechanismus ist anhand von Testfällen zu zeigen. Zu diesem Zweck muss zunächst eine praktikable Lösung zum Austausch gefunden werden. Mittels dieser ist zu überprüfen, ob das System dieselben Ergebnisse für gleiche Anwendungen liefert wie das aktuelle DemaqAusführungssystem. 16 3.4 Herausforderungen 3.3.2 Problemstellung Modularisierung In der vorliegenden Diplomarbeit werden der Nachrichtenspeicher und die Regelauswertung im Demaq-System ausgetauscht. Hierbei ist eine Modularisierung angestrebt, um einzelne Komponenten später gegeneinander auszutauschen bzw. neu miteinander zu kombinieren. Auf diese Weise können sie auch in zukünftigen Untersuchungen durch weitere Alternativen ersetzt werden. Die zu verwendende Variante des Demaq-Systems (vgl. Abbildung 1) soll zur Kompilier-Zeit festgelegt werden. Es wird nicht möglich sein, während der Laufzeit des Systems den Nachrichtenspeicher zu wechseln. Dazu müsste das System erst gestoppt, neu kompiliert und gestartet werden. 3.3.3 Leistungsverhalten Das Leistungsverhalten der zu entwickelnden Komponenten hat eine hohe Priorität. Allerdings steht zunächst die generelle Machbarkeit im Vordergrund. Sollte diese jedoch gegeben sein, ist es eine Anforderung, das System bezüglich des Leistungsverhaltens zu optimieren. Außerdem soll das Leistungsverhalten der Varianten (vgl. Abbildung 1) mit dem aktuellen NATIX-basierten System verglichen werden. Im Idealfall sind Aussagen über Veränderungen einzelner Funktionalitäten zu treffen, wie z.B. über Zugriffe auf Slices oder Properties. 3.4 Herausforderungen Aus den Zielen und Anforderungen dieser Diplomarbeit ergeben sich einige Herausforderungen, die im Nachfolgenden kurz dargestellt werden. Dieses Kapitel zielt dabei auf die Frage ab, welche Probleme zu lösen sind, um die Anforderungen und Ziele zu erfüllen. 17 3.4 Herausforderungen 3.4.1 Problemstellung Überprüfung der Korrektheit Zur Überprüfung der Korrektheit des Demaq-Systems sind Tests auszuführen, die den vollständigen Funktionsumfang von Demaq abdecken. Alle lauffähigen Varianten müssen in diesen Tests nicht nur das gleiche, sondern auch das der Spezifikation [6, 46] entsprechende Ergebnis liefern. 3.4.2 Modularisierung Aus den Zielen (vgl. Kapitel 3.2) dieser Diplomarbeit können zwei getrennt voneinander zu bearbeitende Teilprobleme abgeleitet werden: Zum einen der Austausch des Nachrichtenspeichers und zum anderen der Austausch der Regelauswertung. Die betroffenen Komponenten sollen frei miteinander kombinierbar bleiben (vgl. Kapitel 3.3.2). Daraus ergeben sich drei lauffähige Varianten des DemaqSystems. Das Demaq-System wird entweder mit NATIX und Saxon oder ausschließlich mit der DB2 kompilierbar sein. Außerdem wird es eine weitere Mischform des Demaq-Systems geben, welche die DB2 als Nachrichtenspeicher und Saxon als Regelauswerter verwendet. Dadurch können Experimente durchgeführt werden, deren Ergebnisse eindeutig dem Austausch des Nachrichtenspeichers zuzurechnen sind. Eine weitere Variante mit NATIX als Nachrichtenspeicher und der DB2 als Regelauswerter ist nicht sinnvoll, da der Arbeitsaufwand zu groß ist und Optimierungsmechanismen innerhalb der Komponenten nicht genutzt werden können. Abbildung 1 veranschaulicht die angestrebten möglichen Ausführungsversionen des Demaq-Systems. Die Modularisierung stellt eine große Herausforderung dar, da an mehreren Stellen im Quelltext des Demaq-Ausführungssystems NATIX-spezifischer Code direkt inkludiert und verwendet wird. Dementsprechend wurde bei der Entwicklung von Demaq keine strikte Kapselung verfolgt, da eine Austauschbarkeit von einzelnen Komponenten nicht vorgesehen war. 18 3.4 Herausforderungen Problemstellung Abbildung 1: Varianten des Demaq-Systems 3.4.3 Modellierung der Datenstrukturen und Features Die Modellierung der Datenstrukturen und Features ist eine Herausforderung, die sich aus der Anforderung zur Optimierung des Leistungsverhaltens ergibt (vgl. Kapitel 3.3.3). Im Wesentlichen stellt sich die Frage, wie die internen Datenstrukturen im Demaq-System effizient auf ein relationales Datenbanksystem abgebildet werden können. Hierzu zählt nicht nur die Abbildung der Warteschlangen, sondern auch die Modellierung der sonstigen Daten und Metadaten, wie z.B. der Regeln (Rules) und Eigenschaften (Properties). Die DB2 stellt viele Mechanismen und Erweiterungsmöglichkeiten bereit, die es erlauben, ähnliche Features abzubilden wie sie das Demaq-System bietet. Im Rahme dieser Arbeit sind Möglichkeiten zu untersuchen, wie einzelne Funktionalitäten in das relationale DBMS verlagert werden können, um Leistungssteige19 3.4 Herausforderungen Problemstellung rungen zu erzielen. Dabei ist deren Vorteilhaftigkeit kritisch zu beleuchten und zu diskutieren. 3.4.4 Physische Optimierung des Leistungsverhaltens Bei der Optimierung des Leistungsverhaltens der Demaq-Varianten mit der DB2 spielen insbesondere die Parallelisierung der Abläufe, Nebenläufigkeit, die Anfrageoptimierung und Indizes eine wichtige Rolle. 3.4.4.1 Parallelisierung Die Parallelisierung umfasst die physische Opti- mierung der DB2. Dabei sind zwei Bereiche besonders wichtig: Zum einen die Speicherung der Daten, da diese unabhängig vom Prozessor durchgeführt werden kann. Zum anderen betrifft es den/die Prozessor(en) selbst. Dabei ist eine Kontrolle über die Auslastung der Prozessoren nur über das DB2 Control Center möglich, da der Quelltext der DB2 nicht offen ist. Hierbei stellt sich die Frage, welche Mechanismen zur Beeinflussung der Parallelität zur Verfügung stehen und wie diese im Sinne des Demaq-Ausführungssystems leistungssteigernd eingesetzt werden können. 3.4.4.2 Nebenläufigkeit Im Demaq-Ausführungssystem ist Nebenläufigkeit für die Abarbeitung der Warteschlangen vorgesehen, indem verschiedene Nachrichten auf mehreren nebenläufigen Threads verarbeitet werden können. Allerdings unterstützt NATIX keine nebenläufigen Zugriffe (vgl. Kapitel 2.2.3), so dass immer nur eine Transaktion gleichzeitig auf den Nachrichtenspeicher zugreifen kann. Wenn eine NATIX-Transaktion gestartet ist, werden alle anderen ausgeführten Threads blockiert, die ebenfalls eine Transaktion initiieren wollen. Da der Zugriff auf den Nachrichtenspeicher essentiell für den Programmablauf im Demaq-Ausführungssystem ist, kann eine nebenläufige Verarbeitung mit NATIX nicht unterstützt werden. Dies führt so weit, dass das Starten mehrerer Threads das System verlangsamt, da diese untereinander synchronisiert werden müssen, 20 3.4 Herausforderungen Problemstellung obwohl keine Nebenläufigkeit möglich ist. Die Integration der DB2 als Nachrichtenspeicher ermöglicht eine nebenläufige Verarbeitung. Mithilfe der DB2 können beliebig viele Transaktionen gleichzeitig gestartet werden, die simultan auf den Nachrichtenspeicher zugreifen und Daten ändern können. Diese Option soll genutzt und optimiert werden, um eine Verbesserung des Leistungsverhaltens zu erzielen. 3.4.4.3 Anfrageoptimierung Eine Anfrageoptimierung findet in der DB2 automatisch statt. Ein Einfluss hierauf ist nur beschränkt über die Datenbankadministration möglich. Grundsätzlich gilt, dass mehrere einzelne Anfragen möglichst zusammengefasst werden, damit die automatische Optimierung übergreifende Synergieeffekte realisieren kann (vgl. beispielsweise [3]). 3.4.4.4 Indizes Indizes bieten eine gute Möglichkeit, um Zugriffe auf be- stimmte Datensätze innerhalb einer Tabelle zu beschleunigen. Ebenso können sie aber die Verarbeitung von Daten verlangsamen, insbesondere wenn viele Update-Operationen jeweils die Anpassung eines Index erfordern. Als Folge kann der Aufwand für die Pflege eines Index so groß sein, dass er den Gewinn beim Zugriff übersteigt. Insofern ist die Verwendung von Indizes im Vorfeld abzuwägen. 3.4.5 Untersuchung des Leistungsverhaltens Das im Rahmen dieser Arbeit implementierte System soll nach der Änderung des Leistungsverhaltens beurteilt werden, das sich aufgrund des Austauschs des Regelauswertungsmechanismus und des Nachrichtenspeichers ergibt. Durch breit angelegte Experimente wird die Veränderung derart gemessen werden, so dass diese: 1. eindeutig auf eine Ursache zurückzuführen ist 21 3.4 Herausforderungen Problemstellung 2. möglichst generalisierbar, d.h. im besten Fall auf alle denkbaren Anwendungsszenarien übertragbar ist. Die Ergebnisse von Tests, die ausschließlich mit sehr kurzen Nachrichten und einfachen Regeln definiert sind, können erheblich von den Ergebnissen von Tests abweichen, die mit sehr langen Nachrichten und komplexen Regeln arbeiten. Aus diesem Grund müssen vernünftig formulierte Tests alle denkbaren Anwendungsszenarien abdecken und idealtypisch nach ihrer Komplexität skalierbar sein. Hierdurch können Veränderungen des Leistungsverhaltens für einzelne Features des Demaq-Systems identifiziert werden. Beispielsweise könnten sich Zugriffe auf Properties als besonders effizient herausstellen, während sich Zugriffe auf Slices als uneffizient erweisen. Veränderungen des Leistungsverhaltens bei gleichzeitigem Austausch des Nachrichtenspeichers und des Regelauswertungsmechanismus können nicht eindeutig auf eine der beiden Ursachen zurückgeführt werden. Deshalb liegt eine Herausforderung in der Definition von zwei unabhängigen Experimenten, die beide Veränderungen getrennt voneinander untersuchen (vgl. Kapitel 3.4.2). 22 Architektur 4 Architektur Nachdem im vorangegangenen Kapitel die Ziele formuliert und die Anforderungen des zu entwickelnden Systems analysiert wurden, wird in diesem Kapitel das Design des Systems auf konzeptioneller Ebene entworfen. Zu diesem Zweck werden die Architekturen der Demaq System-Varianten vorgestellt, die im Rahmen dieser Diplomarbeit entwickelt werden. Während Kapitel 4.1 die Architekturen variantenbezogen und schematisch vorstellt, befasst sich das Kapitel 4.2 detaillierter mit den Modulen, die zu mehreren Varianten in Bezug stehen. 4.1 Demaq System-Varianten Ein zentrales Ziel der vorliegenden Arbeit ist es, das Demaq-System komponentenbasiert zu realisieren. Mit diesen Komponenten können durch freie Kombination mehrere Varianten des Systems erzeugt werden, von denen im Rahmen dieser Ausarbeitung drei beschrieben werden (vgl. Kapitel 3.4.2). Die Architektur der Varianten wird in den folgenden Unterkapiteln beleuchtet. Dabei werden die Komponenten analysiert und beschrieben, sofern sie für die Aufgabenstellung dieser Diplomarbeit relevant sind. Zusätzliche Komponenten, wie beispielsweise das Kommunikationssystem [46], bleiben unberücksichtigt. 4.1.1 Übersicht der System-Varianten In dem Demaq-Ausführungssystem sind folgende Komponenten für diese Diplomarbeit relevant: Demaq Kern: Der Code, der die Hauptfunktionalität von Demaq enthält. In diesem werden die Systemabläufe gesteuert und weitere Aufgaben an den Nachrichtenspeicher und die Regelauswertung deligiert. Nachrichtenspeicher: Im Nachrichtenspeicher werden alle Nachrichten und weitere Daten gespeichert. 23 4.1 Demaq System-Varianten Architektur Regelauswertung: Die Regelauswertung (XQuery-Processing) verarbeitet Nachrichten im XML-Format. Abbildung 2: Varianten des Demaq-Systems: Komponenten und deren individuelle Module Nach der Implementation wird es drei Kompilier-Alternativen des DemaqSystems geben. Diese werden in Abbildung 2 gruppiert nach der Komponentenzugehörigkeit dargestellt. Außerdem werden die Module dargestellt, die für diese Komponenten individuell zum Einsatz kommen. Für die Regelauswertung mit Saxon wird NATIX zur Steuerung des Kontrollflusses verwendet, wie in Kapitel 4.2.3 ausführlich diskutiert werden wird. Eine Kompilierung mit NATIX als Nachrichtenspeicher und der DB2-XQuery-Engine als Regelauswerter wird nicht betrachtet. In den folgenden Kapiteln werden die Varianten detaillierter beschrieben. Dabei werden die individuellen Module der Varianten in den Gesamtkontext der Module eingeordnet, die unverändert bleiben. 24 4.1 Demaq System-Varianten 4.1.2 Architektur Demaq mit NATIX und Saxon Das bisherige Demaq-Ausführungssystem benutzt folgende drei Hauptkomponenten: Demaq Kern: Der Kern des Demaq-Systems mit den individuellen Modulen NatixGateway, NatixRuleProcessor, NatixQueryResult und NatixActionInterpreter. Nachrichtenspeicher: Die XML-Nachrichten werden im nativen XMLDatenbanksystem NATIX gespeichert. Regelauswertung: Wird mit der Saxon-XQuery-Engine [30] durchgeführt. Der Demaq-Kern beinhaltet die wesentlichen Teile des Ausführungssystems, welche die Steuerung des Kontrollflusses übernehmen. Während des Systemstarts werden hier zunächst die Hauptspeicherstrukturen und der Nachrichtenspeicher initialisiert. Abbildung 3: Schematischer Kontrollfluss im Demaq-System Jede vom Kommunikationssystem eingehende Nachricht wird vom NatixActionInterpreter über das NatixGateway in NATIX abgespeichert. Außerdem wird der QueueScheduler mittels einer ConsequenceList über den Eingang einer Nachricht informiert. Dieser wiederum veranlasst die Ausführung der Regeln für die Nachricht mit dem NatixRuleProcessor, der mit Hilfe von NATIX die 25 4.1 Demaq System-Varianten Architektur Saxon-XQuery-Engine nutzt. Während der Auswertung kann die XQuery-Engine über Callbacks (vgl. Abschnitt 2.2.1.4) auf den Nachrichtenspeicher zugreifen. Die erfolgreiche Verarbeitung einer Regel liefert eine Pending Action List, die in Form eines NatixQueryResult an den NatixActionInterpreter weitergegeben wird. Der NatixActionInterpreter führt die ausstehenden Aktionen, wie z.B. Nachrichten in Warteschlangen einreihen oder Antworten in Kommunikationskanäle übermitteln, aus und leitet erneut eine ConsequenceList an den QueueScheduler weiter. Auf diese Weise können mehrere iterative Durchgänge entstehen (vgl. Abbildung 3). Abbildung 4 zeigt das bisherige Demaq-System mit NATIX als Nachrichtenspeicher und Saxon als Regelauswerter. Die Kommunikation zwischen NatixActionInterpreter, QueueScheduler und dem RuleExecutor regeln Dispatcher, die einer oder mehreren Warteschlangen zugeordnet sind. Die Dispatcher unterstützen Nebenläufigkeit, indem sie mit mehreren ProcessingThreads verschiedene Kommunikationsflüsse gleichzeitig steuern können. 4.1.3 Demaq mit der DB2 und Saxon Die zweite Variante des Demaq-Systems (vgl. Abbildung 1) umfasst folgende Komponenten: Demaq Kern: Der Kern des Demaq-Systems mit den individuellen Modulen DB2Gateway, NatixRuleProcessor, NatixQueryResult und NatixActionInterpreter. Nachrichtenspeicher: Alle relevanten Daten werden im relationalen DBMS DB2 gespeichert. Regelauswertung: Die Regeln werden mit der Saxon-XQuery-Engine [30] ausgewertet. Die Callback-Services sind für die DB2 angepasst. 26 4.1 Demaq System-Varianten Architektur Abbildung 4: Bisheriges Demaq-System: Detailansicht der wichtigsten Module in den Komponenten Die Implementierung dieser Version betrifft zwei Schnittstellen (vgl. Abbildung 4): Zum einen die funktionale Schnittstelle zwischen Demaq-Kern und Nachrichtenspeicher, die im System mit NATIX als Nachrichtenspeicher im NatixGateway implementiert ist. Zum anderen die Schnittstelle zwischen Regelauswertung und Nachrichtenspeicher, implementiert in den Callback Services. Abbildung 5 veranschaulicht die Architektur dieser System-Variante. Im Gegensatz zu Abbildung 4 wurde das NatixGateway durch das DB2Gateway ersetzt, um die Kommunikation mit der DB2 als Nachrichtenspeicher aus dem DemaqKern heraus zu ermöglichen. Das DB2Gateway greift dabei nicht direkt auf die DB2 zu, sondern nutzt die Funktionalitäten der Klasse DB2Transaction, die im Wesentlichen eine Fassade [42] für den Nachrichtenspeicher darstellt. 27 4.1 Demaq System-Varianten Architektur Abbildung 5: Demaq-System mit der DB2 und Saxon : Detailansicht der wichtigsten Module in den Komponenten Bei der Regelauswertung wird NATIX zur Steuerung von Saxon verwendet. Damit die Callback Services weiterhin auf den Nachrichtenspeicher zugreifen können, müssen diese entsprechend angepasst werden. Außerdem muss NATIX selbst erweitert werden, um Zugang zu den Nachrichten in der DB2 zu bekommen. Auf diese Weise kann der Rest des Demaq-Systems unverändert gegenüber der aktuellen Version bleiben, d.h. beispielsweise der NatixRuleProcessor, das NatixQueryResult und der NatixActionInterpreter können wie bisher verwendet werden. 28 4.1 Demaq System-Varianten 4.1.4 Architektur Demaq mit der DB2 Die dritte Variante des Demaq-Systems (vgl. Abbildung 1) benutzt folgende Komponenten: Demaq Kern: Der Modulen Kern DB2Gateway, des Demaq-Systems DB2RuleProcessor, mit den individuellen DB2QueryResult und DB2ActionInterpreter. Nachrichtenspeicher: Alle relevanten Daten werden im relationalen DBMS DB2 gespeichert. Regelauswertung: Die XQuery-Engine der DB2 wird zur Regel-Auswertung benutzt. Die Callback-Services sind für die DB2 angepasst. Im Vergleich zu der vorhergehenden Version mit der DB2 und Saxon muss zunächst die Schnittstelle zur Regelauswertung (NatixRuleProcessor) ausgetauscht werden. Allerdings könnte in Weiterentwicklungen ein Fallback Mechanismus implementiert werden, der Saxon in den Fällen zur Regelauswertung benutzt, in denen die Regel von der DB2 nicht ausgewertet werden kann (z.B. wenn XQuery-Module importiert oder Funktionen deklariert werden; vgl. Abschnitt 2.3.2.2). Außerdem müssen das NatixQueryResult und der NatixActionInterpreter durch angepasste Varianten ersetzt werden, die auf die DB2 abgestimmt sind. Die Schnittstelle zum Nachrichtenspeicher (DB2Gateway) kann von der zweiten System-Version (siehe Kapitel 4.1.3) übernommen werden. In Abbildung 6 wird das System schematisch mit den Modulen dargestellt. Der NatixRuleProcessor wird im Demaq-Quelltext nur in einer Klasse aufgerufen (RuleExecutor). Dort wird er erzeugt und zur Regelauswertung eingesetzt. Dabei enthält der NatixRuleProcessor außer der Funktion executeRule() keine weiteren wesentlichen Funktionen. Aus diesem Grund kann die Implementierung mit wenig Aufwand über eine Vererbungshierarchie geregelt werden: Der 29 4.1 Demaq System-Varianten Architektur Abbildung 6: Demaq-System mit der DB2 : Detailansicht der wichtigsten Module in den Komponenten RuleProcessor wird als Oberklasse verwendet und an zwei Unterklassen NatixRuleProcessor und DB2RuleProcessor vererbt. Auf diese Weise kann im RuleExecutor die Regelauswertung in gleicher Weise sowohl mit NATIX als auch mit der DB2 als Regelauswerter vorgenommen werden. Außerdem wird es ermöglicht einen NatixRuleProcessor sowie einen DB2RuleProcessor parallel in einem System ausführen zu können. Nach der Regelauswertung mit NATIX oder der DB2 werden strukturell unterschiedliche Ergebnisse zurückgeliefert (siehe Kapitel 6.2). Deshalb werden die Klassen, die für die Weiterverarbeitung des QueryResults zuständig sind ebenfalls angepasst. Analog zum RuleProcessor wird eine Vererbungsstruktur gewählt, damit die Handhabung für alle Versionen gleich ist und verschiedene 30 4.2 Module Architektur Abbildung 7: Detailansicht der Vererbungshierarchien im Kontext der Kontrollflüsse im DemaqKern Regelauswerter parallel in einem System eingesetzt werden können. Entsprechend wird eine Klasse QueryResult umgesetzt, die an die individuellen Klassen DB2QueryResult und NatixQueryResult vererbt. Außerdem wird eine Basisklasse ActionInterpreter implementiert, von der die Klassen NatixActionInterpreter und DB2ActionInterpreter erben. Die Vererbungshierachien (gestrichelte Pfeile) werden in Abbildung 7 im Ablaufschema im Demaq-Kern dargestellt. Die Query-Auswertung mit der DB2 über NATIX abzuwickeln bringt keine Vorteile mit sich. Zudem würde dies das System von NATIX abhängig machen. Aus diesem Grund wird von dieser Architekturvariante abgesehen. 4.2 Module Module werden von den Komponenten benutzt. Es kann sich dabei um Klassen innerhalb von Komponenten oder Funktionseinheiten handeln. Beispielsweise besteht der DB2 Nachrichtenspeicher aus zwei Modulen (Funktionseinheiten): Der Datenbank DB2 und der DB2-Fassade mit der Klasse DB2Transaction. Die Module können den in dieser Arbeit beschriebenen Varianten des DemaqSystems nicht eindeutig zugeordnet werden. Sie werden wiederverwendet und sind abhängig von den benutzten Komponenten, müssen aber nicht zu diesen gehören. 31 4.2 Module Architektur Als Beispiel: Das Modul DB2Gateway (Schnittstelle zum Nachrichtenspeicher) ist abhängig von der Komponente ”Nachrichtenspeicher“, gehört aber zu der Komponente ”Demaq-Kern“. In diesem Kapitel werden die Module nicht vollständig beschrieben, sondern bestimmte Aspekte detailliert beleuchtet, welche für die Ziele dieser Diplomarbeit entscheidend sind. 4.2.1 DB2-Datenbankmodul: Konzeptuelles Design Auf Grundlage des bereits vorhandenen Demaq Handbuches [46] können die Gegenstände, Beziehungen und Attribute für das ER-Modell [31] identifiziert werden. Darauf aufbauend kann das entsprechende Schema entwickelt werden. Abbildung 8 zeigt einen möglichen Entwurf, der die Daten im Demaq-System übersichtlich darstellt und miteinander in Beziehung setzt. Als Besonderheit werden hierbei zwei Generalisierungen modelliert: Sowohl Queues als auch Slicings sind Container für Nachrichten (Message Container ); und Basic- sowie GatewayQueues gehören zu den Warteschlangen (Queues). Weiterhin ist noch zu beachten, dass einem Slicing genau eine Property-Definition zugeordnet ist, während einem Nachrichtencontainer (und folglich auch den Nachrichten) beliebig viele Property-Definitionen zugewiesen sein können. Der Wert (Value) eines Properties jedoch ist immer genau einer Nachricht zugeordnet. 4.2.2 Schnittstelle zum Nachrichtenspeicher Der Zugriff auf den Nachrichtenspeicher muss derart angepasst werden, dass mit einer Kompilier-Option wahlweise mit NATIX oder der DB2 als Speicher kompiliert werden kann. Dementsprechend bieten sich vier in Frage kommende Entwicklungs-Alternativen: • das NATIX-Interface wird auch für die DB2 abgebildet 32 4.2 Module Architektur Abbildung 8: Das ER-Modell vom Demaq-System • an jeder Stelle im Quelltext, an der NATIX-spezifischer Code auftaucht wird mit #ifdefs wahlweise DB2-spezifischer Code eingefügt 33 4.2 Module Architektur • die bisherige Schnittstelle (NatixGateway) wird unabhängig vom Nachrichtenspeicher entworfen und entsprechend neu implementiert • die bisherige Schnittstelle wird beibehalten und kann mit einem typedef entweder als NatixGateway oder als DB2Gateway kompiliert werden. Die Deklaration des typedefs wird über eine Makrovariable gesteuert, die in der Datei configure.ac gesetzt wird. Das NATIX-Interface nachzubauen ist nicht geeignet, da der Aufwand hierfür im Rahmen einer Diplomarbeit nicht zu bewerkstelligen ist. Diese Option kann für zukünftige Weiterentwicklungen in Erwägung gezogen werden. Der übermäßige Gebrauch von #ifdefs im Quelltext führt zur Unlesbarkeit bzw. Unbeherrschbarkeit des Codes, im besonderen, wenn in Zukunft weitere Alternativen für den Nachrichtenspeicher integriert werden. Aus diesem Grund wird von dieser Variante der Implementierung abgesehen. Zusätzlich läuft sie der Modularisierung entgegen, die eine möglichst hohe Flexibilität mit Blick auf zukünftige Untersuchungen garantieren soll (vgl. Kapitel 3.3.2). Eine Neuimplementierung der NATIX-Schnittstelle wäre bei einer starken Ausrichtung auf diesen Nachrichtenspeichertyp notwendig. Dies ist aber nicht der Fall, da in den Funktionssignaturen des NatixGateways kein NATIX-spezifischer Code vorkommt. Als beste Wahl bietet sich demnach die dargestellte Alternative mit einem typedef an. 4.2.3 Schnittstelle zur Regelauswertung: Saxon In dieser Version des Demaq-Systems soll die Regelauswertung weiterhin mit Saxon ausgeführt werden. Demnach gibt es für die Realisierung zwei Optionen: • die Regelauswertung mit Saxon wird neu implementiert • der Teil von NATIX, der die Regelauswertung im aktuellen System durchführt, wird weiterverwendet und eine Zugriffsmöglichkeit aus NATIX auf 34 4.2 Module Architektur Tabelle 2: Erweiterung der Fragment/View -Matrix von Seite 8 die DB2 wird ergänzt In dem ersten Fall, dass NATIX bei der Regelauswertung nicht mehr eingesetzt wird, müsste die Regelauswertung noch einmal vollständig neu implementiert werden. Dies wäre mit einem hohen Aufwand verbunden, da z.B. die Query Vorbereitung, die Callback -Funktionalität und das Parsen der XML-Dokumente erneut umgesetzt werden müsste. Auf der anderen Seite ist die gesamte Funktionalität zur Regelauswertung mit Saxon bereits im NATIX-System integriert. Dabei werden von NATIX die Konzepte der Fragmente und Sichten (vgl. Abschnitt 2.2.1) genutzt, die sich leicht um zusätzliche Quellen für XML-Daten erweitern lassen. So kann einfach ein Fragmenttyp DB2Document realisiert werden, der in verschiedenen Sichten geöffnet werden kann (vgl. Tabelle 2). Auf diese Weise kann die Regelauswertung von NATIX wiederverwendet werden, ohne an dem Ablauf selbst etwas zu ändern. Nur die Behandlung der Callback -Funktionalität (vgl. auch Kapitel 2.2.1.4) ist hierbei anzupassen. Zu diesem Zweck müssen die Callback-Services innerhalb der Datei saxonxqueryquerystreamviewfactory.cc so geändert werden, dass sie über SQL-Ausdrücke, die an die DB2 weitergeleitet werden, die gewünschten 35 4.2 Module Architektur Daten liefern. Beispielsweise könnte folgendes Sprachkonstrukt: (: ... 2 :) qs : queue ( ’ queue1 ’ ) (: ... :) innerhalb des Callback-Handler s mit folgendem SQL-Statement an die DB2 weitergeleitet werden: 1 SELECT message FROM me ssa g es 3 WHERE queuename= ’ queue1 ’ ; und das Ergebnis an Saxon zurückgeliefert werden. Auf diese Weise können für alle Demaq-spezifischen Sprachkonstrukte die Callback-Services für die DB2 implementiert werden. Über eine Kompilier-Option kann dann die Datei saxonxqueryquerystreamviewfactory.cc wahlweise für die DB2 oder NATIX kompiliert werden. Aus diesem Grund wird von einer Neuimplementierung der Regelauswertung mit Saxon abgesehen, da diese sehr arbeitsintensiv wäre, aber ansonsten keine weiteren Vorteile hätte. Stattdessen wird die Regelauswertung von NATIX wiederverwendet, die um einen Fragmenttyp DB2Document erweitert wird. 4.2.4 DB2-Fassade Die Implementierung der Funktionen zum Zugriff auf die DB2 wird in einer Fassade [42] als eigenständige Shared Library umgesetzt. Hierbei macht es die geplante Realisierung der Integration der DB2 in das Demaq-Ausführungssystem notwendig, dass sowohl das Demaq-System selbst als auch NATIX auf das relationale DBMS zugreifen können (vgl. Kapitel 4.2.3). Würde der verwendete Code innerhalb des NATIX-Projektes angesiedelt werden, so wäre Demaq immer abhängig von NATIX, auch wenn das System mit der DB2 als Nachrichtenspeicher und Regelauswerter kompiliert würde. Auf der anderen Seite könnte die Funktionali36 4.2 Module Architektur Abbildung 9: Abhängigkeiten von Komponenten und Modulen im Demaq-System. (a) Durch Integration der Kommunikation mit der DB2 in den Demaq-Kern entstehen zyklische Abhängigkeiten. (b) Als eigenständiges Projekt können die zyklischen Abhängigkeiten aufgelöst werden. tät zum Zugriff auf die DB2 voll in das Demaq-Projekt integriert werden. Dann allerdings würde sich eine zirkuläre Abhängigkeit ergeben. In diesem Fall wäre NATIX abhängig vom Demaq-Code und umgekehrt auch der Demaq-Kern abhängig von NATIX, da NATIX zur Regelauswertung benutzt wird. Aus diesem Grund muss die Funktionalität der DB2 als eigenständiges Modul ausgegliedert werden (wie in Abbildung 9 dargestellt). 4.2.5 DB2-Datenbankmodul: Varianten der Abbildung von Slices Grundsätzlich existieren zwei Varianten, auf welche Weise Slicings im DemaqSystem behandelt werden. In der ersten Variante werden die Slicing-Definitionen vom DQL-Compiler durch Rewrites ersetzt. Hierdurch werden Slicings als Queues mit einem Property aufgefasst. In diesem Fall werden alle Slicing-Properties in der Tabelle für Warteschlangen-Properties gespeichert und nicht gesondert behandelt. In der zweiten Variante werden Slices nativ verarbeitet, d.h. für sie wird gesondert Speicherplatz zur Verfügung gestellt. Folglich kann die Behandlung der Slices isoliert optimiert werden, wodurch die Effizienz erhöht werden kann. Da 37 4.2 Module Architektur die Optimierung des Leistungsverhaltens eine Anforderung dieser Diplomarbeit ist (vgl. Kapitel 3.3.3), wird eine native Unterstützung implementiert. Vorschläge für mögliche Abbildungen von Slices werden in Kapitel 5.1.5 vorgestellt. 38 Feinentwurf 5 Feinentwurf In diesem Kapitel werden die konzeptionellen Entwürfe aus Kapitel 4 auf logischer Ebene betrachtet und detailliert verfeinert. Dabei werden die Anforderungen und Ziele aus Kapitel 3 weiter verfolgt. Die Enwürfe auf logischer Ebene werden bezogen auf die zu entwickelnden Varianten vorgestellt. Zunächst wird das Demaq-System mit der DB2 und Saxon (Kapitel 5.1) und anschließend das System, das die DB2 auch zur Regelauswertung verwendet (Kapitel 5.2), betrachtet. 5.1 Demaq mit der DB2 und Saxon In der System-Variante von Demaq mit der DB2 als Nachrichtenspeicher und Saxon als Regelauswerter werden neben allen Nachrichten, auch alle sonstigen relevanten Daten, wie beispielsweise Properties oder Rules, in der DB2 gespeichert. Eine mögliche relationale Modellierung der Daten wird in diesem Kapitel vorgestellt. Zu diesem Zweck wird das bereits entworfene ER-Diagramm (vgl. Abschnitt 4.2.1) in ein logisches Schema (in DDL) überführt. Dafür schlägt [31] vor, zunächst jede Entität und Beziehung als eigene Relation zu berücksichtigen. Nachdem dies in Kapitel 5.1.1 erfolgt ist, werden in Abschnitt 5.1.2 Verfeinerungen an dem Schema vorgenommen, um überflüssige Relationen und Redundanzen zu bereinigen. Anschließend wird in Abschnitt 5.1.3 das verfeinerte Schema teilweise noch einmal überarbeitet, um es den Gegebenheiten im aktuellen DemaqSystem anzupassen. In Kapitel 5.1.4 werden verschiedene Varianten für die Abbildung der Nachrichten-Warteschlangen des Demaq-Systems auf ein relationales Model vorgestellt. Die Möglichkeiten bei der Umsetzung sind allerdings sehr umfangreich, so dass kein Anspruch auf Vollständigkeit erhoben werden kann. Vielmehr sollen die vorgestellten Varianten verschiedene Denkansätze illustrieren und somit mögliche Richtungen für Weiterentwicklungen aufzeigen. 39 5.1 Demaq mit der DB2 und Saxon Feinentwurf Nachdem die Datenmodellierung abgehandelt wurde, werden in Kapitel 5.1.6 die Änderungen des Quelltextes im Demaq-Kern besprochen. Da in dieser SystemVariante NATIX weiterverwendet wird (vgl. Abschnitt 4.2.3), befasst sich Abschnitt 5.1.7 mit den Erweiterungen im NATIX-Code, die notwendig sind, um mithilfe der NATIX-Konzepte (vgl. Kapitel 2.2.1) auf Daten in der DB2 zugreifen zu können. Abschließend beleuchtet Kapitel 5.1.8 die Implementierung der DB2-Fassade, die unabhängig von Demaq und NATIX umgesetzt wird (vgl. Abschnitt 4.2.4). 5.1.1 Überführung des ER-Diagramms in ein logisches Schema Anhand des modellierten ER-Diagramms (vgl. Abbildung 8 auf Seite 33) werden alle Entitäten und Beziehungen in Relationen überführt. Es ergeben sich hieraus die im Folgenden dargelegten Tabellen-Definitionen für Daten im Demaq-System. 5.1.1.1 Regeln Regeln bestehen aus einem eindeutigen Namen, über den sie identifiziert werden, sowie einem gültgen XQuery-Ausdruck. Der XQueryAusdruck ist hierbei nicht in seiner Länge beschränkt. Deshalb wird für diesen der Datentyp CLOB gewählt. 1 create table r u l e s ( name 3 varchar ( 2 5 5 ) expression clob not null , not null , primary key ( name ) 5 ); 5.1.1.2 Warteschlangen Warteschlangen werden durch ihren Namen iden- tifiziert. Des Weitern kann ihnen eine Priorität zugeordnet werden, die derzeit noch nicht im Demaq-System berücksichtigt wird. Der mode einer Warteschlange ist entweder transient oder persistent, wobei aktuell alle Queues persistenziert werden. Der Typ der Warteschlange wird im Attribut kind festgehalten. Er kann 40 5.1 Demaq mit der DB2 und Saxon Feinentwurf entweder basic, incoming oder outgoing sein. Der port ist die Anschlussadresse, die die Kommunikation über ein Netzwerk mit der Warteschlange erlaubt (nur bei den Gateway-Typen incoming und outgoing). Das interface legt für GatewayQueues das zugehörige Protokoll für die Kommunikation über ein Netzwerk fest, möglich sind beispielsweise SMTP oder HTTP. 1 create table queues ( name 3 varchar ( 2 5 5 ) not null , p r i o r i t y smallint not null default 0 , −− mode : 0= p e r s i s t e n t ,1= t r a n s i e n t 5 mode smallint not null default 0 check ( mode in ( 0 , 1 ) ) , −− k i n d : 0=b a s i c ,1= incoming ,2= o u t g o i n g 7 9 kind smallint not null default 0 port int check ( kind in ( 0 , 1 , 2 ) ) , not null check ( p o r t between 1024 and 6 5 5 3 5 ) , interface varchar ( 5 1 2 ) not null default ’ h t t p : / / ’ , primary key ( name ) 11 ) ; 5.1.1.3 Nachrichten Nachrichten können über eine ID eindeutig über alle Warteschlangen hinweg identifiziert werden. Die Nachricht selbst wird im XMLFormat gespeichert. Ihr Zustand (state) kann entweder enqueued oder deleted sein, da im Modus Persistent Nachrichten nur als gelöscht markiert, aber nicht tatsächlich physisch gelöscht werden. 1 create table me ssa g es ( 3 i d int not null , message xml not null , −− s t a t e : 0=enqueued ,1= d e l e t e d 5 s t a t e smallint not null default 0 primary key ( i d ) 7 ); 41 check ( s t a t e in ( 0 , 1 ) ) , 5.1 Demaq mit der DB2 und Saxon 5.1.1.4 Feinentwurf Eigenschaften Eigenschaften (Properties) zeichnen sich durch einen eindeutigen Namen aus und haben einen Typ, der einem Datentyp des XQuery Datenmodells [10] entspricht. Falls nicht explizit ein Datentyp für eine Eigenschaft angegeben wird, wird der Typ implizit auf xs:anyType gesetzt. 1 create table p r o p e r t i e s ( 3 name varchar ( 2 5 5 ) not null , type varchar ( 2 5 5 ) not null default ’ xs : anyType ’ , primary key ( name ) 5 ); 5.1.1.5 Slicings Slicings werden über einen eindeutigen Namen gekennzeich- net. 1 create table s l i c i n g s ( s l i c i n g n a m e varchar ( 2 5 5 ) 3 not null , primary key ( s l i c i n g n a m e ) ); 5.1.1.6 Schemata Ein XML-Schema wird durch seine zugewiesene eindeuti- ge URI identifiziert. Das eigentliche Schema ist im XML-Format speicherbar. create table schema ( 2 uri varchar ( 5 1 2 ) schema 4 xml not null , not null , primary key ( u r i ) ); 5.1.1.7 Beziehung Warteschlangen-Regel Jeder Warteschlange können mehrere Regeln zugeordnet werden. Eine Regel kann aber nur einer Queue zugeordnet sein. Regeln und Warteschlangen werden jeweils durch ihre Namen repräsentiert. 42 5.1 Demaq mit der DB2 und Saxon Feinentwurf 1 create table q u e u e r u l e ( rulename varchar ( 2 5 5 ) 3 queuename not null , varchar ( 2 5 5 ) not null , primary key ( rulename , queuename ) 5 ); 5.1.1.8 Beziehung Slicing-Regeln Jedem Slicing können mehrere Regeln zugeordnet werden. Umgekehrt kann eine Regel aber nur einem Slicing zugeordnet sein. Außerdem kann eine Regel nur entweder auf einer Queue oder einem Slicing definiert sein. In der Beziehung Slicing-Regeln werden Regeln und Slicings jeweils durch ihren Namen repräsentiert. 1 create table q u e u e r u l e ( rulename varchar ( 2 5 5 ) 3 not null , s l i c i n g n a m e varchar ( 2 5 5 ) not null , primary key ( rulename , queuename ) 5 ); 5.1.1.9 Beziehung Warteschlange zu Antwort-Warteschlange Gateway-Queues haben maximal genau eine Antwort-Warteschlange, so dass requestqueue als Primärschlüssel verwendet werden kann. Eine Antwort-Queue kann nur einmal als solche verwendet werden. Deshalb muss responsequeue eindeutig (unique) sein. 1 create table r e s p o n s e q u e u e ( 3 requestqueue varchar ( 2 5 5 ) not null , responsequeue varchar ( 2 5 5 ) not null , primary key ( r e q u e s t q u e u e ) , 5 unique ( responsequeue ) ); 43 5.1 Demaq mit der DB2 und Saxon 5.1.1.10 Feinentwurf Beziehung -Warteschlange zu Regeln Zu jeder Regel kann eine Queue zur Behandlung von Errors bestimmt werden. Eine Error-Warteschlange kann aber zu mehreren Regeln zugeordnet sein. Deshalb kann der Regelname in dieser Beziehung als Primärschlüssel verwendet werden. create table h a n d l e e r r o r ( 2 rulename varchar ( 2 5 5 ) queuename 4 not null , varchar ( 2 5 5 ) not null , primary key ( rulename ) ); 5.1.1.11 Beziehung Schema zu Warteschlangen Diese Beziehung stellt eine optionale Zuordnung eines Schemas zur Nachrichten-Validierung einer oder mehrerer Warteschlangen dar. 1 create table queue schema ( 3 schemauri varchar ( 2 5 5 ) not null , queuename varchar ( 2 5 5 ) not null , primary key ( queuename ) 5 ); 5.1.1.12 Beziehung Nachricht-Warteschlange Jede Nachricht muss ge- nau einer Warteschlange zugeordnet sein. Hieraus folgt, dass msgid als Primärschlüssel eingesetzt werden kann. 1 create table msg queue ( 3 msgid int not null , queuename varchar ( 2 5 5 ) not null , primary key ( msgid ) 5 ); 5.1.1.13 Beziehung Eigenschaftswerte-Nachricht Nachrichten können keine, eine oder mehrere Properties besitzen. Für jede Nachricht werden alle Ei44 5.1 Demaq mit der DB2 und Saxon Feinentwurf genschaftswerte in dieser Tabelle gespeichert. Da der Wert für jede Nachricht anders sein kann, wiederholen sich die Eigenschaftsnamen häufig. Demnach existiert keine Spalte, die eindeutig ist. Als Primärschlüssel eignen sich aber die Spalten propertyname und msgid. Der Wert einer Eigenschaft kann atomar oder vom Typ XML sein und ist grundsätzlich nicht beschränkt. Deshalb wird für zugehörige Spalte der Datentyp CLOB gewählt. 1 create table m s g p r o p e r t y ( propertyname 3 5 varchar ( 2 5 5 ) msgid int not null , value clob not null , not null , primary key ( propertyname , msgid ) ); 5.1.1.14 Beziehung Eigenschaften-Warteschlangen Die Definitionen für Eigenschaften, welche die Auswertung der Werte für einzelne Nachrichten bestimmen, werden in dieser Tabelle gespeichert. Dabei können die Eigenschaften mit gleichem Namen und unterschiedlichen Definitionen verschiedenen Warteschlangen zugeordnet sein. Deshalb kommen als Primärschlüssel nur die Spalten queuename und propertyname gemeinsam in Frage. Die valueexpression ist ein XQuery-Ausdruck, der definiert, wie der Wert der Eigenschaft auszuwerten ist. Dieser XQuery-Ausdruck ist in der Länge nicht beschränkt. Aus diesem Grund wird für die Spalte valueexpression der Datentyp CLOB gewählt. create table q u e u e p r o p e r t y ( 2 queuename varchar ( 2 5 5 ) propertyname 4 valueexpression not null , varchar ( 2 5 5 ) not null , clob not null , −− f i x e d : 0= f a l s e ,1= t r u e 6 f i x e d smallint not null default 0 −− i n h e r i t e d : 0= f a l s e ,1= t r u e 45 check ( f i x e d in ( 0 , 1 ) ) , 5.1 Demaq mit der DB2 und Saxon 8 inherited Feinentwurf smallint not null default 0 check ( i n h e r i t e d in ( 0 , 1) ) , primary key ( queuename , propertyname ) 10 ) ; 5.1.1.15 Beziehung Eigenschaft-Slicing Einem Slicing muss genau ein Property aus der Tabelle queue_property als Slicing-Property zugeordnet werden. create table s l i c i n g p r o p e r t y ( 2 s l i c i n g n a m e varchar ( 2 5 5 ) propertyname 4 not null , varchar ( 2 5 5 ) not null , primary key ( s l i c i n g n a m e ) ); 5.1.2 Verfeinerung der DDL Relationen können unter bestimmten Bedingung zusammengefasst werden [31]. Die daraus resultierenden Verfeinerungen für die Tabellen-Definitionen werden in diesem Kapitel dargestellt. Auf Tabellen, die nicht weiter verfeinert werden können, wird im Folgenden nicht weiter eingegangen. 5.1.2.1 Zusammenfassung Regeln und Error-Queues Da für jede Regel nur eine oder keine Error-Queue definiert ist, können die beiden betreffenden Tabellen zusammengefasst werden. Die Tabelle handle_error fällt demnach weg bzw. wird in die Tabelle rules integriert: 1 create table r u l e s ( name 3 varchar ( 2 5 5 ) expression clob not null , not null , errorqueuename varchar ( 2 5 5 ) , 5 primary key ( name ) ); 46 5.1 Demaq mit der DB2 und Saxon 5.1.2.2 Zusammenfassung Feinentwurf Warteschlangen mit der Queue- Resonsequeue-Beziehung Da es zu jeder Warteschlange maximal eine Antwort-Warteschlange gibt, kann die Tabelle für die Zuordnung der AntwortWarteschlange in die Warteschlangentabelle integriert werden: create table queues ( 2 name varchar ( 2 5 5 ) not null , p r i o r i t y smallint not null default 0 , −− mode : 0= p e r s i s t e n t ,1= t r a n s i e n t 4 mode smallint not null default 0 check ( mode in ( 0 , 1 ) ) , −− k i n d : 0=b a s i c ,1= incoming ,2= o u t g o i n g 6 8 kind smallint not null default 0 port int check ( p o r t between 1024 and 6 5 5 3 5 ) , interface 10 check ( kind in ( 0 , 1 , 2 ) ) , varchar ( 5 1 2 ) , responsequeue varchar ( 2 5 5 ) , primary key ( name ) 12 ) ; 5.1.2.3 Zusammenfassung Nachrichten und Nachricht- Warteschlange-Beziehung Jede Nachricht, repräsentiert durch ihre eindeutige ID, kann nur in genau einer Warteschlange enthalten sein. Wird sie in eine weitere Warteschlange eingereiht, bekommt sie eine neue eindeutige ID. Auf diese Weise kann sie immer genau einer Warteschlange zugeordnet werden. create table me ssa g es ( 2 i d int not null , queuename 4 message varchar ( 2 5 5 ) xml not null , not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 6 s t a t e smallint not null default 0 primary key ( i d ) 8 ); 47 check ( s t a t e in ( 0 , 1 ) ) , 5.1 Demaq mit der DB2 und Saxon 5.1.2.4 Zusammenfassung von Feinentwurf Slicings und Slicing-Property- Beziehung Jedes Slicing in Demaq ist genau auf einem Property definiert. Deshalb ist keine eigenständige Beziehung für die Zuordnung der Slicings zu Properties notwendig. Die Tabellen slicings und slicing_property können so zu folgender Tabelle zusammengefasst werden: create table s l i c i n g s ( 2 s l i c i n g n a m e varchar ( 2 5 5 ) propertyname 4 varchar ( 2 5 5 ) not null , not null , primary key ( s l i c i n g n a m e ) ); 5.1.2.5 Wegfall Schemata und Schema-Queue-Beziehung Eine Validie- rung von eingereihten Nachrichten anhand eines Schemas wird von Demaq derzeit noch nicht unterstützt. Außerdem gibt es in der DB2 das XML Schema Repository, das die Validierung von XML-Daten mithilfe eines XML-Schemas automatisch vornehmen kann [27]. So kann eine Validierung von Nachrichten auf einfache Weise erfolgen, ohne eine eigene Verwaltung implementieren zu müssen. Die Tabellen zur Schema-Validierung können deshalb wegfallen. 5.1.3 Weitere Anpassungen des logischen Designs In diesem Abschnitt werden noch einmal Änderungen am logischen Design vorgenommen. Zum einen sind Anpassungen an Gegebenheiten des bisherigen DemaqSystems notwendig (Abschnitt 5.1.3.1). Zum anderen sind Besonderheiten mit der DB2 als Nachrichtenspeicher zu beachten (Abschnitt 5.1.3.2). 5.1.3.1 Anpassungen an das Demaq-Ausführungssystems Einige Da- ten, die im ER-Diagramm als Attribute modelliert wurden und somit als DatenSpalte in einer der Relationen definiert wurden, werden im aktuellen DemaqAusführungssystem als Properties gespeichert. Demnach können folgende Spalten 48 5.1 Demaq mit der DB2 und Saxon Feinentwurf weggelassen werden: Tabelle Warteschlangen: Die Daten in den Spalten priority, kind, port, interface und responsequeue werden in der Tabelle queue_property als Property einer Warteschlange gespeichert. Tabelle Regeln: Die Regeln und die Zuordnungen von Error- Warteschlangen zu Regeln werden als Properties gespeichert. Deshalb kann die Tabelle Regeln weggelassen werden. Ebenso wird die Tabelle queue_rule überflüssig. 5.1.3.2 Anpassungen an DB2 Um eine Nachricht aus der DB2 zu laden, muss bekannt sein, welche Länge diese Nachricht hat, da die Verbindung standardmäßig einen Buffer mit begrenzter Größe (32767) verwendet [33]. Ist die Nachricht länger als diese Standardgröße, so wird sie ohne Fehlermeldung nur zum Teil übertragen. Deshalb muss die Größe des Buffer s ab einer bestimmten Nachrichtenlänge explizit vergrößert werden. Die Länge von XML-Daten kann von DB2 allerdings nicht festgestellt werden, ohne diese zu serialisieren. Da dies ein hoher Aufwand ist, wird die Länge jeder Nachricht bereits beim übertragen an die Datenbank in einer zusätzlichen Spalte messagesize in der messages-Tabelle gespeichert. 5.1.4 Varianten der Warteschlangenabbildung In Demaq werden Warteschlangen (Queues) nach dem FIFO-Prinzip bearbeitet. Eine Einhaltung des Prinzips wird aber nicht garantiert, um dem System bei der Ausführung Freiheitsgrade zur Optimierung einzuräumen. Auf diese Weise muss das System nicht auf die abschließende Abarbeitung einer Nachricht warten, sondern kann schon mit der Bearbeitung der nächsten Nachricht beginnen. 49 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 10: Implementierung einer Warteschlange [9]. (a) Implementierung in einem Array. (b) Implementierung als verkettete Liste Warteschlangen können auf verschiedene Art und Weise implementiert werden. Beispielsweise schlägt [9] die Implementierung in einem Array oder als verkettete Liste vor (vgl. Abbildung 10). Allerdings können derartige native Datenstrukturen in einem relationalen DBMS nicht verwendet werden. Folglich stellt sich die Frage, ob ähnliche Datenstrukturen über Relationen nachzubilden ist oder ob es besser ist, einen grundsätzlich abweichenden Ansatz zu wählen. Das Ziel dieser Diplomarbeit ist es, die DB2 in das Demaq-Ausführungssystem zu integrieren. Dabei spielt das Leistungsverhalten eine wichtige Rolle (vgl. Abschnitt 3.3.3). Aus diesem Grund soll eine effiziente Abbildung für Warteschlangen in einer relationalen Datenbank gefunden werden. Dementsprechend werden in diesem Kapitel beispielhaft mehrere unterschiedliche Abbildungsmöglichkeiten vorgestellt. Auf der Grundlage von theoretischen Bewertungsaspekten wird eine Auswahl der Abbildungsvarianten getroffen, die in geeigneten Experimenten innerhalb des Demaq-Ausführungssystems auf ihre Leistungsfähigkeit getestet werden sollen (siehe Kapitel 7.2). Die Varianten mit ihren Bewertungsaspekten werden in einer tabellarischen Übersicht in Kapitel 5.1.4.8 zusammengefasst. Aufgrund der besseren Übersichtlichkeit werden die vorgestellten Möglichkeiten der Warteschlangenabbildung in den Abschnitten auf physischer Ebene opti- 50 5.1 Demaq mit der DB2 und Saxon Feinentwurf miert. Obwohl die physische Optimierung über eine logische Betrachtung hinausgeht, soll auf diese Weise die Lesbarkeit gewahrt bleiben, indem eine allzu Große Fragmentierung vermieden wird. Dieses Kapitel fällt somit im Hinblick auf die Gesamtstruktur dieser Arbeit aus dem Rahmen. 5.1.4.1 Variante 1: Einfache Relation Die erste Variante ist die einfachste Implementierung, um Warteschlangen in einem relationalen DBMS abzubilden. Dabei wird die Abbildung mithilfe einer einfachen Relation umgesetzt, in der alle Daten der Warteschlangen gespeichert werden. Logischer Entwurf: In der Tabelle, in der die Daten der Warteschlangen gespeichert werden, wird eine Spalte mit einer Identifikation (ID) benötigt, mit der eine Nachricht eindeutig (über alle Warteschlangen hinweg) identifiziert werden kann. Aus diesem Grund können alle eingehenden Nachrichten unter Zuhilfenahme einer Sequence durchnummeriert werden. Gleichzeitig kann hierdurch die zeitliche Reihenfolge des Eingangs der Nachrichten festgehalten werden, da die Sequence die IDs in aufsteigender Reihenfolge vergibt. Die Nachricht mit der kleinsten ID ist also diejenige, die am längsten in einer Warteschlange ist und demnach als nächstes verarbeitet werden muss. Auf diese Weise kann eine zusätzliche Spalte mit einem timestamp eingespart werden. Des Weiteren wird eine Spalte benötigt, um in ihr den aktuellen Status (enqueued oder processed ) einer Nachricht zu speichern. Denn in dem derzeitigen Demaq-Ausführungssystem wird nur der Modus ”persistent“ unterstützt, bei dem verabeitete Nachrichten nicht gelöscht, sondern nur als verarbeitet (processed ) markiert werden. Um mehrere Warteschlangen in einer Relation abzubilden, bedarf es einer weiteren Spalte, um die Warteschlangenzugehörigkeit zu speichern. Dies kann mit einer Spalte für den Warteschlangenname erreicht werden. Das SQL-DDLStatement zum Erzeugen der Tabelle sieht wie folgt aus: 51 5.1 Demaq mit der DB2 und Saxon Feinentwurf 1 create table me ssa g es ( i d int 3 not null , queuename message varchar ( 2 5 5 ) xml not null , not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 5 s t a t e smallint not null default 0 7 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ); Abbildung 11: Warteschlangen als einfache Relation Wie in Abbildung 11 dargestellt, können die Funktionen enqueue und dequeue als einfache SQL-Statements ausgedrückt werden. Dabei ist es wichtig, dass die Funktionen isoliert voneinander ausgeführt werden, damit nicht z.B. zwischen Schritt 1 und 2 der dequeue-Funktion in der Abbildung 11 eine andere Transaktion die gleiche Nachrichten-ID als Minimum wählt. Ansonsten wäre es möglich, dass Nachrichten mehrmals abgearbeitet werden. Aus diesem Grund dürfen keine dequeue-Funktionen nebenläufig auf einer Tabelle ausgeführt werden. Zu Erreichen ist dies z.B. durch die Umsetzung als Prozedur mit einem zusammengesetzten atomaren SQL-Statement (vgl. beispielsweise [47]). 52 5.1 Demaq mit der DB2 und Saxon Feinentwurf Physischer Entwurf: Um den direkten Zugriff auf eine Nachricht zu beschleunigen, wird ein Index auf der Spalte für die Nachrichten-ID benötigt. In der DB2 wird auf dem Primärschlüssel einer Relation immer implizit ein Index angelegt [34], so dass kein Index explizit erzeugt werden muss, da die Spalte id bereits als Primärschlüssel gekennzeichnet ist. Um die Funktion dequeue möglichst performant auszuführen, müsste auf der Spalte state ein Index erzeugt werden, der die Spalten queuename und id in dieser Reihenfolge inkludiert [17]. Dies ist aber aus zwei Gründen nicht möglich und bei genauerer Betrachtung auch nicht sinnvoll. Erstens ist die Spalte state nicht eindeutig, so dass auf ihr kein Index definiert werden kann, der andere Spalten inkludiert. Zweitens rechtfertigt der Aufwand zur Pflege des Index auf der state-Spalte den Einsatz nicht. Denn bei jedem Zugriff mit dequeue auf eine Nachricht wird deren Status von enqueued auf processed geändert und der Index muss umstrukturiert werden. Ein sinnvoller Index für diese Variante sollte auf der Spalte queuename erzeugt werden. Da sich die Spalte queuename für eine Nachricht nie ändert und über sie ein Großteil der Nachrichten gefiltert werden kann, bleibt diese als beste Alternative, um darauf einen Index zu erzeugen: create index queuenamendx 2 on me ssa g es ( queuename ) ; Mit jedem insert wird ein exklusiver Lock bei den enqueue-Operationen gehalten. Obwohl die neu eingefügte Zeile nicht in der dequeue-Operation berücksichtigt werden muss, blockiert sie die Ausführung der Operation, da der Ausdruck ”SELECT min(id)...“ auf die Freigabe der Sperre warten muss. Dies kann verhindert werden, indem die DB2 Option DB2_SKIPINSERTED=on gewählt wird [43]. Damit werden inserts, die noch nicht mit commit bestätigt wurden, behandelt als würden sie nicht existieren. In der DB2 Version für z/OS kann zusätzlich der Zusatz ”SKIP LOCKED DATA“ 53 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 12: Warteschlangen als einfache Relation (optimiert) in der dequeue-Funktion verwendet werden. Dadurch werden Datenzeilen, die durch Update-Operationen exklusiv gesperrt sind, ignoriert und die Nebenläufigkeit kann erhöht werden [29]. Eine weitere Optimierung auf der Ebene der einzelnen SQL-Statements ist dadurch möglich, dass diese in ein zusammengefasstes Statement überführt werden. Abbildung 12 zeigt wie die Funktionen dequeue und enqueue jeweils in einem SQL-Ausdruck implementiert werden können. Auf diese Weise kann der Anfrage-Optimierer der DB2 über alle Einzelausdrücke hinweg eine Optimierung vornehmen [3]. Theoretische Bewertung: Nachteilig ist in dieser Variante, dass durch die Update-Operation innerhalb der dequeue-Funktion auf der state-Spalte ein exklusiver Lock gehalten wird. Dadurch wird verhindert, dass mehrere Transaktionen gleichzeitig Nachrichten mit dequeue entnehmen können. Denn ein zweiter dequeue-Aufruf würde wieder ein Minimum selektieren, das aber nicht selektiert werden kann, solange die exklusive Sperre besteht. Zur Lösung dieses Problems 54 5.1 Demaq mit der DB2 und Saxon Feinentwurf darf an dieser Stelle kein Uncommited Read zugelassen werden. Ansonsten werden Nachrichten gelesen, die gerade mit enqueue von einer anderen Transaktion eingefügt werden und noch nicht mit commit bestätigt wurden. In diesem Fall würden Nachrichten weiterverarbeitet, die später potenziell durch ein rollback wieder entfernt werden und deshalb nicht hätten weiterverarbeitet werden dürfen. In der DB2 Version für z/OS könnte das Problem des Locks allerdings umgangen werden, indem der Zusatz ”SKIP LOCKED DATA“ verwendet wird [29]. 5.1.4.2 Variante 2: Mehrere Einfache Relationen Um das Problem der exklusiven Sperre der Variante in Kapitel 5.1.4.1 teilweise zu umgehen, können die Sperren auf einzelne Queues beschränkt werden, indem für jede Warteschlange eine eigene Tabelle verwendet wird. Abbildung 13: Warteschlangen als mehrere einzelne Relationen Logischer Entwurf: Der logische Entwurf für die Tabellen einzelner Warteschlangen entspricht im Wesentlichen dem der Variante in Kapitel 5.1.4.1, nur 55 5.1 Demaq mit der DB2 und Saxon Feinentwurf dass die Spalte queuename überflüssig wird. Das SQL-DDL-Statement sieht, beispielsweise für eine Warteschlange mit dem Namen ”queue1“, wie folgt aus: create table queue1 ( 2 i d int not null , message xml not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 4 s t a t e smallint not null default 0 6 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ); Damit auf Nachrichten nur mithilfe ihrer ID zugegriffen werden kann, muss eine zusätzliche Tabelle verwaltet werden, in der gespeichert wird, in welcher Warteschlange sich die Nachricht mit einer spezifischen ID befindet. Diese Tabelle muss nur zwei Spalten enthalten: Eine für die Nachrichten-ID und eine, die den Tabellennamen der Warteschlange enthält. 1 create table message queue ( i d int 3 queuename not null , varchar ( 2 5 5 ) not null , primary key ( i d ) 5 ); Der Zugriff mit den Funktionen enqueue und dequeue muss für jede Warteschlange individualisiert sein. Abbildung 13 zeigt wie dies durch einzelne SQLStatements umgesetzt werden kann. Physischer Entwurf: Wie in dem physischen Entwurf der Variante in Kapitel 5.1.4.1 bereits diskutiert, muss kein zusätzlicher Index erzeugt werden, da die einzige in Frage kommende Spalte queuename hier nicht existiert. Durch die Deklaration der Nachrichten-ID als Primärschlüssel in der Warteschlangen-Tabelle und der Tabelle message_queue wird implizit ein Index von DB2 generiert [34]. Wie bereits in der Variante in Kapitel 5.1.4.1 ausführlich beschrieben, kann mit der DB2 Option DB2_SKIPINSERTED=on verhindert werden, dass inserts 56 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 14: Warteschlangen als mehrere einzelne Relationen (optimiert) blockierend wirken [43]. So können enqueue- und dequeue-Operationen nebenläufig ausgeführt werden. Allgemeiner kann mit der DB2 Version für z/OS der Ausdruck ”SKIP LOCKED DATA“ bei der dequeue-Funktion verwendet werden [29]. Ein Uncommited Read kann aber auch in dieser Variante nicht zugelassen werden, da ansonsten Nachrichten aus nicht abschließend mit commit bestätigten enqueue-Operationen weiterverarbeitet werden können. Die einzelnen SQL-Statements in den Funktionen enqueue und dequeue können wieder zusammengefasst werden (siehe Abbildung 14), um eine bessere automatische Optimierung zu erreichen [3]. Theoretische Bewertung: Der Vorteil bei der Verwaltung jeder Warteschlange in einer eigenen Tabelle ist, dass eine Filterung über den Queue-Namen entfällt. Jedoch muss es ein zusätzliches Mapping von Nachrichten-IDs zu Warteschlangen bzw. Tabellen geben, da der eindeutige Identifikator einer Nachricht 57 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 15: enqueue und dequeue auf paarweisen Relationen keinen Aufschluss darüber gibt, in welcher Queue sie zu finden ist. Letztendlich kann diese Variante dennoch von Vorteil sein, da erstens eine Selektion des Minimums ausschließlich über den Index des Primärschlüssels erfolgen kann und deshalb keine Datenseiten geladen werden müssen, um die nächste zu bearbeitende Nachricht zu finden; und zweitens eine exklusive Sperre nur eine Warteschlange (anstatt alle Warteschlangen wie in der Variante in Kapitel 5.1.4.1) blockiert und demnach mehrere dequeue-Operationen gleichzeitig ohne Probleme ausgeführt werden können. 5.1.4.3 Variante 3: Paarweise Relationen Um bei dequeue-Operationen Uncommitted Reads zu erlauben, dürfen auf der betroffenen Tabelle gleichzeitig keine enqueue-Operationen möglich sein. Eine mögliche Lösung ist, dass die Warteschlangen auf zwei Tabellen verteilt werden (in Anlehnung an eine Idee von [37]). Auf diese Weise können auf der einen Tabelle die enqueue- und auf der anderen die dequeue-Operationen unabhängig voneinander ausgeführt wer- 58 5.1 Demaq mit der DB2 und Saxon Feinentwurf den. Sobald keine Nachrichten mehr in der Tabelle mit den dequeue-Operationen enthalten sind, rotieren beide Tabellen, so dass dann die leere Tabelle aufgefüllt und die gefüllte abgearbeitet wird. Das Prinzip dieser Variante wird in Abbildung 15 veranschaulicht. Logischer Entwurf: Eine der Tabellen könnte als Kopfteil der Warteschlange genutzt werden und die andere als Rumpf. Da beide Tabellen während der Laufzeit ihre Eigenschaft als Kopf- bzw. Rumpfteil tauschen (Rotation), werden die Tabellennamen mit dem neutralen Zusatz ”L“ bzw. ”R“ gekennzeichnet. Die Definition beider Tabellen entspricht der Variante in Kapitel 5.1.4.2: 1 create table queue1 L ( 3 i d int not null , message xml not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 5 s t a t e smallint not null default 0 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) 7 ); create table queue1 R ( 9 i d int not null , message xml not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 11 s t a t e smallint not null default 0 13 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ); Ebenso wie in der Variante in Kapitel 5.1.4.2 muss eine zusätzliche Tabelle das Mapping der Nachrichten zu den Warteschlangen speichern, damit auf Nachrichten ausschließlich über deren ID zugegriffen werden kann. Eine Sicht auf die gesamte Warteschlange kann mithilfe einer View erzeugt werden: create view queue1 ( id , message , s t a t e ) as 2 s e l e c t id , message , s t a t e from queue1 L 59 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 16: Warteschlange als paarweise Relationen 4 union a l l s e l e c t id , message , s t a t e 6 from queue1 R Die Zuordnung von Tabellen-Kopfteil und -Rumpf, kann im Hauptspeicher verwaltet werden. Physischer Entwurf: Außer den implizit erzeugten Indizes auf den Nachrichten-IDs werden keine weiteren Indizes erzeugt. Abbildung 16 skizziert den Entwurf der Variante mit paarweisen Relationen. Für jede Warteschlange müssen nicht nur zwei Tabellen angelegt werden, sondern für jede dieser Tabellen müssen für die dequeue- und enqueue-Operationen individuelle SQL-Statements erzeugt werden. Abbildung 17 zeigt eine optimierte Version dieser Variante, in der die getrennten SQL-Statements zu atomaren Ausdrücken zusammengefasst wurden, um eine verbesserte automatische Optimierung zu erreichen [3]. Alle Statements der de- 60 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 17: Warteschlange als paarweise Relationen (optimiert) queue-Operation können außerdem mit dem Zusatz ”WITH UR“ ausgeführt werden, durch den die Ausdrücke als Uncommitted Read ausgeführt werden. Die Abbildung 17 zeigt außerdem die Tabellenzuordnung nach der Rotation, während Abbildung 16 die Zuordnung vor der Rotation abbildet. Abbildung 18: Warteschlange als paarweise Relationen blockiert vor der Rotation 61 5.1 Demaq mit der DB2 und Saxon Feinentwurf Theoretische Bewertung: Ein Vorteil bei dieser Variante ist, dass die Funktionen enqueue und dequeue auf unterschiedlichen Tabellen ausgeführt werden. Dadurch kann die Nebenläufigkeit erhöht werden, indem die dequeueFunktion mit einem Zusatz als Uncommitted Read ausgeführt werden kann. Auf diese Weise können keine Nachrichten gelesen werden, die gerade mit enqueue eingefügt, aber noch nicht mit commit bindend bestätigt wurden. Sobald die Rumpf-Tabelle leer ist, kann sie mit der Kopftabelle vertauscht werden (Rotation). Ein Nachteil dabei ist, dass der Tausch erst dann erfolgen darf, wenn alle eingefügten Nachrichten im Kopfteil mit commit bestätigt wurden. Da nicht alle Transaktionen gleichzeitig beginnen und enden, ergeben sich Leerlaufzeiten, in denen Transaktionen warten müssen (vgl. Abbildung 18). Abbildung 19: Warteschlangen als einfache Relation mit Pointern 62 5.1 Demaq mit der DB2 und Saxon 5.1.4.4 Feinentwurf Variante 4: Einfache Relation mit Pointern Wie von [9] vorge- schlagen und in Abbildung 10 veranschaulicht, können Warteschlangen mit Hilfe von Head - und Tail-Pointern und einem Array implementiert werden. Innerhalb eines relationalen DBMS gibt es keine Array-Datenstruktur. Jedoch kann eine Tabelle in ähnlicher Weise benutzt werden, indem die Zeilen als Speicherzellen aufgefasst werden, für die der Primärschlüssel der Tabelle als deren ”Speicheradresse“ verwendet wird. Logischer Entwurf: Die Tabelle für die Warteschlangen unterscheidet sich nicht von der Definition der Variante in Kapitel 5.1.4.2: create table queue1 ( 2 i d int not null , message xml not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 4 s t a t e smallint not null default 0 6 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ); Zusätzlich wird wieder eine message_queue-Tabelle angelegt, welche die Nachrichten-IDs den Tabellen der Warteschlangen zuordnet (vgl. Kapitel 5.1.4.2). Für jede Queue wird zusätzlich eine Relation mit zwei Zeilen verwaltet: In einer Zeile wird der Head -, in der anderen der Tail-Pointer gespeichert. Die Pointer Tabelle kann wie folgt definiert werden (hier am Beispiel einer Warteschlange mit dem Namen ”queue1“): 1 create table q u e u e 1 p o i n t e r ( type char ( 4 ) not null , 3 value int , primary key ( type ) 5 ); Abbildung 19 visualisiert die Implementierung, die der Umsetzung einer Warteschlange in einem Array ähnelt. 63 5.1 Demaq mit der DB2 und Saxon Feinentwurf Physischer Entwurf: Außer den implizit erzeugten Indizes auf den Nachrichten-IDs und der Spalte type in der Pointer -Tabelle, werden keine weiteren Indizes erzeugt (vgl. Diskussion bei Variante 1). Abbildung 20: Warteschlangen als einfache Relation mit Pointern (optimiert) Da die Pointer eher flüchtige Daten darstellen, die aus den übrigen Daten abgeleitet werden können (z.B. nach einem Systemabsturz), bedeutet eine Persistenzierung einen Overhead. Eine Speicherung der Daten in einer temporären Tabelle [20] ist allerdings nicht möglich, da diese immer nur für eine Connection bzw. Session gültig ist. Deshalb müsste sie für mehrere nebenläufige Verbindungen synchronisiert werden. Da dies nur durch großen Aufwand möglich ist, bringen temporäre Tabellen in diesem Fall keinen Vorteil. Den Tail-Pointer in der Pointer -Tabelle zu speichern, ist überflüssig, da auf das Ende der Warteschlange nur zugegriffen wird, wenn eine neue Nachricht eingefügt wird. In diesem Fall kann der Tail-Pointer durch eine Sequence ersetzt 64 5.1 Demaq mit der DB2 und Saxon Feinentwurf werden, da keine Zeile zum Speichern Vorallokiert wird. Denn im Gegensatz zu einem Array, das eine feste Größe hat, wird eine Tabelle in einem relationalen DBMS dynamisch vergrößert. Auf diese Weise können alle Update-Operationen auf dem Tail-Pointer eingespart werden. Die Selektion der nächsten Nachricht durch ein SQL-Statement darf nicht mit dem Zusatz ”WITH UR“ als Uncommitted Read ausgeführt werden. Ansonsten könnten Nachrichten weiterverarbeitet werden, die eingefügt, aber noch nicht mit commit bestätigt wurden. Wie auch bei den bisherigen Varianten können die SQL-Statements zusammengefasst werden (vgl. Abbildung 20), um die automatische Optimierung zu verbessern [3]. Theoretische Bewertung: Im ersten Moment erscheint diese Umsetzung vorteilhaft, da für die Wahl der nächsten Nachricht kein Minimum selektiert werden muss. Ein einfacher Join genügt zum Selektieren. Allerdings muss der Head-Pointer anschließend auf die nächste Nachricht gesetzt werden, wodurch eine zusätzliche Update-Operation ausgeführt wird. Diese Update-Operation auf der Pointer -Tabelle belegt diese mit einem exklusiven Lock bis zum Ende der Transaktion. Auf diese weise wird eine nebenläufige Ausführung verhindert. Ebenso darf der ”SELECT min(id)...“-Ausdruck in keinem Fall als Uncommitted Read ausgeführt werden, da ansonsten möglicherweise Nachrichten weiterverarbeitet werden, die noch nicht mit commit bestätigt wurden. Letztendlich zeichnet sich diese Variante durch eine hohe Komplexität aus, ohne besonders erkennbare Vorteile zu bieten. 5.1.4.5 Variante 5: Einfache Relation mit Verkettung Die Implemen- tierung einer Warteschlange als verkettete Liste ist eine weitere Variante, die [9] vorschlägt und die in Abbildung 10 unter (b) veranschaulicht ist. In einem relationalen DBMS gestaltet sich die Nachbildung einer solchen verketteten Liste als 65 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 21: Warteschlangen als einfache Relation mit Verkettung schwierig. Dennoch soll an dieser Stelle ein Vorschlag zur Umsetzung vorgestellt werden. Dabei wird die Nachrichten-ID wieder ähnlich wie eine Speicheradresse aufgefasst. Logischer Entwurf: Die Warteschlangen werden in einzelne Tabellen abgebildet. Hier eine beispielhafte Definition für eine Warteschlange mit dem Namen ”queue1“: 1 create table queue1 ( i d int 3 next not null , int default null , message 5 xml not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d s t a t e smallint not null default 0 7 primary key ( i d ) 66 check ( s t a t e in ( 0 , 1 ) ) , 5.1 Demaq mit der DB2 und Saxon Feinentwurf ); Zusätzlich wird für jede Warteschlange eine Tabelle angelegt, in welcher der Head - und der Tail-Pointer verwaltet werden. Die Pointer -Tabelle passend zu obigem Beispiel sieht wie folgt aus: create table q u e u e 1 p o i n t e r ( 2 type char ( 4 ) not null , value int , 4 primary key ( type ) ); Abbildung 21 stellt eine mögliche Implementierung einer Warteschlange als verkettete Liste in einem relationalen Datenbanksystem dar. Physischer Entwurf: Außer den implizit erzeugten Indizes auf den Nachrichten-IDs in der Warteschlangentabelle und type-Spalte in der Pointer Tabelle werden keine weiteren Indizes erzeugt. Wie auch bei den bisherigen Varianten können die SQL-Statements zusammengefasst werden, um die automatische Optimierung zu verbessern [3]. Theoretische Bewertung: Die Update-Operationen auf der Pointer Tabelle sperren exklusiv die Einträge bis zum Ende der Transaktion. Die Pointer können nicht als Uncommited Read gelesen werden, da eine neu eingereihte Nachricht, die noch nicht abschließend mit commit bestätigt wurde, den HeadPointer geändert haben könnte. Dann würde die nächste dequeue-Operation, die als Uncommited Read ausgeführt wird, diese Nachricht weiterverarbeiten, was nicht zulässig ist. Insgesamt hat diese Variante der Warteschlangenabbildung keine signifikanten Vorteile zu bieten, außer dass kein Minimum mehr selektiert werden muss. Außerdem ist sie im Vergleich zu den anderen Varianten überdurchschnittlich kompliziert. 67 5.1 Demaq mit der DB2 und Saxon 5.1.4.6 Feinentwurf Variante 6: Trennung von Daten und Statusinformationen Abgearbeitete Nachrichten werden im Demaq-System nicht gelöscht, sondern nur als bearbeitet markiert. Darum erschweren diese bereits abgearbeiteten Nachrichten in den vorhergehenden Varianten die Selektion der nächsten Nachricht, da der notwendige Tablescan 3 alle Daten (auch die bereits abgearbeiteten) einer Warteschlangentabelle durchlaufen muss. Deshalb wird in dieser Variante versucht, die Nachrichtendaten von den relevanten Informationen der Warteschlangenbearbeitung zu trennen. Logischer Entwurf: Zunächst wird eine Relation definiert, um die Nachrichten aller Warteschlangen zu speichern. Allerdings werden die Statusinformationen, d.h. die Spalte state, weggelassen: 1 create table me ssa g es ( i d int 3 not null , queuename message 5 varchar ( 2 5 5 ) xml not null , not null , primary key ( i d ) ); Wenn obige Tabelle isoliert betrachtet wird, ist nicht ersichtlich, welche der Nachrichten bereits bearbeitet wurden und welche nicht. Deshalb wird eine weitere Tabelle benötigt, in der die IDs der Nachrichten gespeichert werden, die noch nicht bearbeitet wurden: create table u n p r o c m e s s a g e s ( 2 i d int not null , primary key ( i d ) 4 ); 3 Wie bei Variante in Kapitel 5.1.4.1 bereits ausführlich diskutiert, ist es nicht sinnvoll einen Index zu verwenden, um die bearbeiteten Nachrichten von den nicht bearbeiteten zu trennen. Deshalb müssen die Datensätze tatsächlich gelesen werden, wenn der SQL-Ausdruck ”WHERE state=0“ auftaucht. 68 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 22: Warteschlange mit Statusinformationen in Form einer extra Tabelle Sobald eine neue Nachricht in die Tabelle messages eingefügt wird, muss ihre ID auch in die Tabelle unproc_messages eingefügt werden. Wird eine Nachricht bearbeitet, muss ihre ID in der Tabelle unproc_messages gelöscht werden. Der Datensatz der Nachricht in der Tabelle messages bleibt hingegen unverändert. Abbildung 22 veranschaulicht die beschriebene Variante und zeigt eine mögliche Implementierung der dequeue- und enqueue-Funktionen. Physischer Entwurf: Die Selektion der nächsten Nachricht erfolgt über einen Join der beiden Tabellen unproc_messages und messages über den Primärschlüssel. Desweiteren wird die Selektion über den Ausdruck ”WHERE m.queuename=qname“ (vgl. Abbildung 22) auf eine bestimmte Warteschlange eingeschränkt, so dass für die – durch den Join vorselektierten – Tabellenzeilen die 69 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 23: Warteschlange mit Statusinformationen in Form einer extra Tabelle (optimiert) Datenseiten von der Festplatte geladen werden. Da der Index für den Primärschlüssel auf der Spalte id der messages-Tabelle eindeutig ist, könnte die Spalte queuename in den Index inkludiert werden [17]. Auf diese Weise kann die Selektion der nächsten Nachricht ausschließlich über die Indizes erfolgen [14], ohne dass zusätzlich Datenseiten geladen werden. Für die Definition der Tabelle bedeutet dies, dass kein Primärschlüssel festgelegt wird. Stattdessen wird ein angepasster Index explizit definiert: create table me ssa g es ( 2 i d int not null , queuename 4 message varchar ( 2 5 5 ) xml not null , not null ); 6 create unique index messagesndx on me ssa g es ( i d ) 8 i n c l u d e ( queuename ) ; 70 5.1 Demaq mit der DB2 und Saxon Feinentwurf In der neu definierten Tabelle unproc_messages werden keine Updates mehr ausgeführt. Es werden nur Inserts für neu eingereihte Nachrichten durchgeführt und Deletes für verarbeitete. In der Standardkonfiguration der DB2 würden diese Operationen die Tabelle blockieren, wenn das nächste Minimum selektiert wird, obwohl die neu eingefügten und die gelöschten Zeilen für die Selektion des Minimums nicht relevant sind. Die Nachrichten, die eingefügt, aber noch nicht mit commit bestätigt wurden, dürfen noch nicht weiterverarbeitet werden, genauso wie Nachrichten, die bereits in Weiterverarbeitung sind. Deshalb kann mit den Optionen DB2_SKIPINSERTED=ON und DB2_SKIPDELETED=ON veranlasst werden, dass DB2 gelöschte und eingefügte Zeilen, die noch nicht mit commit bestätigt wurden, ignoriert, so dass keine Blockierung durch diese stattfindet [43]. Die einzelnen SQL-Statements der dequeue- und enqueue-Operation können wieder zusammengefasst werden, so dass die automatische Optimierung der DB2 effizienter arbeiten kann [3]. Abbildung 23 stellt eine derart optimierte Version dar. Theoretische Bewertung: Durch die getrennte Speicherung der IDs der noch nicht verarbeiteten Nachrichten kann die nächste Nachricht einer Queue wesentlich effizienter selektiert werden. Erstens, weil mit einem schnellen IndexJoin die meisten Nachrichten ausgeschlossen werden können; und zweistens, weil mit den Optionen DB2_SKIPINSERTED=ON und DB2_SKIPDELETED=ON beliebig viele dequeue- und enqueue-Operationen nebenläufig auf die Tabellen zugreifen können, ohne sich gegenseitig zu blockieren. Außerdem ist die nächste Nachricht ausschließlich über die Indizes bestimmbar, wenn die Spalte queuename in den Index der Tabelle messages inkludiert wird. Damit ist diese Variante theoretisch eine der Effizientesten. 5.1.4.7 Variante 7: Einfache Relation mit redundanter Queue im Hauptspeicher In vorhergehenden Diskussionen wurde ausgeführt, dass die 71 5.1 Demaq mit der DB2 und Saxon Feinentwurf Warteschlangenimplementierung mit einer Sicht, die sich auf die relationale Datenbank beschränkt, nicht optimal ist. Dies ist damit zu begründen, dass sich flüchtige Daten, wie die Pointer in Abschnitt 5.1.4.4 und 5.1.4.5, nur schlecht in einem DBMS verwalten lassen. Letztlich bedeutet die Persistenzierung dieser Daten einen Overhead, da sie sich aus den übrigen Daten rekonstruieren lassen. So könnte der aktuelle Zustand ohne persistenzierte Pointer auch nach einem System-Absturz leicht wieder hergestellt werden. Werden andererseits keine Pointer verwendet, muss die nächste Nachricht aus den Daten der Tabellen extrahiert werden. Dies bedeutet einen zusätzlichen Aufwand, z.B. durch ein ”SELECT min(id)..“-Statement oder einen Join. Aus diesem Grund muss das Sichtfeld bei der Implementierung der Warteschlangen auf die gesamte Applikation erweitert werden. Dabei wäre es Vorteilhaft, wenn mit dem Aufruf von dequeue bereits bekannt ist, welche Nachricht mit welcher ID als nächstes abgearbeitet wird. Dann könnte diese ID der Datenbank in einem Select-Statement übergeben werden, so dass nur noch ein einfacher Indexscan zum Auffinden der Nachricht ausreicht. Logischer Entwurf: Da in dieser Variante der ”SELECT min(id)...“Ausdruck, der zum bestimmen der nächsten Nachrichten-ID nötig war, wegfällt, werden keine Sperren mehr auf Ebene der ganzen Tabelle gesetzt. Daher kann für alle Warteschlangen eine einzige Tabelle gewählt werden: create table me ssa g es ( 2 i d int not null , queuename 4 message varchar ( 2 5 5 ) xml not null , not null , −− s t a t e : 0=enqueued ,1= p r o c e s s e d 6 s t a t e smallint not null default 0 primary key ( i d ) 8 ); 72 check ( s t a t e in ( 0 , 1 ) ) , 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 24: Warteschlange mit Informationsverwaltung im Hauptspeicher Damit die ID der nächsten Nachricht beim Aufruf der dequeue-Funktion bereits bekannt ist, muss im Demaq-System eine redundante Warteschlange im Hauptspeicher gehalten werden. In dieser sind lediglich die IDs der noch nicht verarbeiteten Nachrichten vorzuhalten. Deshalb weist die Datenmenge im Hauptspeicher ein niedriges Fluktuationsniveau auf. Die Nachrichten selbst werden weiterhin im relationalen DBMS gespeichert. Bei einem System-Absturz kann die Warteschlange im Hauptspeicher aus den Daten in der DB2 leicht rekonstruiert werden. Abbildung 24 skizziert die Implementierung einer solchen Warteschlangenverwaltung im Hauptspeicher und Datenhaltung in der DB2. Physischer Entwurf: Außer dem implizit erzeugten Index auf der Nachrichten-ID wird kein weiterer Index benötigt, da der einzige Zugriff auf die Messages-Tabelle über die ID erfolgt. Die Implementierung der Queue kann im Demaq-System mithilfe des Queue73 5.1 Demaq mit der DB2 und Saxon Feinentwurf Abbildung 25: Warteschlange mit Informationsverwaltung im Hauptspeicher (optimiert) Schedulers vorgenommen werden. Dort wird bereits im aktuellen System jede Nachrichten-ID zusammen mit dem Queue-Namen eingereiht. Bei der Auswertung durch den RuleExecutor wird allerdings nur der Queue-Name weiterverwendet, während die Nachrichten-ID unbeachtet bleibt. Durch wenige Anpassungen kann die ID an dieser Stelle an den RuleProcessor weitergegeben und an die eigentliche dequeue-Funktion als Parameter übergeben werden. Auf diese Weise können die bestehenden Module verwendet werden, um mit wenig Aufwand eine redundante Queue im Hauptspeicher abzubilden. Wie in Abbildung 25 dargestellt, können die einzelnen SQL-Statements aus Abbildung 24 zusammengefasst werden, um der automatischen Optimierung in der DB2 mehr Spielraum zu lassen [3]. Theoretische Bewertung: Mit Blick auf die nebenläufige Verarbeitung treten mit dieser Variante keine Probleme auf. Da die dequeue-Funktion bei dieser Variante nur direkt mit der ID auf Nachrichten zugreift, wird die Tabelle, in der 74 5.1 Demaq mit der DB2 und Saxon Feinentwurf die Nachrichten liegen, nie komplett blockiert. Denn beim Standard-IsolationsLevel Cursor Stability in der DB2 wird nur die Zeile gesperrt, die auch tatsächlich gelesen oder geändert wird [43]. Der Zugriff auf alle anderen Zeilen bleibt weiter möglich. Auch können neue Zeilen nebenläufig eingefügt werden. Ebenso hätte eine exklusive Sperre einer einzelnen Zeile keine negativen Auswirkungen, da durch die synchronisierte Warteschlange im Hauptspeicher garantiert wird, dass jede Zeile nur von einem Thread bearbeitet wird. Auf diese Weise können beliebig viele dequeue- und enqueue-Operationen nebenläufig auf die Daten in der DB2 zugreifen, ohne sich gegenseitig zu blockiern. Außerdem besteht keine Gefahr, dass Nachrichten, die schon eingefügt, aber noch nicht mit commit bestätigt wurden, weiterverarbeitet werden, weil diese erst nach dem commit dem QueueScheduler bekannt werden. Durch das Selektieren ausschließlich über die Nachrichten-ID kann über einen IndexScan auf dem Primärschlüssel schnellstmöglich auf den Datensatz zugegriffen werden. Insgesamt gehört diese Variante in theoretischer Hinsicht zu den Effizientesten. 5.1.4.8 Tabellarische Übersicht der Varianten In Tabelle 3 wird die Be- wertung der verschiedenen Varianten der Warteschlangenabbildung auf ein relationales DBMS nochmals zusammenfassend dargestellt. Dabei werden die zuvor ausgeführten Aspekte ”Nebenläufigkeit“, ”Zugriffskosten für Selektionen“, ”Zugriffskosten für Updates“ und die ”Handhabung“ berücksichtigt. Die Bewertung erfolgt qualitatv mit ”+“ (positiv), ”0“ (neutral) oder ”-“ (negativ). Insgesamt haben die Varianten 6 und 7 in der theoretsichen Bewertung, insbesondere im Bezug auf die Effizienz, die höchsten Werte erreicht. Aus diesem Grund werden diese Varianten in dem Experiment, welches in Kapitel 7.2.4 beschrieben wird, getestet. 75 5.1 Demaq mit der DB2 und Saxon Feinentwurf Tabelle 3: Übersicht der Varianten der Warteschlangenabbildung in einem relationalen DBMS 5.1.5 DB2-Datenbankmodul: Varianten der Abbildung von Slices Slices können in einer relationalen Datenbank auf unterschiedliche Weise implementiert werden. Die möglichen Varianten können im Rahmen der vorliegenden Arbeit nicht vollständig vorgestellt werden. Entscheidend für eine native Implementierung von Slices (vgl. Kapitel 4.2.5) ist, dass die Nachrichten, die den gleichen Wert für das Slicing-Property haben, möglichst effizient selektiert werden können. Im Folgenden werden beispielhaft drei mögliche Implementierungen vorgestellt. 5.1.5.1 Slicing Zugriffe über einen Index Mithilfe einer separaten Slicing-Property-Tabelle können Slicings in einem relationalen DBMS mit wenig Aufwand implementiert werden. Die Tabelle wird durch folgendes DDL-Statement definiert: create table m s g s l i c i n g p r o p e r t y ( 2 propertyname msgid int 4 varchar ( 2 5 5 ) not null , not null , value varchar ( 5 1 2 ) not null ); 76 5.1 Demaq mit der DB2 und Saxon Feinentwurf Um Nachrichten-IDs zu ermitteln, die zu einem spezifischen Slicing gehören, kann eine Selektion auf der Slicing-Property-Tabelle durchgeführt werden. Folgender SQL-Ausdruck könnte hierfür benutzt werden: 1 SELECT msgid FROM m s g s l i c i n g p r o p e r t y 3 WHERE propertyname= ’ m y S l i c i n g ’ AND value= ’ 42 ’ ; Um dieses SQL-Statement auszuwerten, wird ein Tablescan der gesamten Tabelle msg_slicing_property durchgeführt. Durch eine Indizierung der Spalte propertyname oder der Spalte value ist hierbei eine zusätzliche Beschleunigung möglich. Eine alleinige Selektion von Nachrichten-IDs über einen Index ist allerdings nicht möglich, da beide genannten Spalten keine eindeutigen Werte enthalten. Deshalb kann kein Index erzeugt werden, der andere Spalten enthält [17]. Da davon ausgegangen werden kann, dass in den meisten Fällen die Variation der value-Spalte größer ist als die der propertyname-Spalte, erscheint ein Index auf der value-Spalte vorteilhafter: create index s l i c i n g n d x on m s g s l i c i n g p r o p e r t y ( value ) ; 5.1.5.2 Slicings mit Materialized Views Eine weitere Variante der Imple- mentierung von Slices kann mit Hilfe von Materialized Views umgesetzt werden. Hierzu wird die Property-Tabelle der gewöhnlichen Nachrichten-Properties auch für die Slicing-Properties verwendet. Für jedes Slicing-Property wird eine eigene Materialized View angelegt. Das Statement zum Erzeugen der View sieht wie folgt aus: 1 create table q s s l i c e m y s l i c i n g as (SELECT msgid , value as key 3 FROM m s g p r o p e r t y WHERE propertyname= ’ m y S l i c i n g ’ ) 5 data i n i t i a l l y d e f e r r e d r e f r e s h immediate ; 77 5.1 Demaq mit der DB2 und Saxon Feinentwurf set i n t e g r i t y f o r q s s l i c e m y s l i c i n g immediate checked not incremental ; Das folgende Beispiel verdeutlicht, wie über eine Materialized View bei der Regelauswertung auf ein Slicing zugegriffen werden kann: create r u l e g e t s l i c i n g c o n t e n t f o r m y s l i c i n g 2 enqueue message <r e s u l t > { qs : s l i c e ( ’ 42 ’ , ’ m y s l i c i n g ’ ) } 4 </ r e s u l t > into r e s p o n s e q u e u e ; Der Aufruf qs:slice(’42’,’myslicing’) wird für die Auswertung mit der DB2 in ein SQL-Statement umgewandelt: SELECT message 2 FROM me ssa g es m, q s s l i c e m y s l i c i n g s WHERE s . key= ’ 42 ’ 4 AND s . msgid=m. i d ; 5.1.5.3 Slicings als eigene Tabellen Eine andere Alternative stellt die Möglichkeit dar, für jedes Slicing-Property eine eigene Tabelle anzulegen. Mit dem Slicing-Namen als Tabellenname kann beim System-Start von Demaq für jedes Slicing eine Tabelle erzeugt werden. Beispielsweise wird für das Slicing ”mySlicing“ folgende Tabelle angelegt: create table q s s l i c e m y s l i c i n g ( 2 key varchar ( 5 1 2 ) , msgid int not null 4 ); Wird zur Laufzeit des Demaq-Systems eine Nachricht mit dem SlicingProperty ”myslicing“ eingefügt, wird der Wert nicht in die Tabelle msg_property oder msg_slicing_property eingetragen, sondern in die speziell für das Slicing angelegte Tabelle qs_slice_myslicing. 78 5.1 Demaq mit der DB2 und Saxon Feinentwurf Um die Effizienz der Selektion auf der speziellen Slicing-Tabelle zu steigern, wird zusätzlich ein Index auf der Spalte key angelegt: create index q s s l i c e m y s l i c i n g n d x 2 on q s s l i c e m y s l i c i n g ( key ) ; Auch bei dieser Variante kann keine ausschließliche Selektion der NachrichtenIDs über den Index erfolgen. Die Auswahl erfolgt aber nur über eine Spalte und die Slicing-Tabelle enthält weniger Einträge als bei der Variante in Kapitel 5.1.5.1, da sich die Werte der Slicing-Properties auf mehrere Tabellen verteilen. Deshalb erscheint diese Variante aus theoretischer Sicht effizienter und wird aus diesem Grund im Rahmen dieser Diplomarbeit implementiert. Anhand des folgenden Beispiels soll verdeutlicht werden, wie in dieser Variante der Zugriff auf ein Slicing bei der Regelauswertung abläuft: create r u l e g e t s l i c i n g c o n t e n t f o r m y s l i c i n g 2 enqueue message <r e s u l t > { qs : s l i c e ( ’ 42 ’ , ’ m y s l i c i n g ’ ) } 4 </ r e s u l t > into r e s p o n s e q u e u e ; Der Aufruf qs:slice(’42’,’myslicing’) wird für die Auswertung mit der DB2 zu einem SQL-Statement aufgelöst: SELECT message 2 FROM me ssa g es m, q s s l i c e m y s l i c i n g s WHERE s . key= ’ 42 ’ 4 AND s . msgid=m. i d ; 5.1.6 Änderung des Demaq-Codes Um DB2 als Nachrichtenspeicher zu verwenden, müssen einige Umstrukturierungen vorgenommen werden, die vor Allem der Modularisierung der Komponenten für zukünftige Erweiterungen Rechnung tragen (vgl. die Anforderungen in Kapitel 3.3.2). Zusätzlich müssen neue C++-Klassen eingeführt werden, welche die 79 5.1 Demaq mit der DB2 und Saxon Feinentwurf Schnittstellen zum Nachrichtenspeicher bilden (vgl. Abschnitt 4.1.3). 5.1.6.1 Umstrukturierungen In dem Ordner src/infra/gateway waren bisher die Dateien natixgateway.hh und -.cc zu finden. Um das NatixGateway austauschbar zu machen, werden in diesem Ordner zwei Unterordner natix und db2 angelegt und die Dateien natixgateway.hh und -.cc werden in den natix-Ordner verschoben. Im Unterodner db2 werden die Dateien db2gateway.hh und -.cc für die Klasse DB2Gateway angelegt. Entsprechend den Überlegungen in Kapitel 4.2.2 wird im Ordner src/infra/gateway die Datei messagestoregateway.hh angelegt. In dieser Datei wird ein typedef für den Typ MessageStoreGateway entweder für die Klasse NatixGateway oder DB2Gateway definiert, je nachdem wie die Einstellungen in der Datei configure.ac vorgenommen werden. Die Umstrukturierungen für die austauschbare Gateway-Klasse betreffen auch den übrigen Quelltext des Demaq-Systems. Zunächst müssen alle VariablenDeklarationen und Objekt-Erzeugungen der ehemaligen Gateway-Klasse durch den neutralen Typ MessageStoreGateway ersetzt werden. Außerdem muss der NATIX-spezifische Code aus den unspezifischen Klassen des Demaq-Kerns in die Gateway-Klassen verschoben werden. Beispielsweise wird in der Datei demaq.cc in der Funktion reconstructSchedulerContentFromQueue() NATIXspezifischer Code verwendet, um den letzten System-Zustand nach einem Absturz wieder herzustellen. Um die Systemwiederherstellung neutral, d.h. mit jedem Nachrichtenspeicher kompatibel, zu gestalten, wird in den Gateway-Klassen die zusätzliche Funktion getUnprocessedMessagesTimestampList() implementiert, in die der vom Nachrichtenspeicher abhängige Code verschoben wird. In der Funktion reconstructSchedulerContentFromQueue() wird anschließend die neutrale Funktion der Gateway-Klassen verwendet. Eine Reihe weiterer solcher Code-Verlagerungen in die Gateway-Klassen wird durchgeführt, die an dieser Stelle nicht weiter aufgeführt werden sollen. In dem Ordner src/demaq werden Umstrukturierungen für die Klasse Demaq80 5.1 Demaq mit der DB2 und Saxon Feinentwurf Config vorgenommen. Zunächst wird ein Unterodner config angelegt, in dem die Ordner natix und db2 erzeugt werden. Die ehemaligen Dateien demaqconfig.hh und -.cc werden umbenannt in natixconf.hh und -.cc. Außerdem werden sie in den natix-Ordner verschoben. Dementsprechend werden die Dateien db2conf.hh und -.cc im Unterordner db2 angelegt. In dem neuen Ordner config wird die Datei demaqconf.hh dazu verwendet, um den neutralen Typ DemaqConfig mithilfe eines typedefs entweder als NatixConfig oder als DB2Config zu definieren. Gesteuert wird dies über die gleiche Einstellung in der Datei configure.ac, die auch den typedef des MessageStoreGateway steuert. Dadurch kann eine unterschiedliche Konfigurationsklasse für das System verwendet werden, je nachdem mit welchem Nachrichtenspeicher das System kompiliert wird. Durch die vorgenommenen Umstrukturierungen lassen sich in Zukunft andere Nachrichtenspeicher mit wenig Aufwand in das System integrieren. Dazu müssen nur in den Ordnern src/infra/gateway und src/demaq passende Unterordner mit zusätzlichen Gateway- bzw. DemaqConfig-Klassen angelegt werden. Diese werden dann als typedef in die Dateien messagestoregateway.hh und demaqconf.hh hinzugefügt. Schließlich wird eine zusätzliche Makro-Variable in der Datei configure.ac definiert, welche die Kompilierung mit den neuen Klassen optional zulässt. 5.1.6.2 Neue C++ Klassen Folgende neue Klassen entstehen im Demaq- Kern: DB2Gateway Die Klasse DB2Gateway bildet die neue Schnittstelle zur DB2 als Nachrichtenspeicher. Die Signatur der Klasse ist identisch mit der der NatixGateway-Klasse. NatixGateway Die Klasse NatixGateway ist durch Umbenennung aus der alten Gateway-Klasse entstanden. DB2DemaqConfig Die Klasse enthält Konfigurations-Einstellungen, die speziell 81 5.1 Demaq mit der DB2 und Saxon Feinentwurf für das System mit der DB2 benötigt werden. Ein Objekt der Klasse wird beim Erzeugen der Demaq-Instanz an diese übergeben, die dann ein individuell konfiguriertes System startet. NatixDemaqConfig Analog zu der Klasse DB2DemaqConfig enthält die Klasse NatixDemaqConfig spezifische Einstellungsparameter für ein zu startendes Demaq-System mit NATIX. Diese Klasse ist durch Umbenennung und Verschiebung der ehemaligen DemaqConfig-Klasse entstanden. 5.1.7 Erweiterung des NATIX-Codes Wenn das Demaq-System mit der DB2 als Nachrichtenspeicher und Saxon als Regelauswerter kompiliert wird, kontrolliert NATIX weiterhin den Regelauswertungsmechanismus (vgl. Kapitel 4.2.3). Deshalb muss es NATIX ermöglicht werden auf XML-Dokumente zugreifen zu können, die in der DB2 gespeichert sind. 5.1.7.1 nur Umstrukturierungen Die an wird typ einer erzeugt. Stelle: Dort DB2Document und -.cc, in Der werden den Ordnerstruktur Ordner die sich src/schema/physical/db2document Handler Dateien ändert für den neuen Fragment- db2documentdescriptormanager.hh db2documentmetadataviewfactory.cc und -.cc und db2documentstreamviewfactory.cc und -.cc hinzugefügt. Um steuern zu können, ob NATIX mit der DB2-Funktionalität kompiliert wird, muss eine zusätzliche Compiler -Option hinzugefügt werden. Dazu wird eine neue Datei mit dem Namen db2 in den Ordner abusy/configs angelegt, in der die Umgebungsvariable CONFIG_DB2_SPECIALS=y gesetzt wird. Diese Variable kann in den Imakefiles dazu benutzt werden, die DB2-spezifische Funktionalität nur zu kompilieren, wenn die Variable auf ”y“ gesetzt ist. Der Aufruf, um NATIX mit der DB2 -Funktionalität zu kompilieren, lautet dann beispielsweise: abusy −−c o n f i g n a t i x g c c debug demaq db2 82 5.1 Demaq mit der DB2 und Saxon 5.1.7.2 Feinentwurf Änderungen des bestehenden Codes Wie in Kapitel 4.2.3 be- schrieben, müssen die Callback-Services in NATIX angepasst werden, damit aus Demaq-Regeln heraus auf Daten in der DB2 zugegriffen werden kann. Zu diesem Zweck wird die Datei saxonxqueryquerystreamviewfactory.cc im Ordner src/schema/physical/query/saxon angepasst. In dieser Datei wird die Anfragenbearbeitung der Callback-Services definiert. Jede Anfrage wird durch einen String-Vergleich identifiziert und dann entsprechend auf dem Nachrichtenspeicher ausgeführt. Da mit der DB2 ein weiterer optionaler Nachrichtenspeicher hinzukommt, muss der ausführende Code entweder für NATIX als Speicher oder die DB2 kompiliert sein. Deshalb wird für jede mögliche Anfrage mit einem #ifdef CONFIG_DB2_SPECIALS definiert, für welchen Nachrichtenspeicher der Callback Mechanismus kompiliert wird. Ist CONFIG_DB2_SPECIALS=y gesetzt, werden die Services für die DB2 kompiliert. Der neue Fragmenttyp für XML-Dokumente, die in der DB2 gespeichert sind, wird in der Datei types.xml im Ordner src/control/request/spec hinzugefügt. Die Definition in der XML-Datei genügt aus, damit der notwendige Code beim Kompilieren von NATIX automatisch generiert wird. 5.1.7.3 Neue C++ Klassen In NATIX werden folgende neuen C++- Klassen definiert: DB2DocumentDescriptorManager Die DB2DocumentDescriptorManager-Klasse ist dafür zuständig, ein Descriptor -Objekt für ein Dokument, das in der DB2 gespeichert ist, zu erzeugen. Angefordert wird dies mit einem OpenDB2Document-Request. Außerdem deligiert die DB2DocumentDescriptorManager-Klasse einen OpenView-Request an die richtige Factory-Klasse, wenn dieser mit einem DB2-FragmentDescriptor erzeugt wird. Um NATIX den DB2DocumentDescriptorManager als Handler für DB283 5.1 Demaq mit der DB2 und Saxon Feinentwurf FragmentDescriptoren bekannt zu machen, wird in der SchemaManagerKlasse in den Dateien src/schema/physical/repository/schemamanager.hh und -.cc ein DB2DocumentDescriptorManager als Objekt-Variable hinzugefügt. Damit auf diese Variable zugegriffen werden kann, muss zusätzlich noch die Funktion getDB2DocumentDescriptor() ergänzt werden. DB2Document-Stream-View-Factory Die Stream-View-Factory für DB2- FragmentDescriptoren generiert aus einem in der DB2 gespeicherten XMLDokument einen Stream. Beauftragt wird sie von einem OpenView-Request, der vom DB2DocumentDescriptorManager weitergeleitet wurde und einen DB2-FragmentDescriptor enthält. Durch den Descriptor weiß die FactoryKlasse welches Dokument als Stream geöffnet werden soll. DB2Document-Metadata-View-Factory Die Metadata-View-Factory-Klasse ist dafür zuständig, für ein Dokument, das in der DB2 gespeichert ist, Metadaten zusammenzustellen. Zu diesem Zweck wird ein entsprechender OpenView-Requests von dem DB2DocumentDescriptorManager weitergeleitet, der einen DB2-FragmentDescriptor enthält. Durch den DB2-FragmentDescriptor erhält die Factory-Klasse die Information, für welches Dokument sie die Metadaten zusammenstellen soll. OpenDB2Document Die Klasse OpenDB2Document ist ein neuer Request (vgl. Kapitel 2.2.1). Mit diesem Request kann ein FragmentDescriptor des Typs DB2Document erzeugt und an den Aufrufer zurückgegeben werden. Dieser Request wird in der XML-Datei opendb2document.xml im Pfad src/control/request/spec/schema definiert. Der C++-Code wird hieraus beim Kompilieren vom NATIX-Build -System automatisch generiert. 84 5.1 Demaq mit der DB2 und Saxon 5.1.8 Feinentwurf DB2-Fassade Die Vorüberlegungen zu der Integration der Funktionalität der DB2 betreffen drei Punkte: 1. Die Integration der Funktionalität der DB2: Wie und wo kann man diese am besten integrieren? (Vgl. hierzu Abschnitt 4.2.4), 2. die benutzte Technik: Wie kann man mit der DB2 eine Verbindung herstellen? 3. wie diese Technik benutzt wird: Wie lässt sich die benutzte Technik am besten implementieren?. Die beiden letzten Punkte werden in den Unterabschnitten 5.1.8.1 und 5.1.8.2 behandelt. Die DB2-Fassade kapselt nicht nur die Verbindung und Funktionalität der Datenbank, sondern dient auch zur Verwaltung der Datenbanktransaktionen, die eng an eine Verbindung gekoppelt sind [26]. Denn sobald eine Anfrage über eine Verbindung an die DB2 übermittelt wird, wird implizit eine Transaktion gestartet, die dieser Verbindung im DBMS zugeordnet ist. Abgeschlossen wird eine Transaktion, indem ein explizit commit gesendet wird. Der Zeitpunkt zum Abschluss einer Transaktion durch commit, und damit die Steuerung der Transaktion, wird vom Demaq-System-Kern übernommen. Da die DB2-Fassade die Verbindungen verwaltet, verwaltet sie implizit auch die Transaktionen. Die wichtigste Klasse der DB2-Fassade ist die DB2Transaction-Klasse aufgrund der engen Bindung an eine Transaktion bzw. Verbindung. Diese enthält allerdings mehr als nur die Funktionalität einer Transaktion bzw. Verbindung: Während die Gateway-Klasse die Außenschnittstelle des Demaq-Systems ist, stellt die DB2Transaction-Klasse die Außenschnittstelle der DB2 für Demaq dar. Auf diese Weise ist der Zugriff auf die DB2 einfach zu handhaben. Die implementierten Klassen der Fassade werden in Kapitel 5.1.8.3 detailliert erläutert. 85 5.1 Demaq mit der DB2 und Saxon 5.1.8.1 Feinentwurf Kommunikationstechnik Als Technik zur Kommunikation mit der DB2 wird CLI benutzt. Grundsätzlich stehen folgende Techniken zur Auswahl [8]: • JDBC • .NET Data Provider • Embedded SQL • CLI (ODBC) JDBC kommt für das Demaq-System nicht in Frage, da Java langsamer ist als C/C++. Ansonsten bietet JDBC keine signifikanten Vorteile gegenüber den sonstigen Varianten [8]. Gleichermaßen ungeeignet ist der .NET Data Provider, da dieser nicht primär für Linux-Systeme entworfen worden ist und ebenfalls keine zusätzlichen Vorteile bietet. Embedded SQL wird nicht als eingesetzte Kommunikationstechnik gewählt, da es einige entscheidende Nachteile hat: Es können nicht ohne weiteres mehrere Verbindungen und Transaktionen gleichzeitig von demselben Programm gestartet werden [13], was aber Grundvoraussetzung für die Nebenläufigkeit (vgl. Kapitel 3.4.4) ist. Außerdem benötigt Embedded SQL einen Precompiler und ist sehr unflexibel, da das Programm von der gebundenen Datenbank abhängig ist. Mit CLI sind parallele Abläufe mit mehreren gleichzeitig agierenden Transaktionen kein Problem. Zudem baut es auf dem internationalen Standard SQL/CLI und ODBC auf, was eine hohe Flexibilität bedeutet. 5.1.8.2 Implementierung Die Implementierung der DB2-Fassade mit Hilfe von CLI wird mit der Template Library OTL umgesetzt. Mit OTL kann mit dem Setzen einer Makro-Variable der Code ebenso für die Oracle 11g, MS Sql Server oder einigen anderen Datenbanken kompiliert werden. Damit wird CLI vergleichbar flexibel wie ODBC, ohne dass ein Driver-Manager benötigt wird [15]. Die 86 5.1 Demaq mit der DB2 und Saxon Feinentwurf Flexibilität kommt zukünftigen Vorhaben zugute, wie es in der Anforderung in Kapitel 3.3.2 gefordert wird. Außerdem nutzt OTL wiederverwendbare Streams, so dass ein Großteil der verwendeten SQL-Statements bereits beim System-Start vorbereitet wird. Hierdurch kann die Effizienz der Zugriffe mittels SQL erhöht werden. 5.1.8.3 Neue C++ Klassen Folgende neue Klassen gehören zu der DB2- Fassade: DB2Transaction Die Klasse DB2Transaction ist die Hauptklasse der DB2Fassade. Über sie laufen sämtliche Zugriffe auf die DB2. Zudem bietet sie Transaktionsfunktionalitäten mit ihren Funktionen abort() und commit(). ConnectionPool Die Zeit für den Verbindungsaufbau zur DB2 ist nicht konstant. Wenn eine Verbindung erst beim Starten einer Transaktion aufgebaut wird, führt das zu erheblichen Verzögerungen. Deshalb werden in der ConnectionPool-Klasse Verbindungen auch nach dem Abschluss einer Transaktion gehalten. Beim System-Start wird eine Anzahl an Verbindungen aufgebaut, indem DB2Transaction-Objekte erzeugt und gestartet werden. Die Anzahl kann über die Datei settings.hh im include-Ordner des Projektes gesteuert werden. Wird vom Demaq-System oder NATIX eine DB2Transaction benötigt, so wird diese über die statische Factory-Funktion getDB2Transaction() der DB2Transaction-Klasse angefordert. Die Funktion greift auf den ConnectionPool zu und liefert eine unbenutzte Verbindung zurück. Um eine Verbindung zur weiteren Verwendung an den ConnectionPool zurückzugeben, wird explizit die statische Funktion freeTransaction() der Klasse DB2Transaction aufgerufen werden. Intern werden die unbenutzten Verbindungen im ConnectionPool mit Hilfe 87 5.2 Demaq mit der DB2 Feinentwurf eines Stack s verwaltet. Mit freeTransaction() freigegebene Transaktionen werden auf den Stack zurückgelegt. 5.2 Demaq mit der DB2 Die System-Variante von Demaq mit der DB2 als Nachrichtenspeicher und Regelauswerter baut im Wesentlichen auf der Variante mit der DB2 und Saxon auf (Kapitel 5.1). Die entscheidenden Veränderungen, die notwendig sind, um DB2 im Demaq-Ausführungssystem auch als Regelauswerter zu verwenden, werden in diesem Kapitel im Detail beleuchtet. 5.2.1 Änderung des Demaq-Kerns Zunächst werden einige Veränderungen an der Ordnerstruktur im Demaq-System vorgenommen, die in Kapitel 5.2.1.1 erläutert werden. Diese zielen auf die Erweiterbarkeit für die Zukunft und die Modularisierung ab (vgl. Anforderungen in Kapitel 3.3.2). Änderungen an bestehendem Demaq-Code werden in Kapitel 5.2.1.2 beschrieben. Neu hinzukommenden C++-Klassen betreffen die Regelauswertung und die Abarbeitung der resultierenden Pending Action List und werden in Kapitel 5.2.1.3 erläutert. 5.2.1.1 Umstrukturierungen In dem Ordner src/core werden die neuen Unterordner queryresults, ruleprocessors und actioninterpreters angelegt, in denen jeweils die Unterordner natix und db2 erzeugt werden. Die bisherigen Dateien ruleprocessor.hh und -.cc, queryresult.hh und -.cc bzw. actioninterpreter.hh und -.cc werden in die Ordner src/core/ruleprocessors/natix, src/core/queryresults/natix bzw. src/core/actioninterpreters/natix verschoben. Außerdem werden sie umbenannt in natixruleprocessor.hh und -.cc, natixqueryresult.hh und -.cc bzw. natixactioninterpreter.hh und -.cc. Die entsprechenden Dateien für die DB2 werden in den db2- 88 5.2 Demaq mit der DB2 Feinentwurf Unterordnern angelegt. In der Datei configure.ac im Wurzelverzeichnis des Demaq-Projektes kann gesteuert werden, mit welchem Haupt-Regelauswerter das Demaq-System kompiliert werden soll. Durch die Implementierung der Klassen RuleProcessor, QueryResult und Actioninterpreter über eine Vererbungshierarchie, anstatt mithilfe eines typedef, können in Zukunft, mit wenigen zusätzlichen Anpassungen, verschiedene Regelauswerter in der gleichen System-Instanz betrieben werden. Auf diese Weise kann z.B. ein Fallback -Mechanismus implementiert werden, um Regeln, die von der DB2 nicht ausgewertet werden können, mit Hilfe von Saxon auszuwerten (vgl. Kapitel 4.1.4). 5.2.1.2 Änderungen des bestehenden Codes Die XQuery-Engine der DB2 kann nicht derart erweitert werden, dass Demaq-spezifische Funktionen, wie beispielsweise qs:queue(), direkt von der Datenbank interpretiert werden können (vgl. Kapitel 2.3.2.2). Dazu müssten Funktionen deklariert bzw. Module importiert werden, was von der DB2 nicht unterstützt wird. Deshalb müssen diese speziellen QRL-Funktionen beim Import eines DQLFiles von Demaq während des System-Starts mit Hilfe von Rewrites wegkompiliert werden. Die Rewrites werden für die wichtigsten Demaq-Funktionen in der Tabelle 4 aufgelistet. Diese gelten allerdings nur für eine WarteschlangenAbbildung nach dem Vorschlag in Kapitel 5.1.4.1 und eine Slice-Abbildung nach Kapitel 5.1.5.3. Allerdings sind nur wenige Anpassungen notwendig, um die vorgestellten Rewrites in den übrigen Varianten verwenden zu können. Die Rewrites werden implementiert, indem die Dateien transformation.hh und -.cc im Ordner src/xqlparser angepasst werden. 4 Die Variable $ demaq contextmsgid wird bei der Vorbereitung einer Regel zur Auswer- tung automatisch auf die ID der Kontext-Nachricht gesetzt. Die Variable $ wird mit der Kontext-Nachricht initialisiert. 89 demaq contextmsg 5.2 Demaq mit der DB2 Feinentwurf QRL Rewrite für die DB2 qs:message() $___demaq_contextmsg qs:queue(”qname”) db2-fn:sqlquery(’select message from 4 messages where queuename=parameter(1)’, ”qname”) qs:property(”pname”) db2-fn:sqlquery(’select value from msg_property where msgid=parameter(1) and propertyname=parameter(2)’, $___demaq_contextmsgid, ”pname”) qs:slice(”skey”,”sname”) 4 db2-fn:sqlquery(’select m.message from messages m,qs_slice_sname s where s.key=parameter(1) and s.msgid=m.id’, ”skey”) qs:slicekey(”sname”) db2-fn:sqlquery(’select key from qs_slice_sname where msgid=parameter(1)’, $___demaq_contextmsgid) 4 Tabelle 4: Rewrites für Demaq-spezifische Funktionen 5.2.1.3 Neue C++ Schnittstellen Folgende neue C++-Klassen werden implementiert, damit die DB2 als alternativer Regelauswerter eingesetzt werden kann: DB2RuleProcessor Der DB2RuleProcessor bereitet für eine bestimmte Nachricht die Regelauswertung vor, übergibt die vorbereitete Regel zur Ausführung an die DB2-Fassade und generiert aus dem Ergebnis ein DB2QueryResult. NatixRuleProcessor Der NatixRuleProcessor greift zur Regelauswertung auf 90 5.2 Demaq mit der DB2 Feinentwurf NATIX zu. Aus dem Ergebnis der Auswertung generiert er ein NatixQueryResult. Diese Klasse ist durch Umbenennung der ehemaligen RuleProcessor-Klasse entstanden. DB2QueryResult Die DB2-spezifische Implementierung der Pending Action List, die das Ergebnis einer Regelauswertung mit der DB2 darstellt. NatixQueryResult Die NatixQueryResult-Klasse verkörpert eine Pending Action List als Resultat einer Regelauswertung mit NATIX und Saxon. Diese Klasse ist durch Umbenennung der ehemaligen QueryResult-Klasse entstanden. DB2Actioninterpreter Die DB2Actioninterpreter-Klasse kann ein DB2QueryResult interpretieren und die beinhalteten Aktionen optimiert für die DB2 ausführen. NatixActioninterpreter Der NatixActioninterpreter kann entsprechend ein NatixQueryResult abarbeiten und die enthaltenen Aktionen optimiert für NATIX ausführen. Diese Klasse ist durch Umbenennung der ehemaligen Actioninterpreter-Klasse entstanden. 5.2.2 Erweiterung der DB2-Fassade Um die Regelauswertung mit der DB2 zu ermöglichen, wird die Klasse DB2Transaction der DB2-Fassade um die Funktion execQueryMsg() erweitert. Der Funktion wird als Parameter die ID der Kontext-Nachricht (<<context_msg_id>>) und die auszuführende Regel (<<query>>) als String übergeben. In der Funktion wird die Regelauswertung mithilfe eines SQL/XMLStatements vorbereitet. Beispielsweise wird die XQuery Variable $___demaq_contextmsgid mit der ID der Kontext-Nachricht initialisiert. Diese Variable ist insbesondere für Zugriffe aus der Regel auf den Nachrichtenspeicher wichtig, 91 5.2 Demaq mit der DB2 Feinentwurf die durch SQL-Anfragen mit der Funktion db2-fn:sqlquery() erfolgen (vgl. Abschnitt 5.2.1.2). Auf diese Weise wird folgender SQL-Ausdruck erzeugt: 1 SELECT XMLQUERY( ’<<query>> ’ PASSING ’<<c o n t e x t m s g i d >> ’ AS ” d e m a q c o n t e x t m s g i d ”) 3 FROM sysibm . sysdummy1 ; Es wäre an dieser Stelle auch möglich XQuery direkt, d.h. ohne es in SQL/XML einzubetten, mit der DB2 auszuführen, indem das Schlüsselwort xquery vor die Regel gesetzt wird und beides an die DB2 übertragen wird. Dies wäre allerdings mit dem Nachteil verbunden, dass der XQuery-Ausdruck nicht parametrisiert werden könnte, wie beispielsweise durch die <<context_msg_id>> in obigem Ausdruck. Eine weitere Anpassung ist notwendig, da die DB2 bei der direkten Ausführung von XQuery kein Kontext-Dokument hat. Das bedeutet, dass der Punkt, der in XQuery auf das context-item verweist [5], im äußersten Kontext eines XQueryAusdrucks nicht definiert ist. Im Gegensatz dazu ist in Demaq das context-item als die Kontext-Nachricht definiert, so dass es in der DB2 zu einem Fehler kommt, wenn in einer Regel der Punkt verwendet wird. Aus diesem Grund muss für die DB2 das context-item explizit gesetzt werden. Dies kann nur durch einen XPathAusdruck geschehen. Der SQL/XML-Ausdruck zur Regelauswertung wird deshalb wie folgt erweitert: 1 SELECT XMLQUERY( ’ $ demaq contextmsg/(<<query >>) ’ PASSING 3 (SELECT message FROM me ssa g es WHERE i d= ’<<c o n t e x t m s g i d >> ’ ) AS ” 5 ’<<c o n t e x t m s g i d >> ’ AS ” demaq contextmsg ” , d e m a q c o n t e x t m s g i d ”) FROM sysibm . sysdummy1 ; Mit der Variable $___demaq_contextmsg wird nicht nur in der Regel (<<query>>) das context-item gesetzt, sondern auf sie wird auch zugegriffen, wenn in der DQL-Anwendung die Funktion qs:message() verwendet wird (vgl. 92 5.2 Demaq mit der DB2 Feinentwurf Tabelle 4 auf Seite 90). 93 Implementierung 6 Implementierung In den vorangehenden Kapiteln wurden zunächst die Ziele und Anforderungen formuliert (Kapitel 3), die zu implementierenden System-Varianten konzeptuell entworfen (Kapitel 4) und anschließend auf logischer Ebene verfeinert (Kapitel 5). In diesem Kapitel wird nun das verfeinerte Design auf physischer Ebene optimiert. Die physische Optimierung wird zunächst für den Nachrichtenspeicher (Abschnitt 6.1) und anschließend für die Regelauswertung mit der DB2 (Abschnitt 6.2) vorgenommen. 6.1 Optimierung der DB2 als Nachrichtenspeicher In diesem Kapitel wird dargestellt, inwiefern eine physische Optimierung mit DB2 als Nachrichtenspeicher möglich ist. 6.1.1 Indizes Grundsätzlich wird von DB2 bei jeder Relation für die Spalten im Primärschlüssel implizit ein Index angelegt [34]. Deshalb ist für folgende Tabellen keine explizite Erzeugung eines Index notwendig, da der Zugriff ausschließlich über diesen Schlüssel erfolgt: • queues (Definition der Warteschlangen) • properties (Definition der Attribute) • msg_property (Zuordnung: Nachrichten zu Eigenschaftswert) • queue_property (Zuordnung: Queue zu Eigenschaftsdefinition) Die Indizes für die Tabellen der Nachrichten-Warteschlangen wurden bereits im Kapitel 5.1.4 vorgestellt. Ebenso wurden die Indizes der Slices im Kapitel 4.2.5 erläutert. Ansonsten sind keine weiteren Indizes für Tabellen in der DB2 anzulegen. 94 6.1 Optimierung der DB2 als Nachrichtenspeicher 6.1.2 Implementierung Datenblöcke für große XML-Nachrichten Die Größe der Datenblöcke (pagesize) in der DB2 ist standardmäßig 4KB. Wenn einzelne Daten in Spalten größer sind als 4KB, werden sie in 4KB große Teile zerlegt und auf mehreren Datenseiten gespeichert [36]. Dadurch leidet das Leistungsverhalten, da die Daten bei jedem Lesevorgang aus vielen verteilten Teilstücken rekonstruiert werden müssen. Eine Optimierungsmöglichkeit hierfür besteht darin, einen Tablespace mit zugehörigem Bufferpool mit größeren Datenblöcken (max. 32KB) anzulegen. Zusätzlich wird ein Tablespace mit zugehörigem Bufferpool mit kleinen Datenblöcken (min. 4KB) erzeugt. Die relationalen Daten, die gewöhnlich wenig Platz in Anspruch nehmen, werden in dem Tablespace mit kleinen Datenblöcken gespeichert und die großen XML- bzw. LOB-Daten in dem mit großen Datenblöcken. In Frage kommt diese Art der Optimierung für die Tabelle msg_property, queue_property und die Tabelle, in der die Nachrichten im XML-Format gespeichert werden. Das zugehörige Statement zum Erzeugen der Tabelspaces und zum Auslagern der Daten sieht wie folgt aus (vgl. [36]): create b u f f e r p o o l bp4k 2 p a g e s i z e 4k ; create b u f f e r p o o l bp32k 4 p a g e s i z e 32 k ; create t a b l e s p a c e r e l D a t a 6 p a g e s i z e 4K managed by a u t o m a t i c s t o r a g e 8 b u f f e r p o o l bp4k ; create t a b l e s p a c e xmlData 10 p a g e s i z e 32K managed by a u t o m a t i c s t o r a g e 12 b u f f e r p o o l bp32k ; create table me ssa g es ( 14 id bigint message not null , xml not null , 95 6.1 Optimierung der DB2 als Nachrichtenspeicher 16 −− s t a t e : 0=enqueued ,1= d e l e t e d s t a t e smallint not null default 0 18 Implementierung check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ) in r e l D a t a 20 l o n g in xmlData ; Abbildung 26: Durch räumlich getrennt gespeicherte Daten verlängern sich die I/O-Phasen, weil der Lesekopf der Festplatte umpositioniert werden muss Ein Nachteil dieser Lösung ist, dass die Daten einer Tabellenzeile räumlich getrennt voneinander in unterschiedlichen Tablespaces und damit in unterschiedlichen Containern auf der Festplatte gespeichert werden. Durch die physische Trennung der Daten auf der Festplatte muss der Lesekopf zum Lesen der ganzen Datenzeile mindestens einmal neu positioniert werden (vgl. Abbildung 26), wodurch sich die I/O-Phase durch die erhöhte Seek Time verlängert [31]. Dementsprechend ist die oben vorgeschlagene Lösung nur optimal, wenn tatsächlich große XML-Nachrichten (> 3KB) verarbeitet werden. Sollte die zu speichernde Nachricht kleiner als 3KB sein, wird sie entfernt von den zugehörigen Daten gespeichert, obwohl sie auf die Datenseite der Zeile passen würde. Um diesem Nachteil entgegenzuwirken, wird für XML-Daten eine Inline-Option hinzugefügt [18]. Das 96 6.1 Optimierung der DB2 als Nachrichtenspeicher Implementierung zugehörige Create Table-Statement verändert sich damit wie folgt (vgl. [36]): create table me ssa g es ( 2 id bigint message 4 not null , xml not null i n l i n e l e n g t h 3 0 0 0 , −− s t a t e : 0=enqueued ,1= d e l e t e d s t a t e smallint not null default 0 6 check ( s t a t e in ( 0 , 1 ) ) , primary key ( i d ) ) in r e l D a t a 8 l o n g in xmlData ; Der obige Zusatz ”inline length 3000“ besagt, dass XML-Daten bis zu einer Länge von 3KB zusammen mit den anderen Daten der Tabellenzeile auf der gleichen Datenseite gespeichert werden. Nur wenn eine Nachricht größer als 3KB ist, wird diese auf den Tablespace mit der größeren pagesize von 32KB ausgelagert. Diese Inline ist nur für den XML-Datentyp vorhanden, so dass für die LOBDaten eine andere Lösung gefunden werden muss. Optimal für die Tabellen msg_property und queue_property ist es, keine Daten auf den Tablespace mit der pagesize von 32KB auszulagern. Denn in den meisten Fällen wird die Größe der Property-Definitionen und der Property-Werte 3KB nicht überschreiten, so dass nur in Ausnahmefällen längere Daten auf mehrere Datenseiten aufgeteilt werden. 6.1.3 Parallelisierung von Lese- und Schreibzugriffen Parallelität zu erreichen stellt eine wichtige Möglichkeit zur Optimierung des Leistungsverhaltens im Demaq-System dar. NATIX unterstützt Parallelität in der Speicherverwaltung derzeit nicht explizit. Anders bei der DB2, mit der Parallelität bei der Ausführung per se automatisch erreicht werden kann, z.B. auf einem Server mit mehr als einem Prozessor. Beim Speichern von Daten kann mit der DB2 ebenso Parallelität genutzt werden. Diese muss allerdings explizit konfiguriert werden. Ist sie eingerichtet, so wird die parallelisierte Speicherverwaltung 97 6.1 Optimierung der DB2 als Nachrichtenspeicher Implementierung von der Datenbank automatisch verwaltet. Lese- und Schreibzugriffe auf Festplatten stellen einen Engpass in gängigen Computersystemen dar. Im Gegensatz hierzu ist das Lesen aus dem Hauptspeicher oder Caches um ein Vielfaches schneller. Eine Möglichkeit, um dieses Problematik abzumildern, ist es, die Daten in mehrere kleine Teile zu zerlegen und jeweils auf unterschiedlichen Festplatten parallel zu speichern. Dadurch wird die zu speichernde bzw. lesende Datenmenge je Festplatte reduziert, so dass sich Leseund Schreibvorgänge verkürzen (vgl. Abbildung 27). Dieses Prinzip wird von der DB2 unterstützt und kann automatisch verwaltet werden [41]. Um alle Tablespaces automatisch per default von dem DBMS auf mehrere Festplatten verteilen zu lassen, muss die Datenbank mit mehreren Zielpfaden erzeugt werden: create d a t a b a s e demaq 2 automatic s t o r a g e yes on /mnt/ d i s k 2 / dknochen , 4 /mnt/ d i s k 3 / dknochen , /mnt/ d i s k 4 / dknochen , 6 /mnt/ d i s k 5 / dknochen dbpath on /mnt/ d i s k 6 / dknochen ; Mit obigem Statement wird eine Datenbank demaq erzeugt, deren Daten automatisch auf fünf Festplatten verteilt werden [19]. Auf der ersten Festplatte befindet sich das Betriebssystem sowie der Programm-Code von Demaq und der DB2. Die Festplatten zwei bis fünf werden ausschließlich für die Daten-Container der Tablespaces verwendet. Der Datenbankpfad ist in diesem Beispiel auf der sechsten Festplatte. Hier werden einige Steuerdateien von dem DBMS für die Datenbank abgelegt. Mit dieser Beispielkonfiguration, die in den Tests in Kapitel 7.2 verwendet wird, kann eine hoher Grad an Parallelität erreicht werden. 98 6.1 Optimierung der DB2 als Nachrichtenspeicher Implementierung Abbildung 27: Automatische Speicherverwaltung über mehrere Festplatten (adaptiert von [41]). (a) Engpass bei der Speicherung auf einer Festplatte durch lange I/O-Zyklen. (b) Speicherung auf mehreren Festplatten und Verkürzung der I/O-Zyklen durch Parallelisierung 6.1.4 Nebenläufige Verarbeitung von Nachrichten Das Realisierungsvorhaben der Nebenläufigkeit wird dadurch erleichtert, dass der Quelltext des Demaq-Ausführungssystems bereits alles Notwendige enthält, um die nebenläufige Verarbeitung von Nachrichten zu ermöglichen: Innerhalb eines Dispatchers (vgl. Kapitel 2.1.2.2) können beliebig viele ProcessingThreads gestartet werden. Jedoch wird im aktuellen System immer nur ein Prozess pro Dispatcher gestartet, da mit NATIX als Nachrichtenspeicher keine nebenläufigen Verarbeitungen möglich sind. Die Anzahl der gestarteten Threads kann mit der DB2 als Nachrichtenspeicher erhöht werden, indem die Funktion Dis99 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung patcher::increaseThreadCount() beliebig oft vor dem Start eines Dispatchers aufgerufen wird. Damit sind die Anpassungen für die Realisierung der Nebenläufigkeit mit der DB2 trivial. 6.2 Optimierung der Regelauswertung mit der DB2 In diesem Kapitel werden Möglichkeiten dargestellt, mit denen die Regelauswertung mithilfe der DB2 optimiert werden kann. 6.2.1 Vermeidung von Serialisier- und Parsingvorgängen XML-Dokumente werden von der DB2 ausschließlich in serialisierter Textform an aufrufende Applikationen zurückgegeben (vgl. Kapitel 2.3.2). Ebenso können sie nur in serialisierter Form an die DB2 übermittelt werden. Aus diesem Grund ist der Aufwand für Parsing- und Serialisierungs-Vorgänge umso höher, je mehr Nachrichten zwischen der DB2 und einer anderen Komponente ausgetauscht werden. Abbildung 28 stellt exemplarisch die Interaktion von Saxon als Regelauswerter, DB2 als Nachrichtenspeicher und Demaq dar. Die Anwendung ist so definiert, dass eine Nachricht, die über eine HTTP-Verbindung kommt, in einer GatewayQueue vom Typ Incoming gespeichert wird. Anschließend wird sie an eine interne Warteschlange vom Typ Basic weitergeleitet. Diese zwei enqueue-Aufrufe bedingen fünf Parsing- und vier Serialisierungsvorgänge im System. Durch die Übergänge zwischen den verschiedenen Komponenten im Demaq-System entsteht ein Overhead an redundanten Parsing- und Serialisierungs-Operationen. Aus diesem Grund ist zu erwarten, dass die Tests zum Leistungsverhalten dieser SystemVariante eher negativ ausfallen. Verbessert werden kann diese Situation, wenn statt Saxon DB2 zur Regelauswertung eingesetzt wird. Durch diese Änderung fallen die KomponentenÜbergänge zwischen Nachrichtenspeicher und Regelauswerter weg und damit 100 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung Abbildung 28: Serialisierungs- und Parsing-Vorgänge in einer Beipsiel-Anwendung im DemaqSystem mit der DB2 und Saxon auch überflüssige Parsing- und Serialisierungs-Vorgänge. Gegenüber der in Abbildung 28 schematisierten Beispielanwendung kann auf diese Weise einer von fünf Parsing-Vorgängen und eine von vier Serialisierungs-Operationen eingespart werden (vgl. Abbildung 29). Eine weitere Einsparung ist möglich, indem Nachrichten, die mit enqueue in eine andere interne Warteschlange eingereiht werden, nicht erst an den DemaqKern zurückgegeben werden. Denn bisher werden Nachrichten im QueryResult als Ergebnis einer Regelauswertung an den Demaq-Kern übergeben, damit dort die enthaltenen Aktionen interpretiert und mit den Nachrichten ausgeführt werden können. Soll eine Nachricht in einer Aktion nicht an eine Gateway-Queue, 101 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung Abbildung 29: Serialisierungs- und Parsing-Vorgänge in einer Beipsiel-Anwendung im DemaqSystem mit der DB2 als Nachrichtenspeicher und Regelauswerter sondern an eine interne Basic-Queue übermittelt werden, wird sie unverändert an die DB2 zurückgegeben und löst auf diese Weise einen zusätzlichen Parsingund Serialisierungs-Vorgang aus. Nachrichten, die intern weitergeleitet werden, sollten direkt in der DB2 mit enqueue eingereiht werden. Wird die Regelauswertung derart verändert, müssen diese Nachrichten später nicht noch einmal geparst werden (vgl. Abbildung 30). Statt der kompletten Nachrichten werden dem Demaq-Kern nur die IDs der intern neu eingereihten Nachrichten mitgeteilt, damit der Actioninterpreter diese bei der Generierung der ConsequenceList berücksichtigen kann. Der Actioninterpreter muss demnach angepasst werden, so dass er interne enqueues nicht noch einmal ausführt. 102 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung Abbildung 30: Serialisierungs- und Parsing-Vorgänge in einer Beipsiel-Anwendung im DemaqSystem mit der DB2 als Nachrichtenspeicher und Regelauswerter (optimiert) 6.2.2 Implementierung der Regelauswertung mit DB2 In Kapitel 5.2.2 wurde beschrieben, wie sich die Regelauswertung in der DB2 auf logischer Ebene umsetzen läßt. Darauf aufbauend wurde in Kapitel 6.2.1 erläutert, wie der Ablauf in der Auswertung der Regeln optimiert werden kann. Zur Umsetzung des sich ergebenden Mechanismus der Regelauswertung bieten sich zwei Alternativen an. Zum einen können Stored Procedures für die Auswertung von Regeln verwendet werden. Zum anderen kann ein SQL-Statement zusammengesetzt werden, dass als Seiteneffekte die enqueues ausführt und ein QueryResult zurückliefert. Beide Varianten werden in den beiden folgenden Abschnitten 6.2.2.1 und 6.2.2.2 detailliert vorgestellt. 103 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung Entsprechend der vorhergehenden Diskussionen (vgl. Kapitel 5.2.2 und 6.2.1) sind folgende Arbeitsschritte in beiden Varianten auszuführen: 1. Die XQuery-basierte Regel muss wie bisher auf die Kontext-Nachricht angewandt und zu einer Aktionenliste im XML-Format evaluiert werden. 2. Alle internen enqueues müssen direkt in der DB2 ausgeführt werden. 3. Die Aktionenliste muss geändert werden, so dass bei den internen enqueueAktionen nur die ID der neu eingereihten Nachrichten enthalten ist und nicht die komplette Nachricht selbst. 4. Die modifizierte Aktionenliste muss als Ergebnis der Regelauswertung zurückgegeben werden. 6.2.2.1 Regelauswertung mit Stored Procedures In Stored Procedures können sowohl SQL- als auch SQL/XML- und XQuery-Ausdrücke verwendet werden [38]. Außerdem können mehrere einzelne Statements zu einem atomaren Block zusammengefasst werden [47]. Zunächst wird für jede Regel eine eigene Stored Procedure mit dem Präfix qs_rule_ und dem Namen <<rulename>> wie folgt erzeugt, damit mit dieser die Aktionenliste bei der Regelauswertung generiert werden kann: 1 CREATE PROCEDURE q s r u l e <<rulename>> ( IN msgid int ,OUT p a l xml ) LANGUAGE SQL 3 READS SQL DATA NO EXTERNAL ACTION 5 P1 : BEGIN SET p a l=XMLQUERY( ’ $ 7 demaq contextmsg/(<<query >>) ’ PASSING (SELECT message FROM me ssa g es WHERE i d=msgid ) 9 AS ” msgid AS ” demaq contextmsg ” , d e m a q c o n t e x t m s g i d ”) ; 11 END P1 104 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung In obiger Vorlage wird anstelle von <<query>> der XQuery-Ausdruck, in den die Regel vom XQL-Parser [46] umgewandelt wurde, eingefügt. Die auf diese Weise erzeugte Stored Procedure wird nicht direkt vom DB2RuleProcessor aufgerufen, da sie die Aktionenliste liefert, welche noch die Aktionen für interne enqueues enthält. Damit die internen enqueues bereits innerhalb der DB2 ausgeführt werden und nicht an den Demaq-Kern zurückgegeben werden, wird eine weitere Stored Procedure mit dem Namen ruleexecutor generiert, die zur Regelauswertung vom DB2RuleProcessor aufgerufen wird. Dieser Prozedure wird der Regelname von der Regel übergeben, die ausgeführt werden soll. Mit Hilfe von dem Regelnamen weiß die ruleexecutor-Prozedur, welche Regel-Prozedur sie aufrufen muss, um für die Regel die Aktionenliste zu bekommen. Die von der Regel-Prozedur erhaltene Aktionenliste wird dann weiterverarbeitet, um die internen enqueues direkt auszuführen (vgl. Kapitel 6.2.1). Die Umsetzung der Stored Procedure ruleexecutor wird im Folgenden dargestellt: 1 CREATE PROCEDURE r u l e e x e c u t o r ( IN msgid int , IN rulename varchar ( 2 5 6 ) ,OUT q r e s u l t CLOB ) LANGUAGE SQL 3 MODIFIES SQL DATA NO EXTERNAL ACTION 5 P1 : BEGIN DECLARE p a l XML; 7 DECLARE i n s e r t e d XML; DECLARE stmt varchar ( 1 0 0 0 ) ; 9 DECLARE newidsxml XML; DECLARE m o d i f i e d p a l XML; 11 SET stmt= ’ c a l l q s r u l e ’ c o n c a t rulename c o n c a t ’ ( ? , ? ) ’ ; 13 PREPARE s 1 FROM stmt ; 105 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung 15 −− 1 . R e g e l zu e i n e r A k t i o n e n l i s t e e v a l u i e r e n : EXECUTE s 1 into p a l USING msgid ; 17 −− 2 . I n t e r n e e n q u e u e s d e r r e s u l t i e r e n d e n A k t i o n e n l i s t e 19 −− d i r e k t a u s f u e h r e n und d i e neuen N a c h r i c h t e n −IDs z u r u e c k g e b e n : SELECT 21 XMLELEMENT (NAME ”msgids ” , XMLAGG ( XMLELEMENT ( NAME ” i d ” , i d ) 23 ORDER BY i d ) ) 25 INTO P1 . newidsxml FROM new table ( 27 INSERT INTO me ssa g es ( id , queuename , message , m e s s a g e s i z e , s t a t e ) SELECT n e x t v a l f o r MESSAGE ID SEQ , enq . t a r g e t , enq . message , l e n g t h ( x m l s e r i a l i z e ( enq . message as clob ) ) as l e n g t h , 0 29 FROM XMLTABLE( ’ $ p a l / enqueue ’ PASSING P1 . p a l AS ” p a l ” 31 COLUMNS ”MESSAGE” XML PATH ’ document { . / message / ∗ [ 1 ] } ’ , 33 ”TARGET” varchar ( 2 5 5 ) PATH ’ . / @ t a r g e t ’ , ”POSITION” int PATH ’ . / p o s i t i o n ( ) ’ 35 ) AS enq ORDER BY enq . position 37 ) GROUP BY s t a t e ; 39 −− 3 . Die u r s p r u e n g l i c h e A k t i o n e n l i s t e v e r a e n d e r n und a n s t e l l e 41 −− d e r N a c h r i c h t e n d i e neuen IDs e i n f u e g e n : SET m o d i f i e d p a l=XMLQUERY( ’ copy $new := $ p a l 43 modify f o r $ e n q u e u e p o s i t i o n i n $new/ enqueue / p o s i t i o n ( ) l e t $newmsgid := $newmsgids / i d [ p o s i t i o n ( )=$ e n q u e u e p o s i t i o n ] 45 l e t $enqueue := $new/ enqueue [ p o s i t i o n ( )=$ e n q u e u e p o s i t i o n ] r e t u r n do r e p l a c e $enqueue / message with <message msgid =”{ $newmsgid }”/> 106 6.2 Optimierung der Regelauswertung mit der DB2 47 Implementierung r e t u r n $new ’ PASSING 49 P1 . p a l AS ” p a l ” , P1 . newidsxml AS ”newmsgids ” 51 ) ; 53 −− 4 . Die m o d i f i z i e r t e A k t i o n e n l i s t e z u r u e c k l i e f e r n : SET q r e s u l t=XMLSERIALIZE( m o d i f i e d p a l as clob ) ; 55 END P1 Die Ausführung der internen enqueues wird mit einem SELECT-Statement mit Seiteneffekt durchgeführt [3]. Mit dem Konstrukt ”new table(INSERT...)“ wird aus den eingefügten Datensätzen eine temporäre Tabelle erzeugt, auf die in einem äußeren SELECT-Statement zugegriffen werden kann. Auf diese Weise können die INSERT-Statements ausgeführt und gleichzeitig die neu eingefügten NachrichtenIDs zurückgegeben werden. Im dritten Schritt (siehe Kommentare im Code) wird die ursprüngliche Aktionenliste mithilfe eines XQuery-Update-Statements (”do replace“) verändert, indem die Nachrichten-IDs der neu eingefügten Nachrichten an die Stelle der Nachrichten selbst gesetzt wird. 6.2.2.2 Regelauswertung durch ein atomares SQL-Statement Etwas komplizierter als die Umsetzung mit Stored Procedures ist die Regelauswertung bei Ausführung eines einzelnen SQL-Statements. Hierbei werden die einzelnen SQL-Statements, wie sie in Kapitel 6.2.2.1 vorgestellt wurden, zu einem einzigen Ausdruck zusammengefasst. Dementsprechend werden die Zwischenergebnisse nicht in Variablen, sondern in temporären Tabellen mithilfe des WITH-Statements [23] zwischengespeichert. Das sich daraus ergebende Statement sieht wie folgt aus: 1 with −− 1 . E v a l u i e r e A k t i o n e n l i s t e 107 6.2 Optimierung der Regelauswertung mit der DB2 3 a c t i o n s ( p a l ) AS ( SELECT XMLQUERY( ’ $ 5 Implementierung demaq contextmsg/(<<query >>) ’ PASSING (SELECT message FROM me ssa g es WHERE i d= ’<<c o n t e x t m s g i d >> ’ ) 7 AS ” demaq contextmsg ” , ’<<c o n t e x t m s g i d >> ’ AS ” 9 d e m a q c o n t e x t m s g i d ”) FROM sysibm . sysdummy1 ) , 11 −− 2 . Fuehre i n t e r n e e n q u e u e s d i r e k t aus newmsgids ( id , group ) AS ( 13 SELECT id , ’dummy ’ ” FROM new t a b l e ( 15 INSERT INTO m essa g es ( id , queuename , message , m e s s a g e s i z e , state ) SELECT n e x t v a l f o r MESSAGE ID SEQ , enq . t a r g e t , enq . message , l e n g t h ( x m l s e r i a l i z e ( enq . message a s c l o b ) ) , 0 17 FROM XMLTABLE( ’ $ p a l / enqueue ’ PASSING (SELECT p a l FROM a c t i o n s FETCH FIRST 1 ROW ONLY) AS ” pal ” 19 COLUMNS ”MESSAGE” XML PATH ’ document { . / message / ∗ [ 1 ] } ’ , 21 ”TARGET” v a r c h a r ( 2 5 5 ) PATH ’ . / @target ’ , ”POSITION” i n t PATH ’ . / p o s i t i o n ( ) ’ 23 ) AS enq ORDER BY enq . p o s i t i o n 25 ) ), 27 −− G ru p p ie r e d i e neu e i n g e r e i h t e n N a chric hten −IDs 29 i n s e r t e d ( i d s ) AS ( SELECT XMLELEMENT(NAME ”msgids ” , 31 XMLAGG (XMLELEMENT (NAME ” i d ” , n . i d ) ORDER BY n . i d ) ” ) 33 FROM newmsgids n 108 6.2 Optimierung der Regelauswertung mit der DB2 Implementierung GROUP BY n . group 35 ), 37 −− 3 . Passe d i e A k t i o n e n l i s t e an : e r s e t z t d i e b e r e i t s e i n g e r e i h t e n −− N a c h r i c h t e n durch i h r e i d s 39 t o b e r e t u r n e d ( p a l ) AS ( SELECT xmlquery ( ’ copy $new := $ p a l 41 modify f o r $ e n q u e u e p o s i t i o n i n $new/ enqueue / p o s i t i o n ( ) l e t $newmsgid := $newmsgids / i d [ p o s i t i o n ( )= $enqueueposition ] 43 l e t $enqueue := $new/ enqueue [ p o s i t i o n ( )=$ e n q u e u e p o s i t i o n ] r e t u r n do r e p l a c e $enqueue / message with <message msgid =”{$newmsgid }”/> 45 r e t u r n $new ’ PASSING (SELECT p a l FROM a c t i o n s FETCH FIRST 1 ROW ONLY) AS ”pal ” , 47 ( Select i d s from i n s e r t e d FETCH FIRST 1 ROW ONLY) AS ” newmsgids ” ) 49 FROM sysibm . sysdummy1 ) 51 −− 4 . Gebe d i e a n g e p a s s t e A k t i o n e n l i s t e a l s E r g e b n i s z u r u e c k 53 SELECT p a l FROM t o b e r e t u r n e d ; Der obige SQL-Code besteht aus einem einzigen zusammengesetzten Statement. Zur besseren Lesbarkeit sind die einzelnen Schritte zur Regelauswertung jeweils kommentiert. Der Vorteil dieser Variante ist, dass Regeln jeweils dynamisch in ein SQLStatement eingebunden werden und dass die DB2 über alle Teilausdrücke des SQL-Statements hinweg eine automatische Optimierung vornehmen kann [3]. 109 6.2 Optimierung der Regelauswertung mit der DB2 6.2.3 Implementierung Steuerung der Weiterverarbeitung von Nachrichten mit Triggern Ein Feature der DB2, das zum Umsetzen von Demaq-Funktionalität in der DB2 in Betracht gezogen werden kann, sind Trigger. Beispielsweise kann erwogen werden, Trigger zu verwenden, um nach dem Einfügen einer neuen Nachricht die Regelauswertung auf dieser zu starten. Hierbei treten allerdings zwei Probleme auf, die einen Einsatz von Triggern zu diesem Zweck unmöglich machen. Das eine Problem ist, dass es nicht möglich ist, die Ausführung eines Triggers zu verzögern, bis eine eingefügte Nachricht mit commit bestätigt wurde. D.h. Trigger würden immer sofort zum Zeitpunkt des Einfügens einer Nachricht ausgeführt, so dass auf diese Weise Nachrichten weiterverarbeitet würden, die potenziell durch ein rollback wieder gelöscht werden könnten. Das zweite Problem geht mit dem Ersten einher: Trigger laufen immer im Kontext ihrer aufrufenden Transaktion ab. Es ist nicht möglich innerhalb eines Triggers eine Transaktion zu beenden und eine neue Transaktion zu starten [25]. Auch darf in einem Trigger keine Prozedur aufgerufen werden, die ein commit auslöst [24]. Da aber die Verarbeitung einer neu eingefügten Nachricht laut Spezifikation des Demaq-Systems [6, 46] in den Kontrollabschnitt einer eigenen Transaktion fällt, ist der Einsatz von Triggern auch aus diesem Grund nicht möglich. 110 Evaluation 7 Evaluation Die bisherigen Betrachtungen haben sich mit der Analyse, dem Design sowie der Implementation der zu entwickelnden Demaq-System-Varianten beschäftigt. In diesem Kapitel werden die entwickelten System-Varianten evaluiert. Zum einen wird das System qualitativ überprüft (Abschnitt 7.1). Zum anderen wird es quantitativ mittels definierter Testanwendungen experimentell untersucht (Abschnitt 7.2). 7.1 Qualitative Evaluation Die qualitative Evaluation bewertet die entwickelten System-Varianten anhand der Anforderungen aus Kapitel 3.3. 7.1.1 Korrektheit Zum Überprüfen der Korrektheit wurden Testfälle definiert. Wichtig hierbei war, dass sowohl das System mit NATIX, als auch das mit der DB2 zu den gleichen Ergebnissen kommen. Die definierten Testanwendungen sind im Anhang in Kapitel A.1.1 aufgelistet. Die Testfälle wurden zudem verwendet, um peu a peu die lauffähige Funktionalität im System mit ausgetauschtem Nachrichtenspeicher und im späteren Verlauf mit der ausgetauschten Regelauswertung zu vervollständigen. Deshalb wurden die Tests derart definiert, dass sie sich sukzessiv in der Komplexität steigern und somit mehr Funktionen des Demaq-Systems abdecken. Auf diese Weise konnten nach dem Vorbild der agilen Software-Entwicklung (”Working software is the primary measure of progress.“ [2]) zunächst die wichtigsten Funktionalitäten, wie beispielsweise ”create queue“ oder ”create rule“, implementiert sowie getestet werden. Anschließend wurden nach und nach weitere Features, wie z.B. ”qs:slice“ oder ”qs:slicekey“, ergänzt. 111 7.1 Qualitative Evaluation Evaluation Eine Einschränkung der System-Varianten mit der DB2 als Nachrichtenspeicher hat sich bei den Tests gezeigt und bleibt als offenes Problem bestehen: Es kann nur auf Properties und Slicekeys der aktuell bearbeiteten Nachricht zugegriffen werden. Dieses Problem ist darauf zurückzuführen, dass von der XMLRepräsentation einer Nachricht nicht auf ihre ID im Nachrichtenspeicher geschlossen werden kann, da die Spalte message in der Tabelle messages nicht eindeutig ist. Für den Zugriff auf Properties oder den Slicekey einer beliebigen Nachricht, wird die ID aber zwingend benötigt. Im System mit NATIX wird hierzu eine Processing Instruction verwendet, die an jede Nachricht angefügt die Nachrichten-ID enthält. Dies wurde nicht implementiert. 7.1.2 Modularisierung Eine Modularisierung konnte im Rahmen dieser Diplomarbeit umgesetzt werden. Auf den Nachrichtenspeicher wird nun ausschließlich über die NatixGatewaybzw. die DB2Gateway-Klasse zugegriffen, so dass ein Austausch des Nachrichtenspeichers allein durch Implementierung einer passenden Gateway-Klasse erfolgen kann. Ähnlich verhält es sich beim Austausch der Regelauswertung. Hierzu werden die modularisierten Klassen NatixRuleprocessor, NatixQueryResult und NatixActioninterpreter ersetzt. Im Rahmen dieser Arbeit ist dies geschehen mit den Klassen DB2Ruleprocessor, DB2QueryResult und DB2Actioninterpreter. 7.1.3 Leistungsverhalten In dieser Diplomarbeit wurde gezeigt, dass eine Integration der relationalen Datenbank DB2 als Nachrichtenspeicher in das Demaq-System möglich ist. Die Optimierung des Leistungsverhaltens war über die Machbarkeit hinaus eine wichtige Anforderung. Aus diesem Grund wurden zahlreiche Optimierungsmöglichkeiten sowohl auf logischer als auch auf physischer Ebene vorgeschlagen. Letztendlich 112 7.2 Quantitative Evaluation Evaluation konnte eine Optimierung hauptsächlich nur auf theoretischer Basis durchgeführt werden, so dass ein Vergleich für viele Varianten nicht vorliegt. Außerdem wurde bei der Implementierung auf eine zu frühe Optimierung verzichtet, weshalb das derzeitige Leistungsverhalten qualitativ bewertet als steigerungsfähig einzustufen ist. 7.2 Quantitative Evaluation Wesentlicher Bestandteil dieser Diplomarbeit ist die Bearbeitung von zwei Teilproblemen, die bereits in Kapitel 3.4.2 kurz beschrieben wurden. Demgemäß werden zur quantitativen Evaluation zwei unabhängige Experimentreihen für die Teilprobleme durchgeführt: Zum einen wird das Leistungsverhalten verschiedener Abbildungen von Warteschlangen in einem relationalen DBMS untersucht und zu der nativen Implementierung in NATIX in Vergleich gesetzt. Zum anderen wird die Veränderung im Leistungsverhalten des Demaq-Ausführungssystems betrachtet, nachdem zur Regelauswertung die DB2 XQuery Engine anstelle von Saxon verwendet wird. Um wissenschaftliche Fragestellungen zu untersuchen, gibt es eine Vielzahl an möglichen Methoden. Demzufolge muss die Frage beantwortet werden, warum ein formales Experiment die geeignete Wahl ist. Da aber im Rahmen dieser Arbeit ein funktionales Softwaresystem geschlossen untersucht wird, ohne Benutzer oder andere äußere Umstände in der Betrachtung zu berücksichtigen, erscheint die wissenschaftliche Methode des formalen Experiments als offensichtliche Wahl. Dennoch werden die formalen Anforderungen für ein Experiment in Kapitel 7.2.1 zur Vollständigkeit kurz überprüft. Darüber hinaus sollen die Experimente wie folgt definiert und durchgeführt werden [39]: 1. Überprüfung der Anforderungen für formale Experimente (Kapitel 7.2.1) 2. Konzeption (Kapitel 7.2.2) 113 7.2 Quantitative Evaluation Evaluation 3. Design (Kapitel 7.2.3, 7.2.4 und 7.2.5) 4. Vorbereitung (Kapitel 7.2.7) 5. Durchführung (Kapitel 7.2.8) 6. Analyse (Kapitel 7.2.9). 7.2.1 Erfüllung der Anforderungen für formale Experimente In Tabelle 5 sind die Anforderungen aufgelistet, die laut [39] zu erfüllen sind, damit ein formales Experiment die richtige Methode für eine Untersuchung darstellt. Eigenschaft Experiment Grad der Kontrolle Hoch Schwierigkeit der Kontrolle Niedrig Grad der Wiederholbarkeit Hoch Aufwand der Wiederholung Niedrig Tabelle 5: Eigenschaften, welche die Durchführung eines Experiments rechtfertigen (vgl. [39]) Die wissenschaftliche Methode des formalen Experiments ist für die vorliegende Aufgabenstellung der Diplomarbeit die geeignete Wahl. Dementsprechend sind die formalen Anforderungen wie folgt erfüllt: Grad der Kontrolle Der Grad der Kontrolle ist hoch. Es gibt kaum Einflussfaktoren, die nicht kontrollierbar sind, wie z.B. menschliches Verhalten. Faktoren wie die Laufzeitumgebung können frei festgelegt und konstant gehalten werden. Schwierigkeit der Kontrolle Die Schwierigkeit der Kontrolle ist niedrig. Die Laufzeitumgebung wird nicht verändert. Das System kann über KompilierOptionen gesteuert werden und mit Hilfe von Logdateien überprüft werden. 114 7.2 Quantitative Evaluation Evaluation Grad der Wiederholbarkeit Die Untersuchung kann beliebig oft mit definierten Testfällen wiederholt werden. Aufwand der Wiederholung Ein Testdurchlauf wird mit einem einzelnen Shellskriptaufruf gestartet. 7.2.2 Konzeption der Experimente Die Konzeption eines Experiments beinhaltet die Festlegung des Ziels, bzw. der Ziele [39]. Idealerweise wird eine Fragestellung formuliert, die nach der Durchführung des Experiments beantwortet wird. Deshalb werden in folgenden Unterkapiteln 7.2.2.1 bzw. 7.2.2.2 die Ziele festgelegt und entsprechende Fragestellungen formuliert. Zur Vereinfachung wird nachfolgend vom ”Experiment Warteschlange“, bzw. ”Experiment Regelauswertung“ gesprochen. Gemeint sind die Experimente, die das entsprechende Problem, wie es in Kapitel 3.4.2 vorgestellt wurde, bearbeiten. 7.2.2.1 Ziele des Experiments Warteschlange Ziel dieses Experiments ist es, innerhalb des Demaq-Systems eine effiziente Warteschlangen-Abbildung in einem relationalen Datenbanksystem (im Speziellen in der DB2) zu finden. Diese Abbildung soll die effiziente Ausführung der enqueue- und dequeue-Funktionen sowie sonstige Operationen auf Warteschlangen im Demaq-System unterstützen. Zu diesem Zweck wurden in Kapitel 5.1.4 bereits einige Alternativen für mögliche Abbildungen diskutiert, von denen die Varianten 1, 6 und 7 (vgl. Kapitel 5.1.4.1, 5.1.4.6 und 5.1.4.7) auf ihre Leistungsfähigkeit hin überprüft werden. Die zu beantwortende Frage ist: Welche der untersuchten Abbildungen für Warteschlangen im relationalen Datenbanksystem bedingt eine schnellstmögliche Abarbeitung der Elemente? Und als zweite sich anschließende Frage: Wie gut ist das Leistungsverhalten dieser Abbildung im Gegensatz zu der nativen Warteschlangen-Implementierung des NATIX-Systems? 115 7.2 Quantitative Evaluation Evaluation Abbildung 31: Übersicht der Testanwendungen für die Experimente und deren benutzte DemaqFeatures 7.2.2.2 Ziele des Experiments Regelauswertung Ziel dieses Experi- ments ist es zunächst, zu überprüfen, ob eine Regelauswertung mit der XQueryEngine der DB2 möglich ist. Dabei ist es wichtig, dass die Demaq-spezifischen Funktionen möglichst vollständig und vor allem korrekt ausgeführt werden können. Ein weiteres Ziel ist es, das Leistungsverhalten der Regelauswertung mit der DB2 mit der Saxon-basierten Regelauswertung in Relation zu setzen. Die zu beantwortenden Fragen lauten demnach: Läßt sich die DemaqRegelauswertung vollständig und korrekt mit der DB2 umsetzen? Und des Weiteren: Wie steht das Leistungsverhalten dieser Regelauswertung im Verhältnis zur Regelauswertung mit Saxon? 7.2.3 Testanwendungen Die Testanwendungen sind mit unterschiedlicher Komplexität definiert und legen ihren Fokus auf unterschiedliche Demaq-Features (vgl. Abbildung 31). Auf diese Weise kann einerseits eine hohe Allgemeingültigkeit erreicht werden, da Anwendungsfelder in allen Komplexitätsstufen für Demaq denkbar sind. Andererseits 116 7.2 Quantitative Evaluation Evaluation Abbildung 32: Testanwendung 1 und 2: Simulation mit einem Server und mehreren Clients können so Zusammenhänge zwischen bestimmten Features von Demaq, wie z.B. der Zugriff auf Slices oder Properties, und dem Leistungsverhalten hergestellt werden. Beispielsweise könnte der Zugriff auf Properties im relationalen DBMS sehr effizient sein, während das Abfragen von Slices eher uneffizient ist. Welche Aussagen dieser Art am Ende getroffen werden können, ist offen, weshalb die Testanwendungen möglichst wenig antizipativ sein sollen. In den Versuchsanwendungen sollte möglichst keine Kommunikation nach außen erfolgen, so dass keine Indeterminismen im Kommunikationsaufbau über das Betriebssystem auftreten können. Demnach wird pro Anwendung nur für die Start- und Antwort-Nachricht ein externer Kommunikationskanal verwendet. Außerdem muss es in jeder Anwendung ein Terminierungs-Charakteristikum geben, das nicht an ein zufälliges Ereignis gekoppelt ist. Dadurch wird bei jedem Durchlauf der Test-Applikation eine gleichbleibende Menge an Arbeit garantiert. Beispielsweise könnte in einem deterministischen Ablauf eine festgelegte Anzahl an Nachrichten die Terminierung bewirken. Die Testapplikationen sollen typische Anwendungsparadigmen im Bereich der 117 7.2 Quantitative Evaluation Evaluation Business-Processes simulieren. Sie stellen aber isoliert betrachtet keine realistischen Anwendungsbeispiele dar. 7.2.3.1 Testanwendung 1: Client/Server-Simulation In dieser Testan- wendung tauschen mehrere Client-Warteschlangen Nachrichten mit einer Server Warteschlange aus. Die Server -Warteschlange wird überdurchschnittlich ausgelastet und stellt somit einen Engpass dar. Das Ziel der Clients ist es, 1000 Nachrichten mit dem Server hin und her zu wechseln. Die Anzahl der gewechselten Nachrichten wird innerhalb des Wurzelelementes einer Nachricht in dem Attribut msgcount vermerkt. Die Nachrichten werden ansonsten unverändert retourniert. Variantenname Anzahl der Clients Größe der Nachricht A1 5 1KB A2 11 1KB A3 21 1KB B1 5 10KB B2 11 10KB B3 21 10KB C1 5 100KB C2 11 100KB C3 21 100KB Tabelle 6: Varianten der Testanwendungen 1 und 2 Hat einer der Clients 1000 Nachrichten mit dem Server gewechselt, meldet er dies, indem er eine Nachricht an die report-Warteschlange schickt. Die reportWarteschlange wartet bis alle Clients eine Beendigungs-Nachricht gesendet haben und schickt dann eine Antwort-Nachricht, mit der die Anwendung beendet wird. Tabelle 6 listet Variationen auf, die mit dieser Anwendung untersucht werden. Auf diese Weise soll ein breites Spektrum an Komplexitäten abgedeckt werden. 118 7.2 Quantitative Evaluation Evaluation Abbildung 33: Testanwendung 3: Prozesskette mit Überkreuzung Für die Variante A1 ist der DQL-Code im Anhang A.1.2.1 angefügt. Abbildung 32 stellt die Testapplikation ”Client/Server-Simulation“ schematisch dar. 7.2.3.2 Testanwendung 2: Client/Server-Simulation mit qs:queue() Die Testanwendung ”Client/Server-Simulation mit qs:queue()“ ist identisch zu der ersten Testanwendung, außer dass die Clients nur 100 Nachrichten mit dem Server austauschen sowie dass die Anzahl der gewechselten Nachrichten nicht mehr in einem Attribut vermerkt wird. Stattdessen wird die aktuelle Anzahl der gewechselten Nachrichten darüber bestimmt, wie viele Nachrichten in einer Client-Warteschlange vorhanden sind. Zu diesem Zweck wird die Demaq-Funktion qs:queue() und die XQuery-Standard-Funktion fn:count() verwendet. Die Varianten dieser Testanwendung sind ebenfalls in Tabelle 6 aufgeführt. Beispielhaft für die Variante A1 ist der DQL-Code im Anhang A.1.2.2 angefügt. 7.2.3.3 Testanwendung 3: Prozesskette mit Überkreuzung Bei dieser Anwendung werden in mehreren Testreihen (vgl. Tabelle 7) unterschiedlich viele Prozessketten mittels Nachrichten gleichzeitig durch eine zirkulär angeordnete Reihe von Warteschlangen geschickt. Die Warteschlangen sind dabei derart an119 7.2 Quantitative Evaluation Evaluation geordnet, dass sie von zwei Seiten an die gleiche Warteschlange senden und somit eine virtuelle Acht formen. Damit die Nachrichten an der Überkreuzung richtig weitergeleitet werden, wird für sie ein Property verwaltet, in dem vermerkt wird, ob sie sich im Prozessverlauf auf der großen Schleife befinden und folglich auf die Kleine weitergeleitet werden müssen oder umgekehrt. Abbildung 33 visualisiert den Aufbau dieser Testanwendung. Variantenname Anzahl gleichzeitiger Größe der Prozessketten Nachrichten A1 5 1KB A2 20 1KB A3 40 1KB B1 5 10KB B2 20 10KB B3 40 10KB C1 5 100KB C2 20 100KB C3 40 100KB Tabelle 7: Varianten der Testanwendung 3 Die Prozesse werden durch eine Start-Nachricht von außen gestartet und jede Nachricht muss 50 mal die Prozesskette durchlaufen. Die Anzahl der Durchläufe wird in einem Property gespeichert. Sobald eine Nachricht 50 Durchgänge absolviert hat, wird dies durch eine Nachricht an die Warteschlange report gemeldet. Die report-Warteschlange wartet bis alle Prozesse abgeschlossen sind. Dann schickt sie eine Antwort-Nachricht an die ursprünglich aufrufende GatewayQueue, wodurch die Anwendung beendet wird. 120 7.2 Quantitative Evaluation Evaluation Abbildung 34: Testanwendung 4: Prozess-Simulation Split/Join 7.2.3.4 Testanwendung 4: Prozess-Simulation Split/Join In dieser Testanwendung laufen mehrere Prozesse gleichzeitig ab. Jeder Prozess wird an einer Stelle (split) auf zwei verschiedene Warteschlangen (child1 und child2) aufgeteilt. Anschließend wird eine der beiden Nachrichten mithilfe eines Slice (choose) auf die forward-Warteschlange weitergeleitet, während die andere Nachricht ignoriert wird. Welche Nachricht von den beiden weitergeleitet wird, wird durch das Attribut superior festgelegt, in dem per Zufall entweder true oder false gespeichert ist. Auf diese Weise soll ein Prozess simuliert werden, in dem an einer Stelle zwei Alternativen zur Auswahl stehen, von denen die bessere ausgewählt und weiterverarbeitet wird. Insgesamt wird die Split/Join-Simulation pro Nachricht 500 mal durchlaufen, wobei die Anzahl der absolvierten Durchläufe in dem Attribut processcount vermerkt wird. Sollte eine Nachricht die forward-Warteschlange zum 500. Mal passieren, wird diese in die report-Warteschlange umgeleitet. Die report-Warteschlange wartet bis alle Abläufe beendet sind und schickt anschließend die Antwort-Nachricht an die ursprünglich aufrufende Gateway-Queue. Damit wird die Anwendung terminiert. 121 7.2 Quantitative Evaluation Variantenname Evaluation Anzahl gleichzeitiger Größe der Prozesse Nachrichten A1 5 1KB A2 20 1KB A3 40 1KB B1 5 10KB B2 20 10KB B3 40 10KB C1 5 100KB C2 20 100KB C3 40 100KB Tabelle 8: Varianten der Testanwendung 4 Die Tests werden mit unterschiedlich großen Nachrichten und verschieden vielen parallelen Prozessen durchgeführt. Eine Übersicht der Varianten der Tests ist in Tabelle 8 aufgelistet. Für die Variante A1 ist der DQL-Code im Anhang in Abschnitt A.1.2.4 angefügt. 7.2.4 Design des Experiments Warteschlange Die Ziele dieses Experiments wurden bereits in Kapitel 7.2.2.1 festgelegt. Ebenfalls wurden die dazugehörigen wissenschaftlichen Fragestellungen formuliert. Für das Experiment Warteschlange sind zwei Fragen von Interesse. Dementsprechend unterteilt sich das in diesem Unterkapitel vorgestellte Experiment in zwei Teile (Teilexperimente A und B). Zunächst soll eine möglichst effiziente Abbildung für Warteschlangen in der DB2 gefunden werden. Die Abbildung, die sich als am geeignetsten erweist, soll dann in Vergleich gesetzt werden zu der nativen Implementierung in NATIX. Wie in Kapitel 5.1.4 ausführlich behandelt, existiert eine unbeschränkte Zahl 122 7.2 Quantitative Evaluation Evaluation möglicher Abbildungen von Warteschlangen auf ein relationales System. Aus diesem Grund können in diesem Experiment nicht alle Möglichkeiten erschöpfend untersucht werden, so dass nach der theoretischen Vorauswahl (vgl. die Übersicht in Kapitel 5.1.4.8) lediglich die Varianten 6 (vgl. Abschnitt 5.1.4.6) und 7 (vgl. Abschnitt 5.1.4.7) untersucht werden. 7.2.4.1 Unabhängige Variable Die unabhängige Variable in einem Expe- riment ist diejenige Variable, welche verändert wird, um die Auswirkungen der Veränderungen zu untersuchen [39]. Teilexperiment A: Die unabhängige Variable ist die jeweilig gewählte Art der Abbildung von Warteschlangen in der DB2. Es werden die Varianten 6 und 7 der Abschnitte 5.1.4.6 und 5.1.4.7 getestet. Teilexperiment B: Die unabhängige Variable ist der gewählte Nachrichtenspeicher, in dem die Warteschlangen verwaltet werden. Zwei Alternativen werden untersucht: 1. native Implementierung in NATIX oder 2. relationale Abbildung in der DB2. Für die Abbildung der Warteschlange in der DB2 wird diejenige gewählt, welche aus dem Teilexperiment A als die Effizienteste hervorgeht. 7.2.4.2 Abhängige Variablen Die abhängigen Variablen sind diejenigen Variablen, deren Veränderung in Abhängigkeit von der unabhängigen Variable interessiert [39]. Teilexperiment A und B: Die abhängige Variable ist das gemessene Leistungsverhalten. Es wird von dem Zeitpunkt des Sendens der ersten Nachricht bis 123 7.2 Quantitative Evaluation Evaluation zum Erhalt der Antwort-Nachricht gemessen. Außerdem werden durchschnittliche Loop-Zeiten gemessen (siehe Erläuterungen in Kapitel 7.2.7). Weder die Startnoch die Endphase des Demaq-Ausführungssystems wird in der Messung berücksichtigt. 7.2.4.3 Andere konstante Faktoren Die konstanten Faktoren des Expe- riments dürfen nicht verändert werden, um einen Einfluss auf das Ergebnis der Experimente ausschließen zu können [39]. Die folgenden Faktoren werden aus diesem Grund in allen Teil-Experimenten konstant gehalten: Das System: • OpenSUSE Linux 10.2 (Kernel release 2.6.22.5-31) • DualCore Processor (i686) • Hardware Platform i386 • NATIX • IBM DB2 Express-C v9.5 • 6 Festplatten: – SEAGATE ST373207LC (10K-RPM, ”/local“) – FUJITSU MAS3367NC (15K-RPM, ”/mnt/disk2“) – FUJITSU MAS3367NC (15K-RPM, ”/mnt/disk3“) – FUJITSU MAS3367NC (15K-RPM, ”/mnt/disk4“) – FUJITSU MAS3367NC (15K-RPM, ”/mnt/disk5“) – FUJITSU MAP3367NC (10K-RPM, ”/mnt/disk6“) 124 7.2 Quantitative Evaluation Evaluation Testanwendungen für die Experimente: Die Messung erfolgt mit vorab definierten Anwendungen, die ein breites Spektrum an Komplexitäten abdecken. Die Testanwendungen wurden in Kapitel 7.2.3 ausführlich vorgestellt. 7.2.4.4 Hypothesen Die in diesem Abschnitt formulierten Hypothesen spie- geln die theoretische Erwartung über den Ausgang der Experimente wider [39]. Gleichzeitig präzisieren die Hypothesen die Ziele der Experimente. Hypothese zum Teilexperiment A: Von den zu testenden Varianten ist die Implementierung der Warteschlangen in der DB2 innerhalb des DemaqSystems mit Variante 7 (vgl. Abschnitt 5.1.4.7) am effizientesten. Hypothese zum Teilexperiment B: Die Implementierung der Warteschlangen im Demaq-System ist in der DB2 weniger effizient als die native Warteschlangenimplementierung in NATIX. 7.2.4.5 Beschränkungen Eine Allgemeingültigkeit der Experimente kann nicht gewährleistet werden. Zu diesem Zweck müssten alle denkbaren DemaqAnwendungen getestet werden, deren Zahl unbegrenzt ist. Deshalb wird es Anwendungen geben, bei denen die Tests zu einem anderen Ergebnis führen. Da allerdings auf ein möglichst breites Anwendungsspektrum geachtet wurde, kann von einer angemessen hohen Allgemeingültigkeit ausgegangen werden. 7.2.5 Design des Experiments Regelauswertung Es wurden zwei Ziele für das Experiment Regelauswertung definiert (vgl. Kapitel 7.2.2.2). Zum einen soll überprüft werden, ob eine Regelauswertung mit der DB2 im Demaq-System möglich ist. Dies wird als gegeben angesehen, wenn das System mit der DB2 lauffähig ist und die Ergebnisse der Testanwendungen mit den Ergebnissen des aktuellen Systems übereinstimmen. Ist dies der Fall, soll 125 7.2 Quantitative Evaluation Evaluation zum anderen das Leistungsverhalten des Systems mit der DB2 in Bezug zu der bisherigen Implementierung mit NATIX als Nachrichtenspeicher und Saxon als Regelauswerter gesetzt werden. Da die in Unterkapitel 7.2.3 definierten Testanwendungen das Demaq-spezifische Funktionsspektrum variantenreich abdecken, kann eine ausreichende Allgemeingültigkeit angenommen werden. 7.2.5.1 Unabhängige Variable Die unabhängige Variable ist die gewählte System-Variante, entweder mit der DB2 als Nachrichtenspeicher und Regelauswerter oder mit NATIX als Nachrichtenspeicher und Saxon als Regelauswerter. 7.2.5.2 Abhängige Variablen In Abhängigkeit von der unabhängigen Va- riable wird das Leistungsverhalten des Gesamtsystems untersucht. 7.2.5.3 Andere konstante Faktoren Es wird dasselbe System benutzt, das bereits in Abschnitt 7.2.4.3 beschrieben wurde. Die verwendeten Testanwendungen wurden in Unterkapitel 7.2.3 definiert. 7.2.5.4 Hypothese Davon ausgehend, dass eine Umsetzung des Demaq- Systems mit der DB2 als Nachrichtenspeicher und Regelauswerter machbar ist, wird folgende Hypothese formuliert: Das Demaq-System ist mit NATIX und Saxon effizienter als mit der DB2. 7.2.6 Beschränkungen Auch für dieses Experiment kann eine Allgemeingültigkeit nicht gewährleistet werden. D.h. es existieren Anwendungen, bei denen die Tests zu einem anderen Resultat führen. Wie allerdings bereits zuvor erwähnt, wurde ein möglichst breites Anwendungsspektrum berücksichtigt, so dass von einer angemessen hohen Allgemeingültigkeit ausgegangen werden kann. 126 7.2 Quantitative Evaluation 7.2.7 Evaluation Vorbereitung der Experimente Die Vorbereitung der Experimente beinhaltete die Implementierung eines Logging-Mechanismus zur Speicherung der Messwerte. Hierzu wurde im ProcessingThread im Dispatcher zusätzlicher Code eingefügt, der die Messwerte über den Standard-Output-Stream ausgibt. Auf diese Weise konnten die Messdaten über die Konsole in eine Datei umgeleitet werden. Der Umfang der gemessenen Arbeitseinheit umfasst dabei einen Loop. Ein Loop wird definiert durch folgende Arbeitsschritte für eine neu eingereihte Nachricht in einer Warteschlange: 1. Hole alle definierten Regeln für die Warteschlange. 2. Führe alle Regeln auf der Nachricht aus. 3. Interpretiere alle Aktionen in dem QueryResult und führe diese aus. Der Start einer Testanwendung wurde mittels eines Testdrivers ermöglicht. Der Testdriver wurde in C++ geschrieben und ist dafür verantwortlich, dass für eine Testanwendung die notwendige Demaq-Instanz erzeugt und gestartet wird. Außerdem löst dieser die Verarbeitung innerhalb einer Testanwendung mit dem Senden einer Start-Nachricht aus. Innerhalb des Testdrivers wurde zusätzlich zu der bereits beschriebenen Messung der Loops die Messung der Gesamtlaufzeit einer Testanwendung implementiert. Die DQL-Dateien für die Testanwendungen wurden mit Hilfe von XSLStylesheets automatisch in den verschiedenen Varianten erzeugt (vgl. Varianten der Anwendungen in den Tabellen 6, 7 und 8). 7.2.8 Durchführung der Experimente Die Durchführung der Experimente wurde mit Hilfe von Shell -Skripten gesteuert und ausgeführt. Auf diese Weise konnten alle Testanwendungen automatisiert hintereinander gestartet werden. Zunächst wurden jedoch alle Warteschlangen 127 7.2 Quantitative Evaluation Evaluation mit jeweils 100.000 Nachrichten befüllt, um ein realistisches Anwendungsszenario zu schaffen. Ausgenommen hiervon war die Testanwendung ”Client/ServerSimulation mit qs:queue()“ (vgl. Abschnitt 7.2.3.2). Erste Tests hatten bei dieser ein außergewöhnlich schlechtes Leistungsverhalten offenbart, aufgrund dessen eine Verwendung dieser Testanwendung nur ohne das vorherige Befüllen möglich war. Die Experimente wurden mit allen Testanwendungen für folgende DemaqSystem-Varianten durchgeführt: 1. Demaq mit NATIX als Nachrichtenspeicher und Saxon zur Regelauswertung. 2. Demaq mit der DB2 als Nachrichtenspeicher und Saxon zur Regelauswertung. In der DB2 wurde die Warteschlangen-Abbildung in der Variante 6 (vgl. Kapitel 5.1.4.6) verwendet. 3. Demaq mit der DB2 als Nachrichtenspeicher und Saxon zur Regelauswertung. In der DB2 wurde die Warteschlangen-Abbildung in der Variante 7 (vgl. Kapitel 5.1.4.7) verwendet. 4. Demaq mit der DB2 als Nachrichtenspeicher und zur Regelauswertung. Die Regelauswertung wurde mit Hilfe von automatisch erzeugten Stored Procedures (vgl. Kapitel 6.2.2.1) umgesetzt. Bei allen Tests mit der DB2 wurde die native Unterstützung von Slices, wie sie in Kapitel 5.1.5.3 beschrieben wurde, verwendet. 7.2.9 Analyse der Ergebnisse In diesem Kapitel werden die Ergebnisse der Experimente mit den Testanwendungen aus Kapitel 7.2.3 evaluiert. Die Ergebnisse werden für das Experiment Warteschlange (Abschnitt 7.2.9.1) und das Experiment Regelauswertung (Abschnitt 7.2.9.2) getrennt betrachtet. 128 7.2 Quantitative Evaluation 7.2.9.1 Evaluation Ergebnisse des Experiments Warteschlange In diesem Ab- schnitt werden zunächst die Ergebnisse für die untersuchten Abbildungen der Warteschlangen evaluiert (Teilexperiment A). Anschließend wird die effizienteste Abbildung mit der nativen Warteschlangenimplementierung in NATIX verglichen (Teilexperiment B). Teilexperiment A Im Durchschnitt aller Testergebnisse hat Variante 7 (vgl. Abschnitt 5.1.4.7) die Testanwendungen um 4,3% schneller bewältigt als Variante 6 (vgl. Abschnitt 5.1.4.6). Werden allerdings die Ergebnisse der Anwendungen mit kleinen XML-Nachrichten (Varianten A1, A2, A3) isoliert betrachtet, so ist Variante 6 im Schnitt 2% schneller als Variante 7. Während bei den eher einfachen Anwendungen der beiden Client/ServerSimulationen Variante 7 deutlich überlegen ist (9,1 bzw. 8,5% schneller), zeigt sich Variante 6 bei der Verwendung von Slices effizienter (2,3% schneller). Die Testergebnisse des Teilexperiments A sind in der Tabelle 9 auf Seite 131 sowie in Tabelle 10 auf Seite 132 detailliert aufgelistet. Teilexperiment B Die Testergebnisse von Teilexperiment B zeigen, dass das Demaq-System, wenn es Saxon zur Regelauswertung verwendet, mit NATIX im Schnitt 614,35% schneller ist als mit der DB2 als Nachrichtenspeicher. Interessant ist, dass NATIX bei den C-Varianten mit großen Nachrichten (100Kb) nur 112,07% effizienter ist als die DB2. Bei den C-Varianten der Testanwendung ”Client/Server-Simulation mit qs:queue()“ ist die DB2 sogar schneller (13,25%). Die detaillierten Ergebnisse des Teilexperiments B werden in der Tabelle 11 auf Seite 133 und in Tabelle 12 auf Seite 134 detailliert dargestellt. 7.2.9.2 Ergebnisse des Experiments Regelauswertung Das Experiment Regelauswertung hat sehr gemischte Ergebnisse geliefert. Demnach ist die Regelauswertung mit NATIX und Saxon insgesamt im Schnitt 76,67% effizienter 129 7.2 Quantitative Evaluation Evaluation bei den Testanwendungen. Bei genauerer Betrachtung ist die Regelauswertung mit der DB2 bei den Anwendungen ”Client/Server-Simulation mit qs:queue()“ und ”Prozess-Simulation Split/Join“ um 32,13% schneller, während NATIX und Saxon bei den Anwendungen ”Client/Server-Simulation“ und ”Prozesskette mit Überkreuzung“ im Schnitt um 185,46% effizienter ist. Zu beachten bleibt in jedem Fall, dass das System mit der DB2 im Multithreading-Modus verwendet wurde. Die detaillierten Ergebnisse des Experiments Regelauswertung werden in Tabelle 13 auf Seite 135 und in Tabelle 14 auf Seite 136 vorgestellt. 7.2.10 Zusammenfassung der Ergebnisse Für eine schnellstmögliche Abarbeitung der Elemente einer Warteschlange, die in der DB2 implementiert ist, eignet sich von den untersuchten Abbildungen Variante 7 (vgl. Abschnitt 5.1.4.7) am besten. Das Ergebnis ist mit 4,3% allerdings nicht deutlich und diese Variante unterliegt in bestimmten Anwendungen der Variante 6 (vgl. Abschnitt 5.1.4.6). Insgesamt konnte damit jedoch die Hypothese aus Kapitel 7.2.4.4 für Teilexperiment A bestätigt werden. Im Vergleich zu NATIX ist die DB2 in der bisherigen Form als Nachrichtenspeicher unterlegen, wenn zur Regelauswertung Saxon verwendet wird. Im Schnitt ist NATIX hierbei um 614,35% effizienter. Damit ist erwartungsgemäß auch die Hypothese für Teilexperiment B (vgl. Abschnitt 7.2.4.4) bestätigt worden. Das Ergebnis des Experiments Regelauswertung ist nicht eindeutig. Bei einem Teil der Anwendungen zeigte sich die DB2 effizienter (32,13%), bei der anderen Hälfte der Anwendungen waren NATIX und Saxon jedoch deutlich überlegen (185,46%). Damit ist das System mit NATIX und Saxon insgesamt im Schnitt 76,67% schneller als die Regelauswertung mit der DB2. Allerdings kann die Hypothese für das Experiment Regelauswertung (vgl. Abschnitt 7.2.5.4) nicht eindeutig bestätigt werden und muss differenziert betrachtet werden. 130 7.2 Quantitative Evaluation Evaluation Tabelle 9: Testergebnisse Teilexperiment A: Erster Teil 131 7.2 Quantitative Evaluation Evaluation Tabelle 10: Testergebnisse Teilexperiment A: Zweiter Teil 132 7.2 Quantitative Evaluation Evaluation Tabelle 11: Testergebnisse Teilexperiment B: Erster Teil 133 7.2 Quantitative Evaluation Evaluation Tabelle 12: Testergebnisse Teilexperiment B: Zweiter Teil 134 7.2 Quantitative Evaluation Evaluation Tabelle 13: Testergebnisse Experiment Regelauswertung: Erster Teil 135 7.2 Quantitative Evaluation Evaluation Tabelle 14: Testergebnisse Experiment Regelauswertung: Zweiter Teil 136 Zusammenfassung und Ausblick 8 Zusammenfassung und Ausblick In diesem Kapitel werden die zuvor erarbeiteten Ergebnisse zusammengefasst (Abschnitt 8.1). Außerdem wird ein Ausblick auf zukünftige Untersuchungen und Weiterentwicklungsmöglichkeiten des Demaq-Systems gegeben (Abschnitt 8.2). 8.1 Zusammenfassung Im Rahmen dieser Diplomarbeit wurde am Beispiel der DB2 gezeigt, wie ein relationales DBMS in das Demaq-Ausführungssystem integriert werden kann. Als Resultat kann Demaq nun flexibler eingesetzt werden. Die im Verlauf der vorliegenden Diplomarbeit erarbeiteten Ergebnisse sollen im Folgenden kurz zusammenfassend dargestellt werden. In Kapitel 3 wurden zunächst die Anforderungen für das zu entwickelnde System analysiert. Als besonders wichtig wurde die korrekte Funktionsweise des implementierten Systems herausgestellt. Ebenso stand die Modularisierung im Mittelpunkt, um das System für zukünftige Untersuchungen flexibel und anpassungsfähig zu gestalten. Schließlich sollte das Leistungsverhalten optimiert werden, sobald die generelle Machbarkeit feststand. Anschließend folgte in Kapitel 4 eine grob konzeptuelle Vorstellung der Architekturen der zu entwickelnden System-Varianten. Insgesamt wurden drei SystemVarianten präsentiert. Zunächst wurde das aktuelle System, das NATIX als Nachrichtenspeicher und Saxon zur Regelauswertung verwendet, schematisch aufbereitet. Als zweite Variante wurde ein System mit der DB2 als Nachrichtenspeicher und Saxon als Regelauswerter vorgestellt, in dem Teile von NATIX weiterverwendet werden. Schließlich folgte die dritte Variante, in welcher das Demaq-System mit der DB2 als Nachrichtenspeicher und zur Regelauswertung konzipiert wurde. Die Schwierigkeit bei der Architektur war es, eine Modularisierung umzusetzen, bei der verschiedenste Schnittstellen miteinander in Einklang gebracht werden mussten. 137 8.1 Zusammenfassung Zusammenfassung und Ausblick Darauf aufbauend fand in Kapitel 5 eine detaillierte Verfeinerung des Designs auf logischer Ebene statt. Wichtig waren in diesem Abschnitt die Abbildungen der Warteschlangen und Slices auf das relationale Modell. Dementsprechend folgte die Vorstellung und Diskussion diverser möglicher Abbildungen. Für die Regelauswertung mit der DB2 wurden in diesem Abschnitt zudem die Grundlagen gelegt. Hierzu wurden für die Demaq-spezifischen Funktionen Rewrites definiert, welche die Funktionen in SQL-Statements überführen. In Kapitel 6 stand daraufhin die Implementation im Mittelpunkt, wobei eine Optimierung auf physischer Ebene verfolgt wurde. Für die DB2 als Nachrichtenspeicher wurde eine Optimierung der Datenseiten und eine Parallelisierung der Speicherverwaltung vorgeschlagen. Die Regelauswertung mit der DB2 konnte durch einen Mechanismus verbessert werden, der interne enqueue Operationen direkt in der Datenbank ausführt, ohne die Nachrichten an den Demaq-Kern zurückzuliefern. Außerdem wurde eine Ausführung der Regeln mit Hilfe von Stored Procedures vorgeschlagen. In Kapitel 7.1 wurden die implementierten Systemvarianten qualitativ auf Grundlage der Anforderungen evaluiert. Den Schluss bildete eine quantitative Evaluation der implementierten System-Komponenten mittels breit angelegter Experimente mit Testanwendungen. Dabei zeigte sich, dass das Demaq-System mit NATIX und Saxon insgesamt deutlich effizienter ist als das System mit der DB2 als Nachrichtenspeicher und Saxon als Regelauswerter (im Durchschnitt 614,35%). Im Vergleich zu dem System, das die DB2 als Nachrichtenspeicher und zur Regelauswertung verwendet, ist die ursprüngliche Demaq-Variante im Schnitt ebenfalls effizienter (76,67%). Hierbei sind die Ergebnisse allerdings nicht eindeutig, weshalb dieses Resultat differenziert zu betrachten ist. 138 8.2 Ausblick 8.2 Zusammenfassung und Ausblick Ausblick In diesem Kapitel wird ein Ausblick gegeben, wie das im Rahmen dieser Diplomarbeit entwickelte System kurz- bis mittelfristig verbessert werden kann. 8.2.1 Konvertierungen vermeiden In dem in der vorliegenden Diplomarbeit implementierten System sind die Schnittstellen nicht optimal implementiert, da häufig Konvertierungen zwischen verschiedenen Datentypen vorgenommen werden. Sofern eine Vereinheitlichung möglich ist, können diese Konvertierungen vermieden werden und so Leistungssteigerungen erzielt werden. 8.2.2 Auf Properties und Slicekeys beliebiger Nachrichten zugreifen Wie sich bei den Tests zur Überprüfung der Korrektheit in Kapitel 7.1.1 gezeigt hat, kann im System mit der DB2 als Nachrichtenspeicher und Regelauswerter derzeit nur auf Properties und Slicekeys der aktuellen Kontextnachricht zugegriffen werden. Im System mit NATIX bzw. Saxon wurde dies mit Hilfe von Processing-Instructions gelöst, welche die Nachrichten-ID enthalten. Dieser Mechanismus konnte aus zeitlichen Gründen nicht implementiert werden. 8.2.3 Nebenläufigkeit Die Experimente mithilfe der Testanwendungen mit der DB2 als Regelauswerter bei der Verwendung mehrerer Threads verliefen nicht ohne Komplikationen. Im Besonderen hat sich die Verwendung von Slices als problematisch herausgestellt. So kommt es bei der Verarbeitung häufig zu Deadlocks. Wie die Deadlocks genau zustande kommen und ob sie eventuell vermieden werden können, muss noch untersucht werden. Zudem werden Deadlocks von der DB2 automatisch aufgelöst, indem eine oder mehrere der beteiligten Transaktionen zurückgesetzt werden. Das Demaq-System 139 8.2 Ausblick Zusammenfassung und Ausblick bekommt hierüber keinen Bescheid und kann die Anwendung in diesem Fall nicht ordnungsgemäß ausführen. Demnach muss die nebenläufige Verarbeitung noch verbessert werden. 8.2.4 Untersuchung der Slicing-Abbildungen In Kapitel 5.1.5 wurden diverse Varianten der Abbildung von Slices auf das relationale Modell vorgeschlagen. Diese sollten auf ihre Effizienz hin untersucht werden. 8.2.5 Parallelisierung der Aktionen Die Abarbeitung der Aktionen eines QueryResults wird derzeit seriell im Processing Thread durchgeführt. Wie die Abarbeitung parallelisiert werden kann, ist ein Thema für zukünftige Untersuchungen. 8.2.6 Abgleich der Verbindungen der DB2-Fassade mit den Processing-Threads In dem implementierten System wird in der DB2-Fassade in der Datei include/settings.hh die Anzahl der zu erzeugenden Verbindungen zur DB2 für den ConnectionPool festgelegt. Im Demaq-Kern wird die Anzahl der ProcessingThreads deklariert, die somit unabhängig von den Verbindungen gesteuert werden. Dies sollte vereinheitlicht werden, da jeder ProcessingThread immer genau zwei Verbindungen gleichzeitig verwendet, so dass in Abhängigkeit von der Anzahl der gestarteten ProcessingThreads die Anzahl der Verbindungen zur DB2 determiniert werden kann. 8.2.7 Nachrichten-Validierung Die Validierung von XML-Dokumenten in der DB2 könnte zu einem besseren Leistungsverhalten bei Parsing-Vorgängen führen. Eine Queue-abhängige Vali- 140 8.2 Ausblick Zusammenfassung und Ausblick dierung von Nachrichten könnte zukünftig mittels XML-Schemata in der DB2 implementiert werden. Die Möglichkeiten zur Steigerung des Leistungsverhaltens sind dementsprechend zu untersuchen. 8.2.8 Rewrites für die DB2 In dem implementierten System werden die Rewrites für die DB2 als Regelauswerter in der Transformation-Klasse in den Dateien xqlparser/transformation.hh und -.cc umgesetzt. Dies ist nicht optimal, da die Rewrites auf diese Weise nicht bei der AST-Generierung berücksichtigt und geprüft werden. Außerdem wird die Steuerung derzeit über eine Makrovariable gesteuert und nicht über den Rewrite-Mechanismus, der zu diesem Zweck in der Traversal-Klasse in Demaq implementiert wurde. 141 LITERATUR LITERATUR Literatur [1] Rav Ahuja. Introducing db2 9, part 4: Autonomic and other en- hancements in db2 9. Technical report, IBM, Jun 2006. Retrie- ved on 14.07.2008 http://www.ibm.com/developerworks/db2/library/ techarticle/dm-0606ahuja2. [2] Kent Beck, Mike Beedle, Arie van Bennekum, Alistair Cockburn, Ward Cunningham, Martin Fowler, James Grenning, Jim Highsmith, Andrew Hunt, Ron Jeffries, Jon Kern, Brian Marick, Robert C. Martin, Steve Mellor, Ken Schwaber, Jeff Sutherland, and Dave Thomas. Principles of agile software. http://www.agilemanifesto.org/principles.html, 2001. Retrieved on 17.07.2008 http://www.agilemanifesto.org/principles.html. [3] Andreas Behm, Serge Rielau, and Richard Swagerman. Returning modified rows - select statements with side effects. In VLDB ’04: Proceedings of the Thirtieth international conference on Very large data bases, pages 987–997. VLDB Endowment, 2004. [4] Anjul Bhambhri. Firing up the hybrid engine. IBM Database Magazine, 3, Jul 2005. [5] Scott Boag, Don Chamberlin, Mary F. Fernandez, Daniela Florescu, Jonathan Robie, and Jerome Simeon. Xquery 1.0: An xml query language, Jan 2007. Retrieved on 23.04.2008 http://www.w3.org/TR/2007/ REC-xquery-20070123/. [6] A. Böhm, C-C. Kanne, and G. Moerkotte. Demaq: A foundation for declarative xml message processing. In Proc. 3. Biennial Conference on Innovative Data Systems Research (CIDR), 2007. [7] Donald D. Chamberlin and Raymond F. Boyce. Sequel: A structured english query language. In FIDET ’74: Proceedings of the 1974 ACM SIGFIDET 142 LITERATUR LITERATUR (now SIGMOD) workshop on Data description, access and control, pages 249–264, New York, NY, USA, 1974. ACM Press. [8] Whei-Jen Chen, John Chun, Naomi Ngan, Rakesh Ranjan, and Manoj K. Sardana. Db2 express-c: The developer handbook for xml, php, c/c++, java, and .net. Technical report, IBM Redbooks, Sep 2006. Retrie- ved on 14.04.2008 http://www.redbooks.ibm.com/redpieces/abstracts/ SG247301.html. [9] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. McGraw-Hill Science/Engineering/Math, Jul 2001. [10] Mary F. Fernandez, Ashok Malhotra, Jonathan Marsh, Marton Nagy, and Norman Walsh. Jan 2007. Xquery 1.0 and xpath 2.0 data model (xdm), Retrieved on 24.04.2008 http://www.w3.org/TR/2007/ REC-xpath-datamodel-20070123/. [11] Thorsten Fiebig, Sven Helmer, Carl-Christian Kanne, Guido Moerkotte, Julia Neumann, Robert Schiele, and Till Westmann. Anatomy of a native xml base management system. VLDB Journal, 11(4):292–314, 2002. [12] Colleen Graham, Dan Sommer, and Bhavish Sood. Market share: Relational database management systems by operating system, worldwide, 2006. Gartner Dataquest, Jun 2007. [13] IBM. DB2 Information Center - Advantages of DB2 CLI over embedded SQL, Mar 2006. Retrieved on 10.05.2008 http://publib.boulder.ibm. com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/ ad/c0005890.htm. [14] IBM. lationalen DB2 Information Center - Tipps zur Planung von reIndizes, Oct 2006. Retrieved 143 on 12.06.2008 http: LITERATUR LITERATUR //publib.boulder.ibm.com/infocenter/db2luw/v9/topic/com.ibm. db2.udb.admin.doc/doc/c0005054.htm. [15] IBM. DB2 Information Center - Comparison of DB2 CLI and Microsoft ODBC, Mar 2008. Retrieved on 12.05.2008 http: //publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com. ibm.db2.luw.apdv.cli.doc/doc/c0000670.html. [16] IBM. DB2 Information Center - CREATE FUNCTION (SQL Sca- lar, Table, or Row) statement, Aug 2008. Retrieved on 07.08.2008 http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/ com.ibm.db2.luw.sql.ref.doc/doc/r0003493.html. [17] IBM. DB2 Information Center - Create Index Statement, Mar 2008. Retrieved on 12.06.2008 http://publib.boulder.ibm.com/infocenter/ db2luw/v9r5/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/ r0000919.html. [18] IBM. DB2 Information Center - Create Table Statement, Mar 2008. Retrieved on 10.06.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html. [19] IBM. DB2 Information Center - Datenbanken mit dynamischem Speicher, Mar 2008. Retrieved on 10.08.2008 http://publib.boulder.ibm.com/ infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.dbobj.doc/ doc/c0012278.html. [20] IBM. DB2 Information Center - Declaring global temporary tables, Mar 2008. Retrieved on 13.06.2008 http://publib.boulder.ibm.com/ infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.dbobj.doc/ doc/t0020127.html. 144 LITERATUR LITERATUR [21] IBM. DB2 Information Center - Einschränkungen bei pureXML, Mar 2008. Retrieved on 21.05.2008 http://publib.boulder.ibm.com/infocenter/ db2luw/v9r5/topic/com.ibm.db2.luw.xml.doc/doc/r0022679.html. [22] IBM. DB2 Information Center - Funktion ’sqlquery’, Mar 2008. Retrieved on 13.05.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/topic/com.ibm.db2.luw.xml.doc/doc/xqrfnsqq.html. [23] IBM. DB2 Information Center - Select-statement, Mar 2008. Retrie- ved on 05.08.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000879.html. [24] IBM. DB2 Information Center - SQL Nachrichten: SQL0751N, Mar 2008. Retrieved on 23.08.2008 http://publib.boulder.ibm.com/ infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.messages.sql.doc/ doc/msql00751n.html. [25] IBM. DB2 Information Center - SQL Nachrichten: SQL1157N, Mar 2008. Retrieved on 23.08.2008 http://publib.boulder.ibm.com/ infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.messages.sql.doc/ doc/msql01157n.html. [26] IBM. DB2 Information Center - Transaction Processing, Mar 2008. Retrieved on 28.08.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/topic/com.ibm.db2.luw.apdv.cli.doc/doc/c0008003.html. [27] IBM. DB2 Information Center - XML-Schemarepository, Mar 2008. Retrieved on 25.08.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/index.jsp?topic=/com.ibm.db2.luw.xml.doc/doc/c0022720. html. [28] IBM. DB2 Information Center - XQuery Prolog, Mar 2008. 145 Retrie- LITERATUR LITERATUR ved on 13.05.2008 http://publib.boulder.ibm.com/infocenter/db2luw/ v9r5/topic/com.ibm.db2.luw.xml.doc/doc/xqrprologs.html. [29] IBM. DB2 Version 9.1 for z/OS - SQL Reference, Feb 2008. Retrieved on 13.07.2008 http://publib.boulder.ibm.com/infocenter/dzichelp/ v2r2/topic/com.ibm.db29.doc.sqlref/dsnsqk13.pdf?noframes=true. [30] Michael H. Kay. Saxonica - xslt and xquery processing. Retrieved on 13.07.2008 http://www.saxonica.com/introducing.html. [31] Alfons Kemper and André Eickler. Datenbanksysteme - Eine Einführung, 6. Auflage. Oldenbourg, 2006. [32] Sergei Kuchin. Oracle, http://otl.sourceforge.net, Jun odbc 2008. and db2-cli template Retrieved on library. 10.04.2008 http://otl.sourceforge.net. [33] Sergei Kuchin. Oracle, odbc and db2-cli template library documentation – otl connect class. http://otl.sourceforge.net/otl3 connect class.htm, Apr 2008. Retrieved on 10.04.2008 http://otl.sourceforge.net. [34] Alexander Kuznetsov. Essential facts about index covering in db2 universal database. Technical report, IBM, Chicago, IL, USA, Mar 2003. Retrieved on 23.07.2008 http://www.ibm.com/developerworks/db2/library/ techarticle/0303kuznetsov/0303kuznetsov.html. [35] Roger Miller. Large objects get bigger. IBM Database Magazine, 3, Jul 2005. [36] Matthias Nicola. 15 best practices for purxml. Technical report, IBM, Oct 2006. Retrieved on 27.07.2008 http://www.ibm.com/developerworks/db2/ library/techarticle/dm-0610nicola. [37] Chris Okasaki. Simple and efficient purely functional queues and deques. Journal of Functional Programming, 5(4):583–592, 1995. 146 LITERATUR LITERATUR [38] Rex Oliva. Use xml in db2 sql stored procedures. Technical report, IBM, Jan 2007. Retrieved on 14.08.2008 http://www.ibm.com/developerworks/ db2/library/techarticle/dm-0701oliva/index.html. [39] Shari Lawrence Pfleeger. Experimental design and analysis in software engineering. Annals of Software Engineering, 1(1):219–253, 1995. [40] Axel Pols, Klaus Fuest, and Christian Krys. Zukunft digitale wirtschaft. Studie, BITKOM Bundesverband Informationswirtschaft, Telekommunikation und neue Medien e.V., Berlin, Germany, 2007. [41] Aamer Sachedina, Matt Huras, and Kelly Schlamb. Db2 9: Simplify database management with automatic storage, Nov 2006. DB2 Chat with the Lab Retrieved on 23.07.2008 ftp://ftp.software.ibm.com/software/data/db2/ 9/labchats/20061114-slides.pdf. [42] Douglas C. Schmidt. Wrapper facade: a structural pattern for encapsulated functions within classes. C++ Rep., 11(2):40–50, 1999. [43] Werner Schuetz. Lock avoidance in db2 udb v8. Technical report, IBM, Sep 2005. Retrieved on 23.06.2008 http://www-128.ibm.com/developerworks/ db2/library/techarticle/dm-0509schuetz. [44] Sun Microsystems, Inc., Santa Clara, CA, USA. Multithreaded Programming Guide, May 2002. Retrieved on 16.05.2008 http://docs.sun.com/ app/docs/doc/802-1949/802-1949. [45] Universität Mannheim - Database Research Group. Natix Manual. Retrieved on 16.08.2008 http://db.informatik.uni-mannheim.de/natixdoc/. [46] Universität Mannheim - Database Research Group. A brief introduction to the Demaq system, Mar 2008. 147 LITERATUR [47] Paul Yip. LITERATUR Advanced sql scripting pl. Technical report, IBM, Mar 2002. Retrieved on 13.06.2008 http://www.ibm.com/developerworks/db2/ library/techarticle/0203yip/0203yip.html. 148 Mannheim, den 17. Oktober 2008 Ich, Dennis Knochenwefel (Student der Wirtschaftsinformatik an der Universität Mannheim, Matrikelnummer 0947788), versichere an Eides statt, dass ich die vorliegende Diplomarbeit selbstständig verfasst und keine anderen als die angegebenen Hilfsmittel verwendet habe. Die Arbeit wurde in dieser oder ähnlicher Form noch keiner Prüfungskommission vorgelegt. Dennis Knochenwefel 149 Anhang A Anhang A.1 Quellcodes der Tests In dieser Diplomarbeit wurden Testfälle zu verschiedenen Zwecken definiert. In Abschnitt A.1.1 werden die Testfälle aufgezeigt, die während der Entwicklungsphase zur sukzessiven Vervollständigung der Funktionalität und Überprüfung der Korrekheit verwendet wurden (vgl. Kapitel 7.1). In Abschnitt A.1.2 werden die Quelltexte der Testanwendungen der Experimente aufgeführt (vgl. Kapitel 7.2.3). A.1.1 Testfälle Entwicklungsphase / Korrektheitsüberprüfung Alle im Folgenden aufgeführten Testanwendungen sind vollständige, gültige Demaq-Anwendungen, auch wenn es für diese keine tatsächlichen Anwendungsszenarien gibt. Die an Komplexität zunehmenden Anwendungen wurden in der angegebenen Reihenfolge zur Überprüfung der Korrektheit der im Rahmen dieser Diplomarbeit entwickelten System-Varianten verwendet. A.1.1.1 demaqTestcase1.dql c r e a t e queue i n d e f a u l t 2 kind b a s i c mode p e r s i s t e n t ; A.1.1.2 demaqTestcase2.dql 1 c r e a t e queue i n d e f a u l t kind incoming 3 i n t e r f a c e ”h t t p : / / l o c a l h o s t ” p o r t ”8080 ” 5 mode p e r s i s t e n t ; 150 A.1 Quellcodes der Tests A.1.1.3 Anhang demaqTestcase3.dql 1 import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” a t ”/ l o c a l / dknochen /demaq/ s r c / xquery / d e m a q l i b r a r y . x q l ” ; 3 c r e a t e queue i n d e f a u l t 5 kind incoming i n t e r f a c e ”h t t p : / / l o c a l h o s t ” 7 p o r t ”8080 ” response outdefault 9 mode p e r s i s t e n t ; 11 c r e a t e r u l e s i m p l e a n s w e r f o r i n d e f a u l t enqueue message . i n t o o u t d e f a u l t ; A.1.1.4 demaqTestcase4.dql import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” 2 a t ”/ l o c a l / dknochen /demaq/ s r c / xquery / d e m a q l i b r a r y . x q l ” ; 4 c r e a t e queue i n d e f a u l t kind incoming 6 i n t e r f a c e ”h t t p : / / l o c a l h o s t ” p o r t ”8080 ” 8 response outdefault mode p e r s i s t e n t ; 10 c r e a t e r u l e simpleanswer for i n d e f a u l t 12 l e t $msgcount := count ( qs : queue ( ) ) return enqueue message 14 <r e s p o n s e > <queue>i n d e f a u l t </queue> 16 <msgcount >{$msgcount}</msgcount> 151 A.1 Quellcodes der Tests Anhang </r e s p o n s e > i n t o o u t d e f a u l t ; A.1.1.5 demaqTestcase5.dql 1 import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” a t ”/ l o c a l / dknochen /demaq/ s r c / xquery / d e m a q l i b r a r y . x q l ” ; 3 (:∗∗ 5 ∗ This s i m p l e example i s used t o t e s t t h e i m p l e m e n t a t i o n ∗ o f t h e demaq s p e c i f i c f u n c t i o n s : 7 ∗ ∗ qs : queue ( ) 9 ∗ qs : queue ( qname ) ∗ qs : message ( ) 11 ∗ qs : p r o p e r t y ( pname ) ∗ qs : p r o p e r t y ( qs : m e s s a g e i d p r o p e r t y ) 13 ∗ qs : p r o p e r t y ( qs : m e s s a g e q u e u e s t a t u s p r o p e r t y , message ) ∗ qs : s l i c e ( s l i c e k e y , s l i c e n a m e ) 15 ∗ qs : s l i c e k e y ( name ) ∗:) 17 c r e a t e queue i n d e f a u l t 19 kind incoming i n t e r f a c e ”h t t p : / / l o c a l h o s t ” 21 p o r t ”8080 ” response outdefault 23 mode p e r s i s t e n t ; 25 c r e a t e queue l o g g e r kind b a s i c 27 mode p e r s i s t e n t ; 29 c r e a t e p r o p e r t y now 152 A.1 Quellcodes der Tests Anhang queue i n d e f a u l t 31 v a l u e //Now/ t e x t ( ) ; 33 c r e a t e s l i c i n g p r o p e r t y sametime queue i n d e f a u l t , l o g g e r 35 v a l u e //Now/ t e x t ( ) ; 37 c r e a t e r u l e l o g f o r i n d e f a u l t enqueue message qs : message ( ) i n t o l o g g e r ; 39 c r e a t e r u l e simpleanswer for i n d e f a u l t 41 l e t $msgcount1 := count ( qs : queue ( ) ) l e t $msgcount2 := count ( qs : queue ( ” o u t d e f a u l t ”) ) 43 l e t $ s l i c e c o u n t := count ( qs : s l i c e ( qs : message ( ) //Now/ t e x t ( ) , ”sametime ”) ) 45 l e t $ l a s t s l i c e m e s s a g e := qs : s l i c e ( qs : message ( ) //Now/ t e x t ( ) , ”sametime ”) [ $ s l i c e c o u n t ] 47 return enqueue message <r e s p o n s e > 49 <queue> indefault 51 </queue> <msgcount f u n c t i o n=”qs : queue ( ) ”> 53 { $msgcount1 } </msgcount> 55 <msgcount f u n c t i o n=”qs : queue ( o u t d e f a u l t ) ”> { $msgcount2 } 57 </msgcount> <p r o p e r t y f u n c t i o n=”qs : p r o p e r t y ( now ) ”> 59 { qs : p r o p e r t y ( ”now ”) } </p r o p e r t y > 61 <c o n t e x t I t e m f u n c t i o n=”qs : message ( ) ”> { qs : message ( ) } 63 </c o n t e x t I t e m > 153 A.1 Quellcodes der Tests Anhang <s l i c e m s g c o u n t f u n c t i o n=”qs : s l i c e ( . / / Now/ t e x t ( ) , sametime ) ”> { $slicecount } 65 </ s l i c e m s g c o u n t > 67 < s l i c e k e y f u n c t i o n=”qs : s l i c e k e y ( sametime ) ”> { qs : s l i c e k e y ( ”sametime ”) } 69 </ s l i c e k e y > <msgid f u n c t i o n=”qs : p r o p e r t y ( qs : m e s s a g e i d p r o p e r t y ) ”> { qs : p r o p e r t y ( ”qs : m e s s a g e i d p r o p e r t y ”) } 71 </msgid> 73 <m s g s t a t e f u n c t i o n= ”qs : p r o p e r t y ( $ l a s t s l i c e m e s s a g e , 75 qs : m e s s a g e q u e u e s t a t u s p r o p e r t y ) ”> { qs : p r o p e r t y ( $ l a s t s l i c e m e s s a g e , ”qs : m e s s a g e q u e u e s t a t u s p r o p e r t y ”) } 77 </msgstate > 79 </r e s p o n s e > i n t o o u t d e f a u l t ; A.1.2 Testanwendungen Experimente Die Testanwendungen werden jeweils in der Variante A1 gezeigt (vgl. hierzu das Kapitel 7.2.3). A.1.2.1 test1ClientServer.dql 1 import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” a t ”/home/ dknochen / demaq orig / s r c / xquery / d e m a q l i b r a r y . x q l ” ; 3 (:∗∗ 5 ∗ s t a r t queue ∗:) 7 c r e a t e queue incoming kind incoming 9 i n t e r f a c e ”h t t p : / / l o c a l h o s t ” 154 A.1 Quellcodes der Tests Anhang p o r t ”8080 ” 11 response incoming response mode p e r s i s t e n t ; 13 (:∗∗ 15 ∗ the re po r t that w i l l stop the a p p l i c a t i o n ∗:) 17 c r e a t e queue r e p o r t kind b a s i c 19 mode p e r s i s t e n t ; 21 ( : ∗ ∗ ∗ the s e r v e r 23 ∗:) c r e a t e queue s e r v e r 25 kind b a s i c mode p e r s i s t e n t ; 27 (:∗∗ 29 ∗ a l l other c l i e n t s ∗:) 31 c r e a t e queue c l i e n t 1 kind b a s i c 33 mode p e r s i s t e n t ; 35 c r e a t e queue c l i e n t 2 kind b a s i c 37 mode p e r s i s t e n t ; 39 c r e a t e queue c l i e n t 3 kind b a s i c 41 mode p e r s i s t e n t ; 43 c r e a t e queue c l i e n t 4 155 A.1 Quellcodes der Tests Anhang kind b a s i c 45 mode p e r s i s t e n t ; 47 ( : ∗ ∗ ∗ enqueue s t a r t message 49 ∗:) c r e a t e r u l e s t a r t u p f o r incoming 51 l e t $msg := . return enqueue message 53 <r o o t kind=” s t a r t u p ”> <body> {$msg/ c h i l d : ∗ } 55 </body> 57 </r o o t > i n t o s e r v e r ; 59 ( : ∗ ∗ ∗ enqueue r e s p o n s e message 61 ∗:) c r e a t e r u l e stop for r e p o r t 63 l e t $msg := . return 65 l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d return 67 i f ( ( count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =4) and ( count ( qs : queue ( ’ i n c o m i n g r e s p o n s e ’ ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =0) ) 69 then enqueue message <r o o t kind=” s t o p ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 71 <msgs> { count ( qs : queue ( ) ) } 73 </msgs> <s e s s i o n m s g s > 75 { count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) } </s e s s i o n m s g s > 156 A.1 Quellcodes der Tests 77 Anhang </r o o t > i n t o i n c o m i n g r e s p o n s e else () ; 79 81 ( : ∗ ∗ ∗ server 83 ∗:) c r e a t e r u l e masterping for s e r v e r 85 l e t $msg := qs : message ( ) return i f ( $msg// r o o t / @kind=”s t a r t u p ”) 87 then l e t $ s e s s i o n i d := count ( qs : queue ( ’ r e p o r t ’ ) ) 89 return ( : p i n g i n i t i a l message t o a l l o t h e r s : ) 91 ( enqueue message < c l i e n t 1 msgcount=”1 ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 93 {$msg// r o o t / body } 95 </ c l i e n t 1 > i n t o c l i e n t 1 , enqueue message < c l i e n t 2 msgcount=”1 ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 97 {$msg// r o o t / body } 99 </ c l i e n t 2 > i n t o c l i e n t 2 , enqueue message < c l i e n t 3 msgcount=”1 ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 101 {$msg// r o o t / body } 103 </ c l i e n t 3 > i n t o c l i e n t 3 , enqueue message < c l i e n t 4 msgcount=”1 ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 105 {$msg// r o o t / body } 107 </ c l i e n t 4 > i n t o c l i e n t 4 ) 109 else ( : i n c r e a s e msgcount by 1 . then 157 A.1 Quellcodes der Tests 111 Anhang check where t h e pong came from and p i n g i t back : ) 113 l e t $msgcount := f n : number ( $msg// @msgcount )+1 l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 115 return i f ( $msg/ c l i e n t 1 ) 117 then enqueue message < c l i e n t 1 msgcount=”{ $msgcount } ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// body } 119 </ c l i e n t 1 > i n t o c l i e n t 1 121 e l s e i f ( $msg/ c l i e n t 2 ) then enqueue message < c l i e n t 2 msgcount=”{ $msgcount } ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 123 {$msg// body } 125 </ c l i e n t 2 > i n t o c l i e n t 2 e l s e i f ( $msg/ c l i e n t 3 ) 127 then enqueue message < c l i e n t 3 msgcount=”{ $msgcount } ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// body } 129 </ c l i e n t 3 > i n t o c l i e n t 3 131 e l s e i f ( $msg/ c l i e n t 4 ) then enqueue message < c l i e n t 4 msgcount=”{ $msgcount } ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 133 {$msg// body } 135 </ c l i e n t 4 > i n t o c l i e n t 4 else () ; 137 (:∗∗ 139 ∗ common c l i e n t s ∗:) 141 c r e a t e r u l e pong1 f o r c l i e n t 1 l e t $msg := qs : message ( ) 143 l e t $msgcount := f n : number ( $msg/ c h i l d : ∗ / @msgcount ) return i f ( $msgcount <1000) 158 A.1 Quellcodes der Tests 145 Anhang then ( : pong t o s e r v e r : ) 147 enqueue message $msg i n t o s e r v e r else 149 ( : g i v e up : ) enqueue message $msg i n t o r e p o r t ; 151 c r e a t e r u l e pong2 f o r c l i e n t 2 153 l e t $msg := qs : message ( ) l e t $msgcount := f n : number ( $msg/ c h i l d : ∗ / @msgcount ) 155 return i f ( $msgcount <1000) then 157 ( : pong t o s e r v e r : ) enqueue message $msg i n t o s e r v e r 159 else ( : g i v e up : ) 161 enqueue message $msg i n t o r e p o r t ; 163 c r e a t e r u l e pong3 f o r c l i e n t 3 l e t $msg := qs : message ( ) 165 l e t $msgcount := f n : number ( $msg/ c h i l d : ∗ / @msgcount ) return i f ( $msgcount <1000) 167 then ( : pong t o s e r v e r : ) 169 enqueue message $msg i n t o s e r v e r else 171 ( : g i v e up : ) enqueue message $msg i n t o r e p o r t ; 173 c r e a t e r u l e pong4 f o r c l i e n t 4 175 l e t $msg := qs : message ( ) l e t $msgcount := f n : number ( $msg/ c h i l d : ∗ / @msgcount ) 177 return i f ( $msgcount <1000) then 159 A.1 Quellcodes der Tests 179 Anhang ( : pong t o s e r v e r : ) enqueue message $msg i n t o s e r v e r 181 else ( : g i v e up : ) 183 enqueue message $msg i n t o r e p o r t ; A.1.2.2 test2ClientServer2.dql 1 import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” a t ”/home/ dknochen / demaq orig / s r c / xquery / d e m a q l i b r a r y . x q l ” ; 3 (:∗∗ 5 ∗ s t a r t queue ∗:) 7 c r e a t e queue incoming kind incoming 9 i n t e r f a c e ”h t t p : / / l o c a l h o s t ” p o r t ”8080 ” 11 response incoming response mode p e r s i s t e n t ; 13 (:∗∗ 15 ∗ the re po r t that w i l l stop the a p p l i c a t i o n ∗:) 17 c r e a t e queue r e p o r t kind b a s i c 19 mode p e r s i s t e n t ; 21 ( : ∗ ∗ ∗ the s e r v e r 23 ∗:) c r e a t e queue s e r v e r 25 kind b a s i c 160 A.1 Quellcodes der Tests Anhang mode p e r s i s t e n t ; 27 (:∗∗ 29 ∗ a l l other c l i e n t s ∗:) 31 c r e a t e queue c l i e n t 1 kind b a s i c 33 mode p e r s i s t e n t ; 35 c r e a t e queue c l i e n t 2 kind b a s i c 37 mode p e r s i s t e n t ; 39 c r e a t e queue c l i e n t 3 kind b a s i c 41 mode p e r s i s t e n t ; 43 c r e a t e queue c l i e n t 4 kind b a s i c 45 mode p e r s i s t e n t ; 47 ( : ∗ ∗ ∗ enqueue s t a r t message 49 ∗:) c r e a t e r u l e s t a r t u p f o r incoming 51 l e t $msg := . return enqueue message 53 <r o o t kind=” s t a r t u p ”> <body> 55 {$msg/ c h i l d : ∗ } </body> 57 </r o o t > i n t o s e r v e r ; 59 ( : ∗ ∗ 161 A.1 Quellcodes der Tests Anhang ∗ enqueue r e s p o n s e message 61 ∗:) c r e a t e r u l e stop for r e p o r t 63 l e t $msg := . return 65 l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d return i f ( ( count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =4) and 67 ( count ( qs : queue ( ’ i n c o m i n g r e s p o n s e ’ ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =0) ) 69 then enqueue message <r o o t kind=” s t o p ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 71 <msgs> { count ( qs : queue ( ) ) } 73 </msgs> <s e s s i o n m s g s > { count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) } 75 </s e s s i o n m s g s > 77 </r o o t > i n t o i n c o m i n g r e s p o n s e else () ; 79 (:∗∗ 81 ∗ server ∗:) 83 c r e a t e r u l e m a s t e r p i n g f o r s e r v e r l e t $msg := qs : message ( ) 85 return i f ( $msg// r o o t / @kind=”s t a r t u p ”) then 87 l e t $ s e s s i o n i d := count ( qs : queue ( ’ r e p o r t ’ ) ) return 89 ( : p i n g i n i t i a l message t o a l l o t h e r s : ) ( 91 enqueue message < c l i e n t 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 93 {$msg// r o o t / body } 162 A.1 Quellcodes der Tests Anhang </ c l i e n t 1 > i n t o c l i e n t 1 , 95 enqueue message < c l i e n t 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 97 </ c l i e n t 2 > i n t o c l i e n t 2 , 99 enqueue message < c l i e n t 3 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 101 </ c l i e n t 3 > i n t o c l i e n t 3 , 103 enqueue message < c l i e n t 4 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 105 </ c l i e n t 4 > i n t o c l i e n t 4 107 ) else 109 ( : i n c r e a s e msgcount by 1 . then check where t h e pong came from and 111 p i n g i t back : ) l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 113 return i f ( $msg/ c l i e n t 1 ) 115 then enqueue message < c l i e n t 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 117 {$msg// body } </ c l i e n t 1 > i n t o c l i e n t 1 119 e l s e i f ( $msg/ c l i e n t 2 ) then enqueue message 121 < c l i e n t 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// body } 123 </ c l i e n t 2 > i n t o c l i e n t 2 e l s e i f ( $msg/ c l i e n t 3 ) 125 then enqueue message < c l i e n t 3 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 127 {$msg// body } 163 A.1 Quellcodes der Tests Anhang </ c l i e n t 3 > i n t o c l i e n t 3 129 e l s e i f ( $msg/ c l i e n t 4 ) then enqueue message < c l i e n t 4 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 131 {$msg// body } 133 </ c l i e n t 4 > i n t o c l i e n t 4 else () ; 135 (:∗∗ 137 ∗ common c l i e n t s ∗:) 139 c r e a t e r u l e pong1 f o r c l i e n t 1 l e t $msg := qs : message ( ) 141 return l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 143 return l e t $msgcount := count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) 145 return i f ( $msgcount <100) then 147 ( : pong t o s e r v e r : ) enqueue message $msg i n t o s e r v e r 149 else ( : g i v e up : ) 151 enqueue message $msg i n t o r e p o r t ; 153 c r e a t e r u l e pong2 f o r c l i e n t 2 l e t $msg := qs : message ( ) 155 return l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 157 return l e t $msgcount := count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) 159 return i f ( $msgcount <100) then 161 ( : pong t o s e r v e r : ) 164 A.1 Quellcodes der Tests Anhang enqueue message $msg i n t o s e r v e r 163 else ( : g i v e up : ) 165 enqueue message $msg i n t o r e p o r t ; 167 c r e a t e r u l e pong3 f o r c l i e n t 3 l e t $msg := qs : message ( ) 169 return l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 171 return l e t $msgcount := count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) 173 return i f ( $msgcount <100) then 175 ( : pong t o s e r v e r : ) enqueue message $msg i n t o s e r v e r 177 else ( : g i v e up : ) 179 enqueue message $msg i n t o r e p o r t ; 181 c r e a t e r u l e pong4 f o r c l i e n t 4 l e t $msg := qs : message ( ) 183 return l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 185 return l e t $msgcount := count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) 187 return i f ( $msgcount <100) then 189 ( : pong t o s e r v e r : ) enqueue message $msg i n t o s e r v e r 191 else ( : g i v e up : ) 193 enqueue message $msg i n t o r e p o r t ; 165 A.1 Quellcodes der Tests A.1.2.3 Anhang test3ProcessChain.dql 1 import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” a t ”/home/ dknochen / demaq orig / s r c / xquery / d e m a q l i b r a r y . x q l ” ; 3 (:∗∗ 5 ∗ s t a r t queue ∗:) 7 c r e a t e queue incoming kind incoming 9 i n t e r f a c e ”h t t p : / / l o c a l h o s t ” p o r t ”8080 ” 11 response incoming response mode p e r s i s t e n t ; 13 (:∗∗ 15 ∗ t h e r e p o r t queue t h a t w i l l s t o p t h e a p p l i c a t i o n ∗:) 17 c r e a t e queue r e p o r t kind b a s i c 19 mode p e r s i s t e n t ; 21 ( : ∗ ∗ ∗ the s t a r t / f i n i s h 23 ∗:) c r e a t e queue s t a r t f i n i s h 25 kind b a s i c mode p e r s i s t e n t ; 27 (:∗∗ 29 ∗ t h e complex p r o c e s s s t e p ∗:) 31 c r e a t e queue complex kind b a s i c 166 A.1 Quellcodes der Tests 33 Anhang mode p e r s i s t e n t ; 35 ( : ∗ ∗ ∗ the big c y c l e 37 ∗:) c r e a t e queue s i m p l e 1 39 kind b a s i c mode p e r s i s t e n t ; 41 c r e a t e queue s i m p l e 2 kind b a s i c 43 mode p e r s i s t e n t ; c r e a t e queue s i m p l e 3 45 kind b a s i c mode p e r s i s t e n t ; 47 (:∗∗ 49 ∗ the small c y c l e ∗:) 51 c r e a t e queue s i m p l e 4 kind b a s i c 53 mode p e r s i s t e n t ; c r e a t e queue s i m p l e 5 55 kind b a s i c mode p e r s i s t e n t ; 57 (:∗∗ 59 ∗ cycle property ∗ i n d i c a t e s from which c y c l e t h e p r o c e s s 61 ∗ a c t u a l l y comes from ∗:) 63 c r e a t e p r o p e r t y c y c l e queue s t a r t f i n i s h , s i m p l e 1 , s i m p l e 2 , s i m p l e 3 , s i m p l e 4 , s i m p l e 5 , complex 65 value ”” ; 167 A.1 Quellcodes der Tests Anhang 67 ( : ∗ ∗ ∗ p r o p e r t y t o count t h e f i n i s h e d p r o c e s s e s 69 ∗:) create property processcount 71 queue s t a r t f i n i s h , s i m p l e 1 , s i m p l e 2 , s i m p l e 3 , s i m p l e 4 , s i m p l e 5 , complex value 0; 73 (:∗∗ 75 ∗ enqueue s t a r t message ∗:) 77 c r e a t e r u l e s t a r t u p f o r incoming l e t $msg := . 79 return enqueue message <r o o t kind=” s t a r t u p ”> 81 <body> {$msg/ c h i l d : ∗ } 83 </body> </r o o t > i n t o s t a r t f i n i s h ; 85 (:∗∗ 87 ∗ enqueue r e s p o n s e message ∗:) 89 c r e a t e r u l e s t o p f o r r e p o r t l e t $msg := . 91 return l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 93 return i f ( ( count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =5) and ( count ( qs : queue ( ’ i n c o m i n g r e s p o n s e ’ ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =0) ) 95 then enqueue message <r o o t kind=” s t o p ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 97 <msgs> { count ( qs : queue ( ) ) } 99 </msgs> 168 A.1 Quellcodes der Tests Anhang <s e s s i o n m s g s > { count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) } 101 </s e s s i o n m s g s > 103 </r o o t > i n t o i n c o m i n g r e s p o n s e else () ; 105 107 ( : ∗ ∗ ∗ s t a r t and f i n i s h 109 ∗:) c r e a t e r u l e s t a r t r u n f i n i s h for s t a r t f i n i s h 111 l e t $msg := qs : message ( ) return i f ( $msg// r o o t / @kind=”s t a r t u p ”) 113 then l e t $ s e s s i o n i d := count ( qs : queue ( ’ r e p o r t ’ ) ) 115 return ( : s t a r t the race : ) 117 ( enqueue message 119 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 121 </p r o c e s s 1 > i n t o s i m p l e 1 with c y c l e v a l u e ” b i g c y c l e ” 123 with p r o c e s s c o u n t v a l u e 1 , enqueue message 125 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 127 </p r o c e s s 2 > i n t o s i m p l e 1 with c y c l e v a l u e ” b i g c y c l e ” 129 with p r o c e s s c o u n t v a l u e 1 , enqueue message 131 <p r o c e s s 3 s e s s i o n i d=”{ $ s e s s i o n i d } ” > {$msg// r o o t / body } 133 </p r o c e s s 3 > i n t o s i m p l e 1 169 A.1 Quellcodes der Tests Anhang with c y c l e v a l u e ” b i g c y c l e ” 135 with p r o c e s s c o u n t v a l u e 1 , enqueue message <p r o c e s s 4 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 137 {$msg// r o o t / body } 139 </p r o c e s s 4 > i n t o s i m p l e 1 with c y c l e v a l u e ” b i g c y c l e ” 141 with p r o c e s s c o u n t v a l u e 1 , enqueue message <p r o c e s s 5 s e s s i o n i d=”{ $ s e s s i o n i d } ” > 143 {$msg// r o o t / body } 145 </p r o c e s s 5 > i n t o s i m p l e 1 with c y c l e v a l u e ” b i g c y c l e ” 147 with p r o c e s s c o u n t v a l u e 1 ) 149 else ( : i n c r e a s e p r o c e s s c o u n t by 1 . then 151 s t a r t t h e next p r o c e s s c h a i n : ) l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) 153 return i f ( $ p r o c e s s c o u n t <50) then 155 enqueue message $msg i n t o s i m p l e 1 with c y c l e v a l u e ” b i g c y c l e ” 157 with p r o c e s s c o u n t v a l u e ( $ p r o c e s s c o u n t +1) else 159 enqueue message $msg i n t o r e p o r t ; 161 ( : ∗ ∗ ∗ big cycle 163 ∗:) c r e a t e r u l e s i m p l e 1 r u l e for simple1 165 l e t $msg := qs : message ( ) l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) 167 return 170 A.1 Quellcodes der Tests Anhang enqueue message $msg i n t o s i m p l e 2 169 with c y c l e v a l u e ” b i g c y c l e ” with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; 171 c r e a t e r u l e s i m p l e 2 r u l e for simple2 173 l e t $msg := qs : message ( ) l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) 175 return enqueue message $msg i n t o s i m p l e 3 177 with c y c l e v a l u e ” b i g c y c l e ” with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; 179 c r e a t e r u l e s i m p l e 3 r u l e for simple3 181 l e t $msg := qs : message ( ) l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) 183 return enqueue message $msg i n t o complex 185 with c y c l e v a l u e ” b i g c y c l e ” with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; 187 (:∗∗ 189 ∗ small cycle ∗:) 191 c r e a t e r u l e s i m p l e 4 r u l e f o r s i m p l e 4 l e t $msg := qs : message ( ) 193 l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) return 195 enqueue message $msg i n t o s i m p l e 5 with c y c l e v a l u e ” s m a l l c y c l e ” 197 with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; 199 c r e a t e r u l e s i m p l e 5 r u l e f o r s i m p l e 5 l e t $msg := qs : message ( ) 201 l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) 171 A.1 Quellcodes der Tests Anhang return 203 enqueue message $msg i n t o complex with c y c l e v a l u e ” s m a l l c y c l e ” 205 with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; 207 c r e a t e r u l e c o m p l e x r u l e f o r complex l e t $msg := qs : message ( ) 209 l e t $ p r o c e s s c o u n t := f n : number ( qs : p r o p e r t y ( ” p r o c e s s c o u n t ”) ) l e t $ c y c l e := qs : p r o p e r t y ( ” c y c l e ”) 211 return i f ( $ c y c l e=” b i g c y c l e ”) 213 then enqueue message $msg i n t o s i m p l e 4 215 with c y c l e v a l u e ” s m a l l c y c l e ” with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t 217 else enqueue message $msg i n t o s t a r t f i n i s h 219 with c y c l e v a l u e ” b i g c y c l e ” with p r o c e s s c o u n t v a l u e $ p r o c e s s c o u n t ; A.1.2.4 test4SplitJoin.dql import module namespace qs = ”h t t p : / /www. demaq . n e t / d q l ” 2 a t ”/home/ dknochen / demaq orig / s r c / xquery / d e m a q l i b r a r y . x q l ” ; 4 (:∗∗ ∗ s t a r t queue 6 ∗:) c r e a t e queue incoming 8 kind incoming i n t e r f a c e ”h t t p : / / l o c a l h o s t ” 10 p o r t ”8080 ” response incoming response 172 A.1 Quellcodes der Tests 12 Anhang mode p e r s i s t e n t ; 14 ( : ∗ ∗ ∗ t h e r e p o r t −queue t h a t w i l l s t o p t h e a p p l i c a t i o n 16 ∗:) c r e a t e queue r e p o r t 18 kind b a s i c mode p e r s i s t e n t ; 20 (:∗∗ 22 ∗ t h e s p l i t t i n g queue ∗:) 24 c r e a t e queue s p l i t kind b a s i c 26 mode p e r s i s t e n t ; 28 ( : ∗ ∗ ∗ the f i r s t c h i l d p r o c e s s 30 ∗:) c r e a t e queue c h i l d 1 32 kind b a s i c mode p e r s i s t e n t ; 34 (:∗∗ 36 ∗ the second c h i l d p r o c e s s ∗:) 38 c r e a t e queue c h i l d 2 kind b a s i c 40 mode p e r s i s t e n t ; 42 ( : ∗ ∗ ∗ t h e f o r w a r d queue 44 ∗:) c r e a t e queue f o r w a r d 173 A.1 Quellcodes der Tests 46 Anhang kind b a s i c mode p e r s i s t e n t ; 48 (:∗∗ 50 ∗ the choose s l i c e ∗ t h i s s l i c e i s used t o c h o o s e 52 ∗ the s u p e r i o r of the c h i l d p r o c e s s e s ∗:) 54 c r e a t e s l i c i n g p r o p e r t y c h o o s e queue c h i l d 2 , c h i l d 1 56 v a l u e . // @ p r o c e s s i d ; 58 ( : ∗ ∗ ∗ enqueue s t a r t message 60 ∗:) c r e a t e r u l e s t a r t u p f o r incoming 62 l e t $msg := . return enqueue message 64 <r o o t kind=” s t a r t u p ”> <body> {$msg/ c h i l d : ∗ } 66 </body> 68 </r o o t > i n t o s p l i t ; 70 ( : ∗ ∗ ∗ enqueue r e s p o n s e message 72 ∗:) c r e a t e r u l e stop for r e p o r t 74 l e t $msg := . return 76 l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d return i f ( ( count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =5) and 78 ( count ( qs : queue ( ’ i n c o m i n g r e s p o n s e ’ ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) =0) ) 174 A.1 Quellcodes der Tests Anhang then enqueue message <r o o t kind=” s t o p ” s e s s i o n i d=”{ $ s e s s i o n i d } ” > 80 <msgs> { count ( qs : queue ( ) ) } 82 </msgs> 84 <s e s s i o n m s g s > { count ( qs : queue ( ) [ // @ s e s s i o n i d=$ s e s s i o n i d ] ) } 86 </s e s s i o n m s g s > </r o o t > i n t o i n c o m i n g r e s p o n s e 88 else () ; 90 ( : ∗ ∗ ∗ split processes 92 ∗:) c r e a t e r u l e s p l i t t i n g for s p l i t 94 l e t $msg := qs : message ( ) return i f ( $msg// r o o t / @kind=”s t a r t u p ”) 96 then l e t $ s e s s i o n i d := count ( qs : queue ( ’ r e p o r t ’ ) ) 98 return ( : s p l i t t h e f i r s t time : ) 100 ( l e t $random sup := b o o l e a n ( number ( 102 s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” 1 1 ”) 104 return ( enqueue message 106 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”1 ” > {$msg// r o o t / body } 108 </p r o c e s s 1 > i n t o c h i l d 1 , enqueue message 110 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( 175 A.1 Quellcodes der Tests Anhang $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”1 ” > {$msg// r o o t / body } 112 </p r o c e s s 2 > i n t o c h i l d 2 ) , l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) 114 l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” 1 2 ”) return ( 116 enqueue message <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”1 ” > 118 {$msg// r o o t / body } </p r o c e s s 1 > i n t o c h i l d 1 , 120 enqueue message <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”1 ” > 122 {$msg// r o o t / body } </p r o c e s s 2 > i n t o c h i l d 2 ) , 124 l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” 1 3 ”) 126 return ( enqueue message 128 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”1 ” > {$msg// r o o t / body } 130 </p r o c e s s 1 > i n t o c h i l d 1 , enqueue message 132 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”1 ” > 176 A.1 Quellcodes der Tests Anhang {$msg// r o o t / body } 134 </p r o c e s s 2 > i n t o c h i l d 2 ) , l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) 136 l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” 1 4 ”) return ( 138 enqueue message <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”1 ” > 140 {$msg// r o o t / body } </p r o c e s s 1 > i n t o c h i l d 1 , 142 enqueue message <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”1 ” > 144 {$msg// r o o t / body } </p r o c e s s 2 > i n t o c h i l d 2 ) , 146 l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” 1 5 ”) 148 return ( enqueue message 150 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”1 ” > {$msg// r o o t / body } 152 </p r o c e s s 1 > i n t o c h i l d 1 , enqueue message 154 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”1 ” > {$msg// r o o t / body } 156 </p r o c e s s 2 > i n t o c h i l d 2 ) 177 A.1 Quellcodes der Tests Anhang ) 158 else ( : i n c r e a s e p r o c e s s c o u n t by 1 . then s p l i t a g a i n : ) 160 l e t $ p r o c e s s c o u n t :=number ( $msg// @ p r o c e s s c o u n t )+1 l e t $ s e s s i o n i d :=$msg// @ s e s s i o n i d 162 return (: split :) 164 ( l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) 166 l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” ” , $ p r o c e s s c o u n t , ” 1 ”) return ( 168 enqueue message <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”{ $ p r o c e s s c o u n t } ” > 170 {$msg// r o o t / body } </p r o c e s s 1 > i n t o c h i l d 1 , 172 enqueue message <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”{ $ p r o c e s s c o u n t } ” > 174 {$msg// r o o t / body } </p r o c e s s 2 > i n t o c h i l d 2 ) , 176 l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” ” , $ p r o c e s s c o u n t , ” 2 ”) 178 return ( enqueue message 180 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 182 </p r o c e s s 1 > i n t o c h i l d 1 , 178 A.1 Quellcodes der Tests Anhang enqueue message 184 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 186 </p r o c e s s 2 > i n t o c h i l d 2 ) , l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) 188 l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” ” , $ p r o c e s s c o u n t , ” 3 ”) return ( 190 enqueue message <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”{ $ p r o c e s s c o u n t } ” > 192 {$msg// r o o t / body } </p r o c e s s 1 > i n t o c h i l d 1 , 194 enqueue message <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”{ $ p r o c e s s c o u n t } ” > 196 {$msg// r o o t / body } </p r o c e s s 2 > i n t o c h i l d 2 ) , 198 l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” ” , $ p r o c e s s c o u n t , ” 4 ”) 200 return ( enqueue message 202 <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 204 </p r o c e s s 1 > i n t o c h i l d 1 , enqueue message 206 <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( 179 A.1 Quellcodes der Tests Anhang $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 208 </p r o c e s s 2 > i n t o c h i l d 2 ) , l e t $random sup := b o o l e a n ( number ( s e c o n d s −from−dateTime ( c u r r e n t −dateTime ( ) ) ) mod 2 ) 210 l e t $ p r o c e s s i d := c o n c a t ( $ s e s s i o n i d , ” ” , $ p r o c e s s c o u n t , ” 5 ”) return ( 212 enqueue message <p r o c e s s 1 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ $random sup } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t =”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 214 </p r o c e s s 1 > i n t o c h i l d 1 , 216 enqueue message <p r o c e s s 2 s e s s i o n i d=”{ $ s e s s i o n i d } ” s u p e r i o r=”{ not ( $random sup ) } ” p r o c e s s i d=”{ $ p r o c e s s i d } ” p r o c e s s c o u n t=”{ $ p r o c e s s c o u n t } ” > {$msg// r o o t / body } 218 </p r o c e s s 2 > i n t o c h i l d 2 ) 220 ); 222 ( : ∗ ∗ ∗ choose the s u p e r i o r p r o c e s s 224 ∗:) c r e a t e r u l e c h o o s e r u l e for choose 226 l e t $msg := . l e t $ s l i c e=qs : s l i c e ( ) 228 l e t $ s u p e r i o r := $ s l i c e / c h i l d : ∗ [ @ s u p e r i o r=true ( ) ] return i f ( $msg/∗ / @ s u p e r i o r=f n : t r u e ( ) ) 230 then ( : l e t the superior through : ) 232 enqueue message $ s u p e r i o r i n t o f o r w a r d else () ; 180 A.1 Quellcodes der Tests Anhang 234 create r u l e forwardrule f o r forward 236 l e t $msg := q s : message ( ) l e t $ p r o c e s s c o u n t := f n : number ( $msg // @ p r o c e s s c o u n t ) 238 r e t u r n i f ( $ p r o c e s s c o u n t <100) then 240 ( : s t a r t t h e n e x t p r o c e s s round : ) enqueue message $msg i n t o s p l i t 242 else (: report :) 244 enqueue message $msg i n t o r e p o r t ; 181