Gestion d'une bibliothèque

Projet BIB-CCI

Projet L&P - DESS CCI  1999-2000
Sara Bouchenak - Edmond Boyer - Fabienne Dechamboux - Christian Lenne
 
 
 
 

1. Présentation générale du stage

Le stage a pour objectif la réalisation d'un logiciel de gestion d'une bibliothèque, appelé BIB-CCI.  Il se déroule sur une période bloquée durant laquelle votre présence est obligatoire. Il sera réalisé par équipes de 3 personnes.
Le stage sera évalué sur les aspects suivants : Ces aspects seront évalués lors d'une démonstration d'environ 15 minutes qui sera effectuée par chaque équipe en fin de stage. Cette démonstration permettra de tester l'application et de présenter une synthese du stage (difficultés rencontrées, organisation mise en oeuvre dans la répartition des taches, choix de programmation effectués, etc).
En outre, il est demandé de laisser un accès en lecture au code source de votre projet.  Enfin, il est également demandé de rendre un document d'utilisation (1 ou 2 pages) précisant quelles sont les commandes et les options permettant de manipuler l'application BIB-CCI.
 
 

2. Présentation générale du projet BIB-CCI

La bibliothèque que l'on souhaite informatiser comporte un ensemble d'adhérents  (personnes membres de l'association bibliothécaire), et gère un ensemble de livres.  Pour chaque livre, il peut exister plusieurs exemplaires, sans dépasser une limite fixée, soit NMex (nombre maximum d'exemplaires). Cette limite est la même pour tous les livres.
L'emprunt d'un livre par une personne n'est possible que si les règles suivantes sont toutes respectées : Pour gérer les prêts de la bibliothèque, on considère deux ensembles d'informations, la catalogue des livres et le répertoire des adhérents.
Le catalogue décrit l'ensemble des livres acquis par la bibliothèque. Deux livres distincts diffèrent par leur titre et / ou par leur auteur.  Pour chaque livre, on dispose des informations suivantes : Le nombre total de livres , ainsi que le nombre total d'auteurs de livres gérés par la bibliothèque, sont a priori illimités. L'ajout de nouveaux livres est une opération relativement courante, au contraire de la suppression. Par ailleurs, on souhaite pouvoir accéder aux éléments du catalogue selon un auteur, ou bien un titre donné.

Le répertoire décrit les adhérents de l'association. Deux adhérents distincts doivent avoir au moins un attribut qui diffère parmi les trois suivants : nom, prénom et adresse. L'emploi de numéros d'adhérents (identificateurs uniques) devra permettre de distinguer simplement les adhérents. Pour chaque adhérent, on dispose des informations suivantes :

 Le nombre total de d'adhérents gérés par la bibliothèque est limité a NMAdh.  L'ajout et le retrait d'adhérents sont des opérations courantes, de même que la consultation des livres empruntés par un adhérent. On considère qu'une personne peut emprunter plusieurs exemplaires d'un même livre.
 
 

3 Représentation et manipulation des informations

On essaiera de représenter les informations à l'aide des mécanismes de structuration fournis par le langage C qui sont le plus adéquat en fonction des caractéristiques des données à gérer, énoncées en 2. L'organisation modulaire du programme de gestion de la bibliothèque devra cependant permettre de réaliser un développement incrémental, au cours duquel on pourra utiliser des structures de données temporaires. En outre, lorsque des fonctions identiques sont requises en divers points du programme, on veillera à regrouper celles-ci dans un même module.

Les fonctions principales qui sont attendues sont décrites ci-après. L'ensemble de ces fonctions constitue la partie visible de l'application BIB-CCI, qui sera accessible aux utilisateurs au travers d'une interface graphique (voir 5).
Il peut être intéressant d'étoffer cet ensemble de fonctions pour offrir des capacités additionnelles, telles que la possibilité pour la bibliothèque de conserver l'historique des emprunts dans un fichier, et de réaliser des statistiques sur les demandes des adhérents.
 

 

4 Propriétés de l'application de gestion de la bibliothèque

4.1 Persistence des données

Les données manipulées par l'application BIB-CCI sont de nature persistente, c'est à dire qu'elles doivent survivre à l'exécution de l'application. Pour assurer la persistence de ces données, nous proposons de les sauvegarder dans des fichiers Unix. Le principe consiste alors à restaurer (c'est à dire charger) ces données depuis leur sauvegarde lors du lancement de l'application.  Nous supposerons qu'au lancement de l'application BIB-CCI, la totalité des données, c'est à  dire la base complète, est chargée en mémoire.
 

Un choix doit être fait pour décider des moments auxquels auront lieu la sauvegarde des données sur disque. Plusieurs politiques sont possibles :

Dans tous les cas, la persistence des données implique de mettre en oeuvre deux nouvelles fonctions : sauver_donnees, et restaurer_donnees.

