-
Notifications
You must be signed in to change notification settings - Fork 0
/
rapport.tex
208 lines (148 loc) · 10.9 KB
/
rapport.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
\documentclass[a4paper,12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[francais]{babel}
\usepackage{graphicx}
\usepackage[left=3cm,right=3cm,top=4cm,bottom=4cm]{geometry}
\pagestyle{plain}
\title{Projet de Systèmes Concurrents}
\author{Jorge Gutierrez \& Grégoire Martini}
\date{25 Janvier 2016}
\begin{document}
\maketitle
\bigskip
\bigskip
\bigskip
\tableofcontents
\newpage
\section{Etape 1}
On doit implanter le service de gestion d'objets partagés répartis. Dans cette première version, les
SharedObject sont utilisés explicitement par les applications. \\
Plusieurs applications peuvent accéder de façon concurrente au même objet, ce qui nécessite de mettre en
œuvre un schéma de synchronisation globalement cohérent pour le service que l'on implante.
On suppose que chaque application voulant utiliser un objet en récupère une référence (un SharedObject) en
utilisant le serveur de nom. On ne gère pas le stockage de référence à des objets partagés dans des objets partagés pour l'instant.
\subsection{Coté client}
\bigskip
\subparagraph{La classe Client}
\smallskip
\subparagraph{init}
Initialise la connexion avec le serveur.
\subparagraph{lookup}
Retourne la référence à l'objet partagé, null si il n'existe pas.
\subparagraph{register}
Enregistre un nouvel objet partagé dans le serveur.
\subparagraph{create}
Crée un nouvel objet partagé.
\subparagraph{lock\_read}
Demande le verrou en lecture d'un objet partagé.
\subparagraph{lock\_write}
Demande le verrou en écriture d'un objet partagé.
\subparagraph{reduce\_lock}
Réduit le verrou d'un objet partagé.
\subparagraph{invalidat\_reader}
Supprime le verrou en lecture d'un objet partagé.
\subparagraph{invalidate\_writer}
Supprime le verrou en écriture d'un objet partagé.
\bigskip
\subparagraph{La classe SharedObject}
contient trois attributs:
\begin{itemize}
\item[- une énumération représentant l'état de l'objet]
\item[- l'état actuel de l'objet]
\item[- l'identifiant unique de l'objet partagé]
\end{itemize}
\subparagraph{lock\_read}
Gère la demande de verrou en lecture sur l'objet partagé en fonction de l'état actuel.
\subparagraph{lock\_write}
Gère la demande de verrou en écriture sur l'objet partagé en fonction de l'état actuel.
\subparagraph{reduce\_lock}
Gère la demande de réduction de verrou en lecture sur l'objet partagé en fonction de l'état actuel.
\subparagraph{invalidate\_reader}
Gère la demande d'invalidation de verrou en lecture sur l'objet partagé en fonction de l'état actuel.
\subparagraph{invalidate\_writer}
Gère la demande d'invalidation de verrou en écriture sur l'objet partagé en fonction de l'état actuel.\\
La gestion de la synchronisation est garantie par l'exclusion mutuelle des call-backs du serveur (méthodes synchronized) et l'utilisation du moniteur java sur l'objet et ses méthodes wait et notify.
\bigskip
\bigskip
\subsection{Coté serveur}
\bigskip
\paragraph{La classe Server}
contient trois attributs:
\begin{itemize}
\item[- un entier qui est l'identifiant unique retourné pour chaque SharedObject]
\item[- une HashMap qui lie les ServerObject à leur identifiant]
\item[- une HashMap qui lie les identifiants des ServerObject à leur nom]
\end{itemize}
\smallskip
\subparagraph{lookup}
Permet de récupérer l'identifiant d'un objet partagé en fonction de son nom.
\subparagraph{register}
Enregistre le lien entre l'identifiant d'un objet partagé et son nom.
\subparagraph{create}
Crée un nouvel objet partagé et retourne son identifiant.
\subparagraph{lock\_read}
Passe la demande de lock\_read au ServerObject correspondant.
\subparagraph{lock\_write}
Passe la demande de lock\_write au ServerObject correspondant.\\
La méthode principale initiale la connexion distante et enregistre le serveur dans le serveur de nom.
\bigskip
\paragraph{La classe ServerObject}
contient cinq attributs:
\begin{itemize}
\item[- une énumération représentant l'état de l'objet]
\item[- l'état actuel de l'objet]
\item[- la liste des clients en lecture]
\item[- le client en écriture]
\item[- l'identifiant unique de l'objet partagé]
\end{itemize}
\smallskip
\subparagraph{lock\_read}
Permet d'ajouter un client en lecture tout en s'assurant qu'il n'ai pas de client en écriture. Appel reduce\_lock sur le client en écriture pour s'en assurer.
\subparagraph{lock\_write}
Permet de passer un client en lecture tout en s'assurant qu'il n'y ai pas de client en lecture ou en écriture.\\
Appel invalidate\_writer sur le client en écriture et crée un thread qui appel invalidate\_reader sur chaque client dans la liste des lecteurs pour une gestion efficace de la cohérence.\\
Les deux méthodes sont synchronized ce qui garanti leur exécution en exclusion mutuelle et évite le croisement d'appels comme illustré dans le sujet.\\
\bigskip
\bigskip
L'application a été testée en modifiant Irc afin de séparer les lock et les unlocks (ajout d'un bouton) et la classe Test qui permet de stresser le serveur quand on en lance plusieurs instances. \\
Si l'application client imbrique les locks sur un même objet, le SharedObject lève l'exception NestedLocksException et les interblocages ne sont pas gérés.\\
\clearpage
\section{Etape 2}
\bigskip
\bigskip
Dans l’étape deux, on a implanté le service de transaction aux objets dupliqués de la façon suivante:\\
Dans la Transaction on stocke trois listes (HashMap), une liste pour les SharedObjects lus, une liste pour les SharedObjects écrits et une liste des Objects qui ont été modifiés au cas où l’application fasse abort. Il y a aussi un boolean pour indiquer si la transaction est active et un boolean pour indiquer si l’application a appelé commit ou abort. Finalement, la Transaction a un attribut static transaction qu'on va envoyer chaque fois que SharedObjet appelle getCourrentTransaction. \\
Par conséquent on est obligé d'ajouter les fonctions addObjectRead(), addObjectWrite(), addMemoire() qui ajoutent les SharedObjects et les Objects avec leur ID dans leur liste respective. Le hasbeenModified() a été ajouté afin de savoir si c’est la première fois que l’objet est modifié et le garder dans la mémoire. Le commitDone() a pour but de réinitialiser la variable commitvalide une fois que l’abort est exécuté. \\
En sachant que l’application gérera la Transaction seulement avec les méthodes start(), commit() et abort(), on a modifié la classe SharedObject en ajoutant la méthode static getCurrentTransaction() pour récupérer la même transaction dans autre interface, ainsi le traitement de lockwrite(), lockread et unlock() pourront dans cette classe vérifier si la transaction est active.\\
À l’intérieur du lock() on vérifie si l’application est en mode transactionnel avec isActive() et on appelle addObjectWrite() ou addObjectRead() selon la méthode. Si l’application modifie l’objet on garde sa valeur en faisant un clonage Byte à Byte de celui-ci grâce à la méthode deepClone qui utilise la serialisation. \\
Puis pour la fonction unlock() on regarde si la transaction n’est pas active pour libérer le verrou ou si l’objet n’a pas été modifié, sinon on ne le libère pas. Dans le cas où l’application appelle abort on retourne l’objet à l’état avant modification.\\
Pour tester la fonctionnalité de transaction on a mis des boutons dans Irc pour appeler start, commit et abort, en assurant qu’on ne verrouille pas l’objet tant que la transaction est active. \\
On a aussi crée une classe Tests qui permet de stresser la transaction. Elle crée le nombre de ClientsTest passé en paramètre et ces derniers exécutent en mode transactionnel le nombre d'actions sur le nombre d'objets définis dans Tests.
\clearpage
\section{Etape 3}
\bigskip
\bigskip
On doit implanter un générateur de stub, destiné à soulager le programmeur de l'utilisation explicite des SharedObject. \\
Le générateur de stub est la classe StubGenerator.\\
La classe métier et l'interface de l'objet à partagé doivent être fournis par le programmeur.\\
Le stub étends la classe SharedObject et implémente l'interface de l'objet à partager ainsi que la classe Serializable.
Il contient un constructeur qui est celui de SharedObject et l'ensemble des méthodes publiques de la classe métier.
Il gère aussi les annotations @Read and @Write qui permettent de soulager le programmeur de la gestion explicite des verrous sur l'objet partagé dans son application. Il lui suffit d'annoter les méthodes de la classe métier selon qu'elles modifient (@Write) ou utilisent simplement l'état (@Read) de l'objet. \\
On utilise la classe File qui permet de créer un nouveau fichier et la classe FileWriter qui permet d'écrire dans un fichier. Le code générer est stocké dans un StringBuffer avant d'être écrit dans le fichier.\\
Toute l'architecture du stub est écrite dans des chaines de caractères statique et seules les parties dépendantes de la classe dont on génère le stub telles que le nom des méthodes ou des paramètres est récupérés au moment opportun.\\
On utilise l'introspection de Java pour accéder à la classe métier. Attention, l'utilisation de la méthode getParameter pour récupérer les paramètres d'une méthode nécessite l'utilisation de Java 8.\\
Lorsque le client à besoin du stub d'un objet, il utilise la méthode getStub en passant la classe de l'objet dont il veut le stub en paramètre et la méthode lui renvoi la classe du stub. Le code du stub est ainsi généré et compilé à la volée et instancié par le client de façon transparente pour le programmeur. Le stub n'est généré que si une classe nomdeclasse\_stub n'existe pas déjà pour éviter de créer un source et le compiler à chaque fois que l'on demande un stub. Si l'on modifie l'objet, il faut donc supprimer son stub pour qu'un nouveau soit généré au prochain appel.\\
Une méthode a été ajoutée à la classe Server pour récupérer la classe de l'objet partagé afin de créer le bon stub lors de l'appel de la méthode lookup dans la classe Client.\\
Si la compilation échoue, le StubGenerator lève l'exception CompilationFailedException.
\clearpage
\section{Etape 4}
\bigskip
\bigskip
\bigskip
\bigskip
On désire prendre en compte le stockage de référence à des objets partagés dans des objets partagés.\\
Il s'agit de spécialiser la méthode readResolve dans la classe SharedObject pour que lorsqu'un SharedObject est désérialisé dans le client (ce qui arrive uniquement lorsqu'il est lui même contenu dans un objet partagé) il soit remplacé par le stub local correspondant.\\
La méthode lookup a été surchargée dans la classe Client afin de rendre le stub de l'objet partagé non pas en fonction de son nom mais de son identifiant.\\
L'étape a été testée en modifiant Irc pour utilisée un Sentence\_cx qui contient un Sentence et vérifier l'installation du stub en local lorsque l'on récupère l'objet partagé.
\end{document}