! Université Joseph Fourier
DEUG STPI - 2ème année - IUP MIAG - 1ère année
Introduction aux systèmes et réseaux
 
 
Réalisation d'objets partagés répartis
avec Tcl-DP
 
 

 
 

Tcl-DP (Distributed Processing) est l'extension répartie de Tcl. Elle permet de réaliser très simplement des systèmes client-serveur et des systèmes à objets partagés répartis. Cette fiche présente les objets répartis. On suppose connu le principe de la réalisation du schéma client-serveur en Tcl-DP (appel de procédure à distance) ; voir la fiche correspondante. On suppose également connus les principes élémentaires de la programmation par objets (classe, instances, appel de méthode).

Objets répartis : principes

Un schéma "idéal" de gestion d'objets répartis est représenté sur la figure ci-dessous. Un objet unique est partagé par un ensemble de processus, répartis sur plusieurs sites. Chaque processus peut appeler les méthodes de l'objet, et toute modification de l'état de l'objet devient immédiatement visible à tous les processus (on n'aborde pas ici les problèmes de synchronisation liés au partage - on suppose pour simplifier que tout appel de méthode s'exécute en exclusion mutuelle).

Le schéma réel (figure ci-dessous) est une approximation de ce schéma idéal. En fait, un processus particulier se comporte comme le serveur de l'objet et les autres comme des clients. Néanmoins, après une phase initiale de mise en place, la situation est voisine de celle du schéma idéal, en ce sens que tout processus (client ou serveur) peut exécuter les méthodes de l'objet et tout processus voit immédiatement les changements de l'état de l'objet provoqués par les autres processus.

La phase initiale de mise en place comporte les étapes suivantes :

  • chez le serveur : création et initialisation de l'objet.
  • chez chacun des clients : appel au serveur demandant la "distribution" de l'objet partagé. Cette opération crée un "représentant" local de l'objet avec une interface identique à celle de l'objet. Les appels sont faits localement au représentant, qui les transmet à l'objet sur le serveur. Ce mécanisme est invisible pour l'application. : le processus client "voit" l'objet comme s'il était local et ignore l'existence du représentant.
  • chez le serveur et les clients : mise en place de "déclencheurs" : il s'agit d'un mécanisme qui permet d'associer une action à toute modification de l'état d'un objet. C'est ce mécanisme qui permet (par exemple) de réafficher un objet lors de chacune de ses modifications.
  • Objets répartis : mécanismes

    N. B. Bien que leur principe soit simple, les mécanismes de répartition des objets dans Tcl_DP peuvent paraître difficiles à comprendre au premier abord. Il est donc conseillé de lire la description qui suit, sans nécessairement essayer de comprendre tous les détails en première lecture, puis d'étudier soigneusement l'exemple fourni (et de le faire exécuter). On pourra ensuite revenir à la description des commandes.

    Un objet est un exemplaire (ou instance) d'une classe, qui définit la structure de l'état des instances de cette classe et le programme des méthodes qui leur sont applicables. L'état est composé de champs ("slots") dont chacun a un nom et une valeur. Par exemple, pour une classe définissant des points (cf exemple plus loin), l'état d'un point est composé de 3 champs de noms x, y et c. Leur valeur est respectivement l'abscisse, l'ordonnée et la couleur du point.

    Si class est le nom d'une classe, on définit ainsi une méthode de nom method dans cette classe :

    proc class.method {object arg0 ... argn} {
    <corps de la méthode>
    }
    class est le nom de la classe, object est l'identificateur de l'objet auquel s'applique la méthode et arg0 ... argn les paramètres de la méthode. On doit toujours définir au minimum trois méthodes : configure, slot-value, et destroy.
    configure permet d'accéder à l'état de l'objet et de le manipuler.
    slot-value prend en paramètre le nom d'un champ et rend la valeur de ce champ.
    destroy détruit l'objet sur lequel elle est appelée.
    La définition des autres méthodes est spécifique de la classe considérée.

    Attention : pour appeler une méthode method sur un objet object, la notation est :

    object method ?args?
    Pour toute classe, il faut définir une procédure de création des instances de cette classe. Cette procédure sert également à définir la structure de l'état des objets de la classe (champs). Tcl_DP fournit pour cela les commandes suivantes.
    dp_objectCreateProc class object
    créee un nouvel objet, instance d'une classe. Les paramètres sont le nom de la classe et l'identificateur de l'instance. Ce dernier nom va désormais désigner le nouvel objet créé.

    Les commandes suivantes permettent de définir les champs d'un objet, et de consulter et de modifier leur valeur.

    dp_objectSlotSet object slot value
    définit un champ. Les paramètres sont le nom d'un objet, le nom d'un champ et la valeur initiale du champ.
    dp_objectSlots object
    renvoie la liste des champs de l'objet passé en paramètre.
    dp_objectConfigure class object ?args?
    permet de configurer un objet, pour pouvoir y accéder. Paramètres : nom d'un objet, nom d'une classe, et suite de couples -<nom de champ> <valeur du champ> (noter le signe - devant le nom du champ ; construction analogue à la configuration des widgets en TK).

    Répartition et partage des objets

    Principe

    Un objet destiné à être réparti est d'abord créé dans un processus serveur. Il est ensuite distribué aux processus clients qui en font la demande. La distribution est réalisée par la commande

    dp_DistributeObject object processes makeObject
    dont les paramètres sont : object l'objet à distribuer, processes la liste des processus auxquels il doit être distribué (désignés par leur descripteur, voir fiche sur l'appel de procédure à distance), et makeObject est le nom de la procédure de création associée à la classe dont l'objet est une instance. Comme le serveur ne connaît pas en général a priori la liste des clients potentiels de l'objet, il exécute en fait cette commande sur demande du client, transmise par le mécanisme de l'appel de procédure à distance.

    Manipulation des objets répartis

    Dans les méthodes applicables aux objets répartis, la manipulation des champs d'un objet se fait par des commandes spéciales qui assurent notamment que les modifications faites par un processus sont répercutées chez tous les processus qui ont accès à cet objet (ce que ne fait pas la commande dp_objectSlotSet) :

    dp_setf object slot value affecte la valeur value au champ slot de l'objet object.
    dp_getf object slot renvoie la valeur du champ slot de l'objet object.
    Déclencheurs

    Tcl-DP permet d'associer l'exécution d'une commande à une modification d'un objet par dp_setf, au moyen d'un mécanisme appelé déclencheur (trigger). La commande qui réalise cette assoation est

    dp_SetTrigger when object slot trigger_list
    object et slot désignent respectivement l'objet réparti et le champ de cet objet dont la modification entraîne l'exécution des commandes données dans trigger_list. Le paramètre when indique quand l'évaluation de ces commandes doit avoir lieu : la valeur before indique que l'évaluation a lieu avant que la modification soit faite et la valeur after indique que l'évaluation a lieu après que la modification ait été faite.

    On peut consulter les déclencheurs associés aux champs d'un objet (dp_GetTrigger), rajouter une commande à la liste des déclencheurs pour un champ d'un objet (dp_AppendTrigger), ou supprimer des déclencheurs (dp_ReleaseTrigger).

    Exemple

    Cet exemple simple illustre la gestion d'objets répartis de classe point. Les programmes sont dans quatre fichiers reproduits ci-après (également dans le répertoire : /h/thales/u8/enseigt/krakowis/tp-tcl/Point/)

    point-class.tcl contient la définition des méthodes de la classe point et leur procédure de création.

    graphique.tcl contient une procédure pour afficher les points dans une fenêtre (pour simplifier, l'ancienne image du point n'est pas effacée)

    point-serveur.tcl contient le programme du serveur de points.

    point-client.tcl contient le programme du client.

    Pour faire marcher cet exemple, créer deux processus et faire exécuter le programme point-serveur.tcl dans l'un et le programme point-client.tcl dans l'autre (utiliser wish). On aura ainsi créé un point partagé nommé p. On pourra ensuite, dans l'interprète wish du client ou dans celui du serveur, changer l'un des champs de p (par exemple p setX 50, ou p setC red). Vérifier que la modification est bien répercutée vers les deux processus. On pourra ensuite créer d'autres points. On pourra aussi créer plusieurs clients.

    fichier point-class.tcl

    # procedure de creation
    # on cree un nouvel objet aPoint
    # avec des parametres de creation dans une liste args

    package require dp
    proc makePoint {aPoint args} {

    # creation de l'objet avec le nom point passe' en parametre
    eval dp_objectCreateProc point $aPoint;
    #Ces objets ont trois champs : coordonnees x et y, couleur c
    dp_objectSlotSet $aPoint x 0;
    dp_objectSlotSet $aPoint y 0;
    dp_objectSlotSet $aPoint c black;
    eval $aPoint configure $args; # "configuration" de l'objet (obligatoire)
    }

    # declaration des methodes de la classe point

    proc point.configure {aPoint args} {

    eval dp_objectConfigure point $aPoint $args
    }

    proc point.slot-value {aPoint slot} {

    dp_objectSlot $aPoint $slot; # renvoie la valeur du champ ?slot'
    }

    proc point.destroy {aPoint} {

    dp_objectFree $aPoint; # détruit l'objet ?aPoint'
    }

    proc point.setX {aPoint newX} {

    dp_setf $aPoint x $newX; # change la valeur du champ ?x' (abscisse)
    }

    proc point.setY {aPoint newY} {

    dp_setf $aPoint y $newY; # change la valeur du champ ?y' (ordonnée)
    }

    proc point.setC {aPoint newC} {

    dp_setf $aPoint c $newC; # change la valeur du champ ?c' (couleur)
    };

    # dessine le point sur l'écran

    proc point.draw {aPoint args} {

    set xx [dp_getf $aPoint x]; # xx, yy, cc variables locales
    set yy [dp_getf $aPoint y];
    set cc [dp_getf $aPoint c];
    dot $xx $yy $cc; # procedure definie dans le fichier graphique.tcl
    }
     
     

    fichier point-serveur.tcl

    package require dp
    source point-class.tcl;
    source graphique.tcl;
    puts stdout "numero de porte : " nonewline;
    flush stdout; gets stdin porte;
    makePoint p; # creer un point p
    p configure -x 70 -y 30 -c red; # definir position et couleur du point
    p draw; # afficher le point
    dp_MakeRPCServer $porte ; # creer serveur pour les points
    dp_SetTrigger after p x {p draw}; # si x change, réafficher point
    dp_SetTrigger after p y {p draw}; # si y change, réafficher point
    dp_SetTrigger after p c {p draw}; # si c change, réafficher point

    fichier point-client.tcl

    package require dp
    source point-class.tcl;
    source graphique.tcl;
    puts stdout "machine serveur : " nonewline;
    flush stdout; gets stdin hote;
    puts stdout "numero de porte : " nonewline;
    flush stdout; gets stdin porte;
    # appel du serveur; server est l'identite' sous laquelle le client
    # connait le serveur pour les appels futurs

    set server [dp_MakeRPCClient $hote $porte];

    # on recupere dans la variable my_Id l'identification du canal de
    # communication etablie cote' serveur (valeur de dp_rpcFile)
    # my_Id est donc l'identite' sous laquelle le serveur connait le client

    set my_Id [dp_RPC $server set dp_rpcFile];

    # le client demande au serveur de lui distribuer un objet
    # de nom p construit par makePoint

    dp_RPC $server eval dp_DistributeObject p $my_Id makePoint;
    p draw; # dessiner le point
    dp_SetTrigger after p x {p draw}; # si x change, redessiner point
    dp_SetTrigger after p y {p draw}; # si y change, redessiner point
    dp_SetTrigger after p c {p draw}; # si c change, redessiner point

    fichier graphique.tcl

    # construction graphique tres simple (visualiser un point)
    package require dp
    canvas .c;
    pack .c; # cree un espace pour le dessin graphique

    # procedure qui dessine le point de coordonnees x, y
    # comme un petit carre' de couleur " couleur "

    proc dot {x y couleur} {

    global .c
    set r 2
    #calculer coordonnees point inf. gauche et pt sup droit
    set xinfg [expr $x - $r] ; set yinfg [expr $y - $r]
    set xsupd [expr $x + $r] ; set ysupd [expr $y + $r]
    .c create rectangle $xinfg $yinfg $xsupd $ysupd -fill $couleur
    }