4.2 Cohérence des données garantie en présence de panne

Les données manipulées par l'application BIB-CCI sont supposées être cohérentes. Par exemple, le nombre d'exemplaire libre d'un livre donné doit être cohérent par rapport aux emprunts qui ont été effectués de ce livre. L'application doit déja assurer que, sans la présence de pannes, les données qu'elle manipule sont cohérentes.

On souhaite garantir la cohérence des données même en présence de pannes. Ceci signifie que, si une panne provient à un instant t, alors la derniere sauvegarde des données doit être récupérable. Pour ce faire, l'opération de sauvegarde des données sur disque doit garantir la propriété d'atomicité :

Le principe de mise en oeuvre d'une sauvegarde atomique est le suivant. Soit un fichier pour lequel on souhaite effectuer des sauvegardes atomiques. Autrement dit, on veut réaliser une fonction atomic_save(données, fichier), qui garantit que, à l'issue de la fonction : Pour ce faire, diverses méthodes sont envisageables, et on pourra essayer d'en imaginer quelques unes. Une méthode simple consiste à effectuer la sauvegarde dans un fichier temporaire (f.bak par exemple), et à utiliser ensuite la commande mv d'Unix (cette commande est atomique) pour copier ce fichier temporaire dans le fichier de sauvegarde. On utilisera la fonction system du langage C pour appeler la commande mv depuis un programme C.

Ces principes de mise en oeuvre pourront être utilisés au niveau des fonctions de sauvegarde et de restauration pour garantir la cohérence des données de l'application BIB-CCI même en présence de pannes.
 

4.4 Gestion de la reprise après panne

Lorsqu'une panne arrive à un instant t, il existe une sauvegarde disponible (voir section précédente). Cependant, le travail effectué sur les données entre la date à laquelle a été réalisée la derniere sauvegarde et le moment auquel a lieu la panne est perdu. Nous dirons que l'application fournit une procédure de reprise après panne si elle fournit un moyen qui permet de récupérer le travail effectué entre la derniere sauvegarde et l'instant auquel a lieu une panne.

Un moyen simple, mais très peu efficace, de fournir cette propriété consiste à obliger l'utilisateur à provoquer une sauvegarde après chaque modification des données. On réfléchira à d'autres moyens plus performants, tels que par exemple l'utilisation d'un journal comme expliqué ci-après.

Un journal est un fichier qui contient des informations sur les modifications effectuées sur les données depuis leur dernière sauvegarde.  Soit E1 l'état initial des données lorsque l'utilisateur lance l'application BIB-CCI. Supposons que ce dernier effectue une série d'opérations Op1, .. , Opn sur les données, et qu'une panne apparaisse durant l'opération Opn. Supposons également que l'état des données en mémoire à la suite de l'opération Opn-1 soit E2.

Les informations contenues dans un journal doivent être suffisantes pour pouvoir rétablir les données dans l'état E2. Pour ce faire, on écrira dans le journal les états des seules données modifiées (personnes, livres) par les opérations effectuées.  Lorsque l'utilisateur souhaite effectuer une sauvegarde de la base, deux cas sont possibles :

Plus précisement, voici un déroulement possible pour une utilisation de l'outil BIB-CCI :
 
Session de travail avec BIB-CCI: 
             Ecrire dans le journal : start_session  
             Op1 
             Ecrire dans le journal les données modifiées par Op1 
             Op2 
             Ecrire dans le journal les données modifiées par Op2 

             ... 
             Opn 
             Ecrire dans le journal les données modifiées par Op1 

             Effectuer une sauvegarde atomique de la base 
             Ecrire dans le journal : end_session

 

 
La session de travail commence toujours par l'écriture dans le journal du mot-clé start_session, indiquant qu'une nouvelle session de travail avec l'application BIB-CCI démarre. Ensuite, chaque opération effectuée par l'utilisateur provoque la sauvegarde de l'état des données modifiées dans le journal. Enfin, lorsque la session de travail se termine, une sauvegarde de la base est effectuée. Si tout se passe bien, le mot-clé end_session est écrit dans le journal. En cas de panne :

La procedure de reprise est la suivante : Toute panne survenant durant la procédure de reprise provoquera à nouveau l'exécution de la procédure de reprise.
 

5 Mise en oeuvre de l'interface utilisateur du systeme de gestion de la bibliothèque

La partie gerant l'interface utilisateur de l'application est fournie aux etudiants. Cette partie utilise un langage de script appelé Tcl-TK permettant de réaliser une interface graphique simple et rapide. Bien qu'il ne soit pas necessaire de comprendre le fonctionnement de l'interprete, nous donnons ci-apres le schema de principe de ce fonctionnement pour information.
Dans la partie fournie, vous trouverez les fichiers suivants : Pour lancer l'application, il faut taper bib_cci bib_cci.tk
 

