Fractal ADL France Telecom 17-12-2004 Matthieu Leclercq.
-
Upload
reinald-le-berre -
Category
Documents
-
view
109 -
download
0
Transcript of Fractal ADL France Telecom 17-12-2004 Matthieu Leclercq.
Fractal ADL
France Telecom 17-12-2004
Matthieu Leclercq
Plan
L’ADL L’usine fractal ADL
L’interface Factory Modules, mini-DTD et AST Architecture de l’usine
Exemple d’extension Ajout dynamique de composants
L’ADL Fractal
Fichiers XML respectant une DTD Un fichier contient une définition Une définition est une description d’un composant.
Interfaces Sous composants (composant composite) Liaisons entre sous composants Implémentation (composant primitif) Contrôleurs
Attributs Contrôleurs Julia (julia.cfg)
runservice
Exemple
Composants Helloworld du tutorial Fractal La méthode run exécute le client qui appel le
serveur grâce à l’interface service
serverclient
HelloWorld
Exemple<definition name="HelloWorld">
<interface name="r" role="server"signature="java.lang.Runnable"/>
<component name="client"><interface name="r" role="server"
signature="java.lang.Runnable"/><interface name="s" role="client"
signature="Service"/><content class="ClientImpl"/>
</component>
<component name="server"><interface name="s" role="server"
signature="Service"/><content class="ServerImpl"/>
</component>
<binding client="this.r" server="client.r"/>
<binding client="client.s" server="server.s"/>
</definition>
HelloWorld
runclient server
Exemple
L’exemple précédent présente un ADL monolithique. Une application est décrite dans un ADL.
Techniques pour découper la description d’une application dans plusieurs fichiers ADL. Référence d’ADL Héritage d’ADL ADL paramétrique
Référence d’ADL
L’ADL du client peut être écrit dans un fichier séparé et référencé dans l’ADL du composite<definition name="HelloWorld">
<interface name="r" role="server"signature="java.lang.Runnable"/>
<component name="client" definition="Client"/>...
Fichier Client.fractal :<definition name="Client">
<interface name="r" role="server" signature="java.lang.Runnable"/>
<interface name="s" role="client"signature="Service"/>
<content class="ClientImpl"/></definition>
Heritage d’ADL Un ADL peut étendre un autre ADL.
Définition du type du composant client :<definition name="ClientType">
<interface name="r" role="server" signature="java.lang.Runnable"/>
<interface name="s" role="client"signature="Service"/>
</definition>
Définition du composant client concret :<definition name="Client" extends="ClientType">
<content class="ClientImpl"/></definition>
Héritage multiple Liste de définitions séparées par des virgules Graphe d’héritage linéarisé pour résoudre les conflits
Arguments d’un l’ADL
Un ADL peut être paramétré par une liste d’arguments.
Le parser remplace textuellement les arguments par leur valeur (chaîne de caractères)
<definition name="Client" arguments="impl"><interface name="r" role="server"
signature="java.lang.Runnable"/><interface name="s" role="client«
signature="Service"/><content class="${impl}"/>
</definition>
<definition name="HelloWorld"><interface name="r" role="server"
signature="java.lang.Runnable"/>
<component name="client" definition="Client(ClientImpl)"/>
...
Exemple avancé
Définition d’un composant par assemblage «d’aspects»
Exemple : Network Dream Un Network est un composite contenant un ChannelOut et
un ChannelIn.
Un Network peut être désynchronisé, fiable, causal, …
Network
ChannelOutCodec
ChannelIn
in-push out-push
Exemple avancé Exemple de l'aspect désynchronisé
Placer une file de message devant le ChannelOut
Définition de l’aspect désynchronisé :<definition name="AspectBuffered"
arguments="client,server"><component name="Queue"
definition="dream.PushPushActiveQueue"/><binding client="${client}" server="Queue.in-push"/><binding client="Queue.out-push" server="${server}"/>
</definition>
Définition d'un Network désynchronisé :<definition name="NetworkBuffered"
extends="AspectBuffered(this.in-push,ChannelOut.in-push), Network()"/>
Exemple avancé
<definition name="NetworkBuffered" extends="AspectBuffered(this.in-push,ChannelOut.in-push),
Network()"/>
Network
AspectBuffered
NetworkBuffered
Network
ChannelOutCodec
ChannelIn
out-pushin-push
Queue
<definition name="AspectBuffered"arguments="client,server"><component name="Queue"
definition="dream.PushPushActiveQueue"/><binding client="${client}" server="Queue.in-push"/><binding client="Queue.out-push" server="${server}"/>
</definition>
Graphe d’Héritage
Plan
L’ADL L’usine fractal ADL
L’interface Factory Modules, mini-DTD et AST Architecture de l’usine
Exemple d’extension Ajout dynamique de sous composants
L’interface Factory
Fournit la méthode
Object newComponent (String name, Map context)
name : nom de la définition à créer context : contient les valeurs des arguments de la
définition Association nom de l’argument → valeur
Retourne l’interface Component du composant créé
La Factory est obtenue grâce aux méthodes statiques de la classe FactoryFactory
L’usine Fractal ADL
L’usine est modulaire et extensible Développé en fractal.
Utilise un AST (Abstract Syntaxic Tree) Créé par le parser XML Un nœud correspond à une entité XML
Un module défini Une partie de la DTD (mini-DTD) Les interfaces implémentées par les nœuds de l’AST
Les modules de l’ADL standard Module Component
Module de base Défini la composition : un composant peut contenir d’autres
composants Module Interface
Un composant possède des interfaces Module Binding
Les interfaces peuvent être liées Module Implementation
Un composant a une implémentation, des contrôleurs Module Argument
Une définition peut avoir des arguments ...
Module de l’ADL
Un module est constitué de Une mini-DTD (fragment de DTD) Un ensemble d’interfaces implementées par les
nœuds de l’AST Les méthodes suivent une convention de nommage Implémentation générée dynamiquement par ASM
Un ensemble de composants intégré à l’usine Fractal ADL. Réalisent des traitements spécifiques sur l’AST.
mini-DTD et interface d’AST
Exemple du module component
<!ELEMENT definition (component*) ><!ATTLIST definition
name CDATA #REQUIREDextends CDATA #IMPLIED>
<!ELEMENT component (component*) ><!ATTLIST component
name CDATA #REQUIREDdefinition CDATA #IMPLIED>
interface DefinitionNode {get/setName();get/setExtends();
}
interface ComponentNode {get/setName();get/setDefinition();
}
interface ComponentContainerNode {addComponent(Component c);getComponents();
}
<?add ast="definition" itf="DefinitionNode"?><?add ast="definition" itf="ComponentContainerNode"?>
<?add ast="component" itf="ComponentNode"?><?add ast="component" itf="ComponentContainerNode"?>
Exemple de parsing<definition name="HelloWorld">
<interface name="r" role="server" signature="java.lang.Runnable"/>
<component name="client" definition="Client"/>
<component name="server" definition="Server"/>
<binding client="this.r" server="client.r"/>
<binding client="client.s" server="server.s"/>
</definition>
Definition Name="Server"
Interface name="r", role="server" signature=…
Component name="client", definition="Client"
Component name="server", definition="Server"
Binding client="this.r", server="client.r"
Binding client="client.s", server="server.s"
addInterface()addComponent()addBinding()
Node implements DefinitionNode,InterfaceContainerNode,ComponentContainerNode,BindingContainerNode
Node implements InterfaceNode
Plan
L’ADL L’usine fractal ADL
L’interface Factory Modules, mini-DTD et AST Architecture de l'usine
Exemple d’extension Ajout dynamique de sous composants
Structure de l’usine
3 passes Génération d’un AST et vérification les contraintes
d’intégrité (ex : liaisons corrects) Construction d’un graphe de taches à exécuter pour
réaliser le déploiement Exécution de chaque tache en respectant l’ordre de
précédence.
Chaque passe est réalisée par un ensemble de composants spécifiques. Chaque module possède ses propres composants pour
chacune des 3 passes.
Loader
Première passe : les Loaders
La première passe est réalisée par une chaîne de Loaders Un Loader délègue au Loader suivant afin d’obtenir un
AST Le parseur XML est en bout de chaîne
Chaque Loader effectue un parcours de l’AST afin de vérifier des contraintes spécifique à un module Exemple : le BindingLoader vérifie pour chaque liaisons que
les interfaces clientes et serveurs existent et sont compatibles
BindingLoader
ComponentLoader
InterfaceLoader
ArgumentLoader
XMLLoader
Première passe : les Loaders
Le ComponentLoader mixe plusieurs AST en un seul Résolution des références, de l’héritage et du partage
de composant Les Loaders placés en « amont » du ComponentLoader effectuent un parcours de l’AST mixer. Les Loader en « aval » parcourent plusieurs AST Le BindingLoader est placé en amont
Les liaisons sont vérifiées sur l’AST mixé L’ArgumentLoader est placé en aval
Les arguments ont une portée locale à un fichier XML
Première passe : les Loaders<definition name="HelloWorld">
<interface name="r" role="server" signature="java.lang.Runnable"/><component name="client" definition="Client"/><component name="server" definition="Server"/><binding client="this.r" server="client.r"/><binding client="client.s" server="server.s"/>
</definition>
Loader
BindingLoader
ComponentLoader
XMLLoader
load("Helloworld")
Interface name="s", role="server" signature=…
Content class=…
Interface name="r", role="server" signature=…
Content class=…
Interface name="s", role="client" signature=…
Component name="Client"
Interface name="r", role="server" signature=…
Content class=…
Interface name="s", role="client" signature=…
Component name="Server"
Interface name="s", role="server" signature=…
Content class=…
load("Helloworld")load("Client")load("Server")
Definition Name="Helloworld"
Interface name="r", role="server" signature=…
Component name="server", definition="Server"
Binding client="this.r", server="client.r"
Binding client="client.s", server="server.s"
Component name="client", definition="Client"
Deuxième passe : les Compilers Les Compilers construisent un graphe de taches
élémentaires de déploiement Exemples de tache : instancier un composant, ajouter un
composant dans un composite, créer une liaison, ... Les taches dépendent les unes des autres
Pour effectuer une liaison il faut que les deux composants soient créés et ajoutés dans un même composite
L’exécution d’une tache fournit un résultat utilisable par les taches qui en dépendent La tache d’instanciation fournit le composant instancié aux
taches d’ajout dans un composite ou aux taches de liaison.
Deuxième passe : les Compilers Le MainCompilers
Effectue un parcours récursif des composants décris dans l‘AST
Exécute les Compilers auxquels il est lié
typeBuilder
componentBuilder
bindingBuilder
attributeBuilder
implementationBuilder
MainCompiler
TypeCompiler
ComponentCompiler
BindingCompiler
AttributeCompiler
ImplementationCompiler
Troisième passe : les Builders Les Builders sont appelés par les taches lorsqu’elles sont
exécutées. Chaque type de tache a son propre Builder
ImplementationBuilder pour les taches d’instanciation BindingBuilder pour les taches de liaison
L’ensemble des Builders est appelé Backend Fractal ADL fournit plusieurs Backends
FractalBackend créé des composants Fractal JavaBackend créé des objets Java StaticFractalBackend génère du code source pour créer des
composants Fractal StaticJavaBackend génère du code source pour créer des objets
Java
Plan
L’ADL L’usine fractal ADL
L’interface Factory Modules, mini-DTD et AST Architecture de l’usine
Exemple d’extension Ajout dynamique de sous composants
Ajout dynamique de sous composants
Décrire, dans un ADL, une structure existante ainsi que des composants à y ajouter Les composants existants sont dits legacy
<definition name="AddServer"arguement="num"><component name="duplicator">
<interface name="s"role="client"cardinality="collection" signature="Service"/>
<legacycontingency="mandatory"/>
</component><component name="server${num}"
definition="Server"/><binding
client="duplicator.s${num}"server="server${num}.s"/>
</definition>
server3
client server1
server2duplicator
HelloWorld
s s
Modification de la DTD
Modification apportée à la DTD afin d'intégrer le nouveau module :
<!ELEMENT component (..., legacy?, ...) >
<!ELEMENT legacy EMPTY><!ATTLIST legacy contingency (mandatory | optional) #REQUIRED >
<!-- legacy module --><?add ast="component" itf="LegacyContainer" ?><?add ast="legacy" itf="Legacy" ?>
Le LegacyLoader
Nouveau Loader inséré en tête de la chaîne de Loaders
Parcourt en parallèle l'AST et la structure à reconfigurer Le composant à reconfigurer est obtenu via le contexte
Vérifie que les composants legacy existent et sont compatibles avec leur description ADL Le type des composants legacy doit être un sous type du
composant décrit dans l'ADL
Loader
LeagacyLoader
BindingLoader
…
Le précompilateur Ajout d'une passe de précompilation
Insertion de taches d'instanciation « fictives » pour les composants existants Les composants existants ne doivent pas être recréés Ces taches fournissent l’instance existante aux taches qui
en dépendent Le Builder d’ajout dans un composite est réécrit
Vérifie que le composant n’est pas déjà dans le composite
MainCompiler
TypeCompiler
…
MainCompiler
LegacyCompiler
Pre-PostCompiler
Perspectives
Modules existants Support pour le packaging Ajout d’information pour le changement dynamique de
classe
Tache ant pour la « compilation » statique d’ADL Générer du code source pour déployer rapidement une
architecture fixe.
ADL de reconfiguration dynamique Déploiement distribué intentionnel