Choisissez votre projet de majeure 2...
...en système!
Choisissez votre projet de majeure 2...
...en système!
Cette page pourra être mise à jour en apportant éventuellement des
précisions sur les projets qui seront effectivement choisis.
La majeure 2 comporte un projet obligatoire
pour tous. Ce projet a lieu dans l'un au choix des cours enseignés.
Cette page décrit les projets rattachés au cours système.
Déposez votre projet avant le dimanche 2 avril, 18 heures.
Vous pourrez en rédéposer une nouvelle version ultérieursement (jusqu'à la
soutenance)
Il n'est pas demandé de faire un rapport détaillé, mais d'inclure un fichier
README expliquant, en ASCII, succinctement votre projet, son
architecture, comment le tester, etc. (par exemple 50 à 200 lignes).
De façon cohérente avec le cours, le langage de programmation recommandé est
OCaml, ce qui n'exclut pas l'utilisation de programmes en C liés avec le
programme principal écrit en OCaml.
Il est aussi envisageable que certains projets puissent être faits
entièrement en C, mais avec accord préalable, afin de vérifier que votre
projet se prête suffisamment à l'utilisation exclusive de C, que vous avez
les compétences nécessaires en C et que vous connaissez déjà OCaml (i.e. que
ce n'est pas une fuite pour ne pas apprendre OCaml...).
Le binômage
Le binômage est (pour l'instant) déconseillé pour les projets de majeure 2.
Il ne pourra être accepté qu'exceptionnellement, avec accord préalable.
La commande rsh pour remote shell permet depuis
une machine A d'exécuter des commandes sur une machine distante B. La
commnade rcp permet de transférer des fichiers entre une machine locale A
et une machine distante B.
On se propose d'écrire un service similaire rcaml permettant
à un programme OCaml tournant sur une machine A d'éxécuter des
appels systèmes sur une machine B distante et de se servir de ce
mécanisme pour implémenter rcp en OCaml.
Le programme consistera en une librairie utilisable par un client sur la
machine A pour effectuer des appels sur une machine distante B
et un serveur de requêtes que l'on lancera sur la machine distante B.
Les commandes permises seront pré-définies par la librairie (utilisée à la
fois par le client et le serveur). Le serveur devra authentifier le
client. Pour simplifier, le serveur s'exécuterasur le compte d'un
utilisateur uB sur la machine B et il authentifiera le client à chaque
connexion en lui demandant le mot de passe de uB. Plusieurs utilisateurs
pourront donc se connecter à la machine B à condition de connaître le mot
de passe de l'utilisateur du service.
Les commandes permises devront comporter au minimum celles permettant
d'explorer et de modifier la hierarchie de fichiers et celles permettant de
lancer un programme sur la machine distante.
Comme application, on utilisera rcaml pour fournir une implémentation
de rcp réalisant l'échange de fichiers entre la machine A et la machine
B avec, comme pour rcp la possibilité de préserver les permissions et
les dates de modification ainsi que les copies récursives.
La commande rsync permet la copie récursive de fichiers entre machines
distantes (reliées par une connexion relativement lente) de façon efficace.
L'idée principale est de limiter le transfert entre les deux machines aux
données qui diffèrent. Comme première approximation, on peut avant de faire
le transfert d'un fichier de la machine A vers la machine B comparer les
clés de hash de ce fichier (par exemple MD5, implanté par le module Digest
de Ocaml) sur les machines A et B et
ne copier le fichier que si ces clés diffèrent. Afin de bien se comporter
également sur de gros fichiers, par exemple des bases de données, on peut
raffiner cette méthode en découpant le fichier en blocs et en prenant le
bloc plutôt que le fichier comme unité de transfert. On pourra également
utiliser des coprocessus pour permettre au processeurs d'effectuer des
calculs pendant les attentes dues aux accès disques.
La copie devra préserver les droits et dates d'accès. Par défaut, on
préservera les liens durs et on ne suivra pas les liens symboliques. On
implantera également un mode qui permette optionnellement de retirer dans la
destination les fichiers qui ne sont pas dans la source.
Il s'agit d'écrire un proxy HTTP permettant de relayer les requêtes
des clients vers les serveurs destinataires. Le proxy pourra être
instrumenté pour «cacher» les réponses aux requêtes les plus récentes et les
resservir directement sans interroger le serveur, ou seulement si elles ont
été modifiées depuis le dernier chargement. On utilisera le protocole
HTTP/1.1 (mais on n'en couvrira qu'un petit sous-ensemble).
Exemple de ce qui est attendu
Le proxy sera implanté avec des processus ou des coprocessus. Traiter les
requêtes GET avec la possibilité de vérifier si le document a changé
depuis une certaine date.
Implémenter un cache des requêtes les plus récentes.
Pour rendre le proxy plus rapide, on pourra maintenir une « piscine » de
coprocessus déjà lancés et tout prêts à traiter une nouvelle requête.
On pourra ajuster le nombre de coprocessus en fonction de la charge du
serveur.
Donner un mode de fonctionnement qui permette de transformer le proxy en
un serveur HTTP.
Il s'agit de faire une implémentation du partage de fichiers sur le
modèle de Bit-Torrent:
un serveur centralisé (le tracker) maintient, pour chaque fichier
(identifié globalement par un numéro supposé unique), la liste des
machines qui l'ont contacté au sujet de ce fichier.
Un client peut désirer soit offrir le fichier (s'il le possède
intégralement), soit le télécharger. Dans les deux cas, il contacte le
tracker, reçoit la liste des autres clients et les contacte tous en
parallèle. Le client maintient une bitmap (tableau de bits) indiquant
les blocs du fichier (on prendra une taille de bloc telle qu'un
fichier n'en contient jamais plus de 1000) qu'il possède déjà, qu'il
compare avec celle des autres clients pour savoir quels blocs il peut
télécharger depuis chacun d'entre eux.
Un certain nombre d'améliorations pourront être facultativement ajoutées:
Une version simple du programme téléchargera chaque bloc depuis
un seul client. Il devra alors supporter que ce client tombe en panne
avant la fin du téléchargement du bloc, et être capable alors de
re-télécharger le bloc depuis un autre client. Une version beaucoup
plus difficile pourra pourra télécharger un même bloc depuis plusieurs
clients, sans télécharger deux fois la même chose.
Chaque client doit être capable non seulement de télécharger des
données depuis les autres clients, mais aussi de fournir ces données
aux autres clients. Une version simple du programme pourra accepter de
transmettre des données vers tous les autres clients, tandis que des
versions plus difficiles pourront limiter le nombre de clients
auxquels des données sont transmises (1) en utilisant une file
d'attente simple (2) en évaluant périodiquement la quantité de données
reçues depuis chaque client, et en servant d'abord les clients les
plus généreux.
Une version simple du programme pourra télécharger un fichier en
une exécution. Néanmoins, pour de gros fichiers, et sur des réseaux
plus petits, un téléchargement peut prendre plus de temps, et il peut
être nécessaire d'interrompre le téléchargement pour le reprendre plus
tard. Une amélioration pourra donc consister à sauvegarder l'état du
téléchargement pour permettre de le reprendre ultérieurement.
Après qu'un bloc a été téléchargé, il peut être utile de
vérifier que le téléchargement s'est bien passé. Pour cela, on pourra
par exemple calculer une checksum très simple sur chaque bloc (on
pourra utiliser le module Digest d'Ocaml en particulier), et
permettre de re-télécharger un bloc dont la checksum est erronée. On
pourra aussi transmettre toutes ces informations au tracker, afin
qu'elles soient diffusées à tous les clients.
Le but de ce projet est de programmer un système de sauvegarde incrémental
des données d'un répertoire. Un serveur de sauvegarde stocke sur un disque
des données importantes pour d'autres ordinateurs. Sur chaque ordinateur
client, un programme est lancé périodiquement pour parcourir les répertoires
à sauvegarder, tester quels fichiers ont été créés ou modifiés, puis
transmettre ces fichiers au serveur de sauvegarde. Un autre programme permet
ensuite de restaurer l'état d'un fichier ou répertoire tel qu'il était à une
date donnée, depuis le serveur de sauvegarde.
Le système consiste donc en 3 programmes:
Le serveur de sauvegarde: il stocke les fichiers reçus des
clients, en fonction de leur machine d'origine, de leur position dans
l'arborescence de cette machine, et de leur date de
création/modification.
Le client de sauvegarde: il parcourt les répertoires à sauvegarder,
transmet les dates de création/modification des fichiers au serveur de
sauvegarde. Celui-ci lui indique alors quels fichiers doivent lui être
transférés pour être sauvegardés.
Le client de restauration: il prend en argument un nom de fichier
ou de répertoire et une date (on peut omettre la date, ce sera alors
la dernière version du fichier qui sera restaurée), et interroge le
serveur de sauvegarde pour recevoir la sauvegarde demandée de ce
fichier, si celle-ci existe.
Des extensions pourront ensuite être étudiées, en particulier la
tolérance aux pannes (crash du serveur ou des clients, qui ne doivent
pas entrainer de perte de données) ou l'utilisation de plusieurs
serveurs de sauvegarde par un même client, pour augmenter la
disponibilité des sauvegardes.
Dans le Devoir Maison de l'an dernier, on a
significativement simplifié la réalité en ne
permettant pas la concurrence des accès à la librairie.
Ce projet consiste à reprendre le DM de façon plus ambitieuse et plus
complète. On simulera toutjours le disque par un fichier Unix, la machine
par le système. Mais maintenant le système sera modélisé par un coprocessus
(thread), et les processus seront simulés par des coprocessus. Ainsi,
plusieurs coprocessus pourront faire appel à notre système de fichiers en
parrallèle. Cela obligera à gérer les accès au cache de façon plus fine en
utilisant des verrous. La partie essentielle sera donc l'écriture d'un vrai
cache.
Pour une implémentation plus réaliste que dans le DM, on implémentera
également les blocs d'indirections. On pourra alors reproduire la plupart
des situations que l'on rencontre dans un vrai système de fichiers:
Lectures/modification de la hiérarchie par deux processus travaillant en
parallèle. On pourra également observer le fonctionnement du cache en
temporisant les lectures/écritures entre le cache et le fichier pour
modéliser le coût des accès au disque.
Vous pouvez proposer un projet personnel. C'est bien sûr sous-réserve
d'approbation. Il faut en particulier, que le projet rentre bien dans le
cadre du cours système, qu'il soit intéressant d'un point de vue système et
aussi (en fait surtout) pas trop ambitieux afin que vous puissiez le mener à
terme dans un temps finalement assez court.