Principe de fonctionnement de TK
La communication entre un programme C et un script Tcl-TK permet d'ajouter au programme C une interface graphique programmée en Tcl-Tk. Le schéma d'interaction entre la partie interface en Tcl-Tk, et la partie du programme écrite en C est le suivant :
 

Les composants (modules) écrits en C comportent une partie d'initialisation (module définissant la fonction main), ainsi qu'une partie qui contient les fonctions et procédures constituant l'application proprement dite. Le module d'initialisation a une structure standard, donnée ci-après : Pour illustrer cette structure, voici un exemple très simple dans lequel l'application écrite en C imprime le carré d'un nombre saisi dans une fenetre. Le programme C comporte une seule fonction square, que l'on associe à  une commande Tcl-Tk appelée square_com (autrement dit, lorsque l'interprete Tcl_Tk appelle la commande com_Square, alors automatiquement la fonction Square est appelee et les parametres sont transmis).
Les paramètres des commandes Tcl, et donc également ceux des fonctions C auxquelles sont associées les commandes Tcl, sont forcément des chaines de caractères. Pour transformer ces chaines en d'autres types (entier, réél, etc), on utilisera les fonctions de la librairie C (atoi, atof, etc).

Dans l'exemple suivant, nous ne prenons pas en compte le traitement des erreurs :
 
/* module C : square.c */                                                                              square.h 
#include <stdio.h>                                                                                           extern int square... 
#include<stdlib.h> 
#include<tcl.h> 
 

int square (ClientData clientData, 
                       Tcl_Interp *interp, 
                       int argc, char *argv[]) { 
   double v; 
    if (argc != 2) return TCL_ERROR; 
    v = atof(argv[1]); 
    sprintf(interp->result, "%.5f", v*v);       /* pour communiquer un résultat depuis C vers Tk */ 
    return TCL_OK; 
}

Le module principal est donné ci-dessous :
 
/* module C : square_main.c */ 
#include <tk.h> 
#include "square.h" 

long main (int argc, char * argv[]) { 
       Tk_Main(argc, argv, Tcl_AppInit); 
        exit(0); 
} 
 

int Tcl_AppInit(Tcl_Interp *interp) {   /*  Tcl-AppInit est appelée par Tk_Main */ 
  if (Tcl_Init(interp) == TCL_ERROR)     /* avant l'entrée dans la boucle d'attente  */ 
        return TCL_ERROR; 
  if (Tk_Init(interp) == TCL_ERROR)  
        return TCL_ERROR; 
  
  /* association entre commandes Tk et fonctions C */ 
  Tcl_CreateCommand(interp,  
                                             "square_com",    /* associe la cde square_com a la fonction square */ 
                                             square,  
                                             (ClientData)Tk_MainWindow(interp),  
                                             (Tcl_CmdDeleteProc *)NULL); 
  ... 
   RETURN TCL_OK; 
}

Le script Tk est le suivant :
 
label .l -text "Entrez un nombre"                       creation label 
entry .e -textvariable val                                      creation zone de saisie 
pack .l .e -side left                                                  affichage 
bind .e <Return> {square_com $val}                appel commande square_com 
bind .e <Control-C> {exit}
 

L'application est compilée par :

6. Etapes de réalisation

On distingue trois parties principales dans la réalisation de l'application BIB-CCI, parties qui peuvent être implantées et testées séparément dans un premier temps, puis intégrées ensuite. L'intégration comportera des tests d'intégration, permettant de valider l'ensemble de l'application.
 

7.1 Manipulation des données bibliothécaires

Cette partie consiste à définir les structures de données utilisées, et à implanter les fonctions de manipulation des données de la bibliothèque énoncées en X. Bien entendu, il est possible de réaliser des fonctions additionnelles dont l'utilité sera jugée pertinente. La gestion des dates (accès à la date courante, calcul de la date de retour d'un livre, etc) utilisera les fonctions fournies par la librairie C (fonction gettimeofday par exemple).
 

7.2 Gestion des sauvegarde de la base

Cette partie consiste tout d'abord à réaliser les fonctions de sauvegarde et de restauration des données, depuis ou vers des fichiers.  Cette première étape implique de définir les formats de stockage des données sur disque (organisation en fichiers, contenu des fichiers), ainsi qu'à implanter les fonctions de translation des données en mémoire vers des données persistentes, et inversement.
Il s'agit ensuite de rendre l'opération de sauvegarde des données sur disque atomique, selon les principes énoncés en 4.
 

 
7.3 Procédure de reprise après panne
Enfin, et si le temps le permet, on cherchera à fournir une procédure de reprise après panne en gérant un journal comme indiqué en 4. Pour tester la procédure, on utilisera le signal Ctrl-C, qui permet d'interrompre un processus Unix dans son exécution.