From dbebe02bdfd69ac6d764489394af6b01e9d691c9 Mon Sep 17 00:00:00 2001 From: smas Date: Fri, 28 Jul 2000 15:30:55 +0000 Subject: [PATCH] =?UTF-8?q?Premi=C3=A8re=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/datastr.h | 539 ++++++++ lib/libdatastr.3 | 737 +++++++++++ lib/libdatastr.c | 3071 ++++++++++++++++++++++++++++++++++++++++++++ lib/libdatastr.doc | Bin 0 -> 101888 bytes lib/libdatastr.h | 97 ++ util/dsbench.c | 529 ++++++++ util/dsbench.xls | Bin 0 -> 17408 bytes util/dsdump.c | 51 + 8 files changed, 5024 insertions(+) create mode 100644 lib/datastr.h create mode 100644 lib/libdatastr.3 create mode 100644 lib/libdatastr.c create mode 100644 lib/libdatastr.doc create mode 100644 lib/libdatastr.h create mode 100644 util/dsbench.c create mode 100644 util/dsbench.xls create mode 100644 util/dsdump.c diff --git a/lib/datastr.h b/lib/datastr.h new file mode 100644 index 0000000..453a344 --- /dev/null +++ b/lib/datastr.h @@ -0,0 +1,539 @@ +#ifndef _LIBDATASTR +#define _LIBDATASTR + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Code retour des fonctions constituant l'API */ + +typedef long DST_Status; + +#define DSS_OK SMS_OK /* La fonction s'est correctement exécutée et a produit un résultat */ +#define DSS_KO SMS_KO /* La fonction s'est correctement exécutée mais n'a pas produit de résultat */ +#define DSS_YES SMS_OK /* Résultat booléen positif */ +#define DSS_NO SMS_KO /* Résultat booléen négatif */ + +#define DSS_ERRMEM SMS_ERRMEM /* Problème d'allocation mémoire */ +#define DSS_ERRAPI SMS_ERRAPI /* Utilisation incorrecte des API */ +#define DSS_ERRSHM SMS_ERRSHM /* Problème relatif aux segments de mémoire partagée */ +#define DSS_ERRSEM SMS_ERRSEM /* Problème relatif à l'utilisation des sémaphores */ +#define DSS_ERRSIG SMS_ERRSIG /* Opération sur sémaphore interrompue par un signal */ +#define DSS_ERRDLL -6 /* Problème de chargement dynamique de librairie */ + +#define DS_ERROR(s) ((s) < 0) /* Tous les codes retour négatifs correspondent à des erreurs */ + +/* Indicateurs */ + +typedef int DST_Flags; + +#define DSD_UNDEF 0 + +/* Flags d'ouverture d'une data structure */ + +#define DSD_OPEN SMD_OPEN /* autorise l'ouverture d'une structure existante */ +#define DSD_CREATE SMD_CREATE /* autorise la création de la structure */ +#define DSD_NEW ~(DSD_OPEN|DSD_CREATE) /* crée une autre structure dans un heap existant */ + +/* Flags de debug sur l'ouverture de la librairie */ + +#define DSD_DEBUG_NONE 0 /* pour n'afficher aucun message généré par les diverses librairies */ +#define DSD_DEBUG 1 /* pour afficher les messages générés par la librairie */ +#define DSD_DEBUG_ALL 2 /* pour afficher les messages générés par toutes les librairies sous-jacentes */ + +/*------------------------------------------------------------------------------*/ +/* Utilisations possibles des flags d'ouverture */ +/*------------------------------------------------------------------------------*/ +/* */ +/* DSD_OPEN */ +/* -> ouvrir une structure existante */ +/* -> ne pas la créer si elle n'existe pas */ +/* */ +/* DSD_OPEN | DSD_CREATE */ +/* -> ouvrir une structure si elle existe */ +/* -> la créer si elle n'existe pas */ +/* */ +/* DSD_CREATE */ +/* -> créer une structure */ +/* -> ne pas l'ouvrir si elle existe déjà */ +/* */ +/* DSD_CREATE | DSD_NEW */ +/* -> créer la structure si elle n'existe pas */ +/* -> créer une autre structure dans le même heap si elle existe déjà */ +/* */ +/* DSD_NEW */ +/* -> créer une autre structure dans le même heap si elle existe déjà */ +/* -> ne pas la créer si elle n'existe pas */ +/* */ +/*------------------------------------------------------------------------------*/ + +/* Flags de verrouillage d'une data structure */ + +#define DSD_READ SMD_READ /* verrou partagé */ +#define DSD_WRITE SMD_WRITE /* verrou exclusif */ + +/* Flags de fermeture d'une data structure */ + +#define DSD_CLOSE SMD_CLOSE /* pour fermer simplement la structure */ +#define DSD_DESTROY SMD_DESTROY /* pour détruire la structure */ + +/* Masques pour récupérer des valeurs combinées */ + +#define DSD_MSK_OPEN(a) (DSD_OPEN & (a)) +#define DSD_MSK_CREATE(a) (DSD_CREATE & (a)) +#define DSD_MSK_NEW(a) (DSD_NEW & (a)) +#define DSD_MSK_READ(a) (DSD_READ & (a)) +#define DSD_MSK_WRITE(a) (DSD_WRITE & (a)) +#define DSD_MSK_RW(a) ((DSD_READ | DSD_WRITE) & (a)) + +/* + On utilise le pointeur 'User' de la racine de la struture pour y + rattacher des données sur le heap sous-jacent. +*/ + +typedef struct { + char * Heap_Name; + char * Manager_FileName; + int OpenSemID; /* Indique le nombre de processus ayant ouvert la struture */ + int Heap_Owner; /* Indique si la structure est propriétaire du heap sous-jacent */ + int Valid; /* Indique si la structure est valide ou non */ +} DST_RootDesc; + +char DS_Error_Msg [512]; + +/* Définition des alias de l'API */ + +#ifndef DS_MODE +#define DS_MODE 0 +#endif + +#if DS_MODE == 2 + +/* + Utilisation des API sans vérification des arguments et sans verrouillage de + des data structures utilisées. + Cette configuration correspond à une utilisation optimisée mais non sécurisée + des API de la librairie. + + Puisque les verrouillages ne sont pas faits systématiquement par les fonctions, + l'utilisateur veillera à verrouiller lui-même les data structures qu'il utilise. +*/ + +# define DS_Library_Open DS_Library_Open_I +# define DS_Library_Close DS_Library_Close_I +# define DS_Library_Stderr_Set DS_Library_Stderr_Set_I +# define DS_DataStruct_Open DS_DataStruct_Open_I +# define DS_DataStruct_Close DS_DataStruct_Close_I +# define DS_DataStruct_Reorg DS_DataStruct_Reorg_I +# define DS_DataStruct_Traverse DS_DataStruct_Traverse_I +# define DS_DataStruct_Convert DS_DataStruct_Convert_I +# define DS_DataStruct_Info_Print DS_DataStruct_Info_Print_I +# define DS_DataStruct_Print DS_DataStruct_Print_I +# define DS_DataStruct_Check DS_DataStruct_Check_I +# define DS_DataStruct_Dump DS_DataStruct_Dump_I +# define DS_DataStruct_Lock DS_DataStruct_Lock_I +# define DS_DataStruct_Unlock DS_DataStruct_Unlock_I +# define DS_Node_Root_Get DS_Node_Root_Get_I +# define DS_Node_First_Get DS_Node_First_Get_I +# define DS_Node_Last_Get DS_Node_Last_Get_I +# define DS_Node_Next_Get DS_Node_Next_Get_I +# define DS_Node_Previous_Get DS_Node_Previous_Get_I +# define DS_Node_Add DS_Node_Add_I +# define DS_Node_Remove DS_Node_Remove_I +# define DS_Node_Find DS_Node_Find_I +# define DS_Value_Alloc DS_Value_Alloc_I +# define DS_Value_Add DS_Value_Add_I +# define DS_Value_Remove DS_Value_Remove_I +# define DS_Value_Free DS_Value_Free_I +# define DS_Alloc DS_Alloc_I +# define DS_Free DS_Free_I + +#elif DS_MODE == 1 + +/* + Utilisation des API sans vérification des arguments mais avec + verrouillage systématique des data structures utilisées. +*/ + +# define DS_Library_Open DS_Library_Open_L +# define DS_Library_Close DS_Library_Close_L +# define DS_Library_Stderr_Set DS_Library_Stderr_Set_L +# define DS_DataStruct_Open DS_DataStruct_Open_L +# define DS_DataStruct_Close DS_DataStruct_Close_L +# define DS_DataStruct_Reorg DS_DataStruct_Reorg_L +# define DS_DataStruct_Traverse DS_DataStruct_Traverse_L +# define DS_DataStruct_Convert DS_DataStruct_Convert_L +# define DS_DataStruct_Info_Print DS_DataStruct_Info_Print_L +# define DS_DataStruct_Print DS_DataStruct_Print_L +# define DS_DataStruct_Check DS_DataStruct_Check_L +# define DS_DataStruct_Dump DS_DataStruct_Dump_L +# define DS_DataStruct_Lock DS_DataStruct_Lock_L +# define DS_DataStruct_Unlock DS_DataStruct_Unlock_L +# define DS_Node_Root_Get DS_Node_Root_Get_L +# define DS_Node_First_Get DS_Node_First_Get_L +# define DS_Node_Last_Get DS_Node_Last_Get_L +# define DS_Node_Next_Get DS_Node_Next_Get_L +# define DS_Node_Previous_Get DS_Node_Previous_Get_L +# define DS_Node_Add DS_Node_Add_L +# define DS_Node_Remove DS_Node_Remove_L +# define DS_Node_Find DS_Node_Find_L +# define DS_Value_Alloc DS_Value_Alloc_L +# define DS_Value_Add DS_Value_Add_L +# define DS_Value_Remove DS_Value_Remove_L +# define DS_Value_Free DS_Value_Free_L +# define DS_Alloc DS_Alloc_L +# define DS_Free DS_Free_L + +#else + +/* + Utilisation des API avec vérification des arguments + et avec verrouillage des data structures utilisées. +*/ + +# define DS_Library_Open DS_Library_Open_CL +# define DS_Library_Close DS_Library_Close_CL +# define DS_Library_Stderr_Set DS_Library_Stderr_Set_CL +# define DS_DataStruct_Open DS_DataStruct_Open_CL +# define DS_DataStruct_Close DS_DataStruct_Close_CL +# define DS_DataStruct_Reorg DS_DataStruct_Reorg_CL +# define DS_DataStruct_Traverse DS_DataStruct_Traverse_CL +# define DS_DataStruct_Convert DS_DataStruct_Convert_CL +# define DS_DataStruct_Info_Print DS_DataStruct_Info_Print_CL +# define DS_DataStruct_Print DS_DataStruct_Print_CL +# define DS_DataStruct_Check DS_DataStruct_Check_CL +# define DS_DataStruct_Dump DS_DataStruct_Dump_CL +# define DS_DataStruct_Lock DS_DataStruct_Lock_CL +# define DS_DataStruct_Unlock DS_DataStruct_Unlock_CL +# define DS_Node_Root_Get DS_Node_Root_Get_CL +# define DS_Node_First_Get DS_Node_First_Get_CL +# define DS_Node_Last_Get DS_Node_Last_Get_CL +# define DS_Node_Next_Get DS_Node_Next_Get_CL +# define DS_Node_Previous_Get DS_Node_Previous_Get_CL +# define DS_Node_Add DS_Node_Add_CL +# define DS_Node_Remove DS_Node_Remove_CL +# define DS_Node_Find DS_Node_Find_CL +# define DS_Value_Alloc DS_Value_Alloc_CL +# define DS_Value_Add DS_Value_Add_CL +# define DS_Value_Remove DS_Value_Remove_CL +# define DS_Value_Free DS_Value_Free_CL +# define DS_Alloc DS_Alloc_CL +# define DS_Free DS_Free_CL + +#endif + +/*------------------------------------------------------------------------------*/ +/* Ouverture d'une instance de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance de la librairie */ +/* (I) Context : nom du contexte */ +/* (I) Debug_Mode : mode d'affichage des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Open_I ( int Instance, const char * Context, \ + DST_Flags Debug_Mode ); +DST_Status DS_Library_Open_L ( int Instance, const char * Context, \ + DST_Flags Debug_Mode ); +DST_Status DS_Library_Open_CL ( int Instance, const char * Context, \ + DST_Flags Debug_Mode ); + +/*------------------------------------------------------------------------------*/ +/* Fermeture de l'instance de la librairie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Close_I ( void ); +DST_Status DS_Library_Close_L ( void ); +DST_Status DS_Library_Close_CL ( void ); + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Stderr_Set_I ( FILE * Out ); +DST_Status DS_Library_Stderr_Set_L ( FILE * Out ); +DST_Status DS_Library_Stderr_Set_CL ( FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Création / ouverture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) DS_Name : nom de la structure */ +/* (O) Root : adresse du pointeur sur la racine de la structure */ +/* (I) Type : type de la structure de données */ +/* (I) Manager_FileName : nom du fichier qui définit les fonctions manager */ +/* (I) Segment_Size : taille ds segments du heap sous-jacent */ +/* (I) Open_Mode : mode d'ouverture de la structure */ +/* (I) Own_Value : indique si la structure possède ses valeurs */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Open_I ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Value ); +DST_Status DS_DataStruct_Open_L ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Value ); +DST_Status DS_DataStruct_Open_CL ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Value ); + +/*------------------------------------------------------------------------------*/ +/* Verrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Lock_Mode : type de verrou à poser sur la structure */ +/* (O) Locked : verrou effectif (TRUE ou FALSE) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Lock_I ( NDT_Root * Root, DST_Flags Lock_Mode, \ + int * Locked ); +DST_Status DS_DataStruct_Lock_L ( NDT_Root * Root, DST_Flags Lock_Mode, \ + int * Locked ); +DST_Status DS_DataStruct_Lock_CL ( NDT_Root * Root, DST_Flags Lock_Mode, \ + int * Locked ); + +/*------------------------------------------------------------------------------*/ +/* Déverrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Unlock_I ( NDT_Root * Root ); +DST_Status DS_DataStruct_Unlock_L ( NDT_Root * Root ); +DST_Status DS_DataStruct_Unlock_CL ( NDT_Root * Root ); + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Close_Mode : mode de fermeture de la structure (destruction ou non) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Close_I ( NDT_Root * Root, DST_Flags Close_Mode ); +DST_Status DS_DataStruct_Close_L ( NDT_Root * Root, DST_Flags Close_Mode ); +DST_Status DS_DataStruct_Close_CL ( NDT_Root * Root, DST_Flags Close_Mode ); + +/*------------------------------------------------------------------------------*/ +/* Affiche les informations d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root: pointeur sur la racine de la structure de données */ +/* (I) Out : flux de sortie de l'affichage */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Info_Print_I ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Info_Print_L ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Info_Print_CL ( NDT_Root * Root, FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Réorganisation d'une structure de données : */ +/* - ordonnancement d'une liste non ordonnée */ +/* - réquilibrage d'un arbre non auto-équilibré */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Reorg_I ( NDT_Root * Root ); +DST_Status DS_DataStruct_Reorg_L ( NDT_Root * Root ); +DST_Status DS_DataStruct_Reorg_CL ( NDT_Root * Root ); + +/*------------------------------------------------------------------------------*/ +/* Parcours de tous les noeuds d'une structure de données et exécution d'une */ +/* commande sur chacun d'eux */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Command : Commande à exécuter sur chaque noeud traversé */ +/* (I) Data : pointeur de données utilisateur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Traverse_I ( NDT_Root * Root, NDT_Command Command, \ + void * Data ); +DST_Status DS_DataStruct_Traverse_L ( NDT_Root * Root, NDT_Command Command, \ + void * Data ); +DST_Status DS_DataStruct_Traverse_CL ( NDT_Root * Root, NDT_Command Command, \ + void * Data ); + +/*------------------------------------------------------------------------------*/ +/* Conversion d'une structure de données d'un type en un autre */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Target_Type : type de structure cible */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Convert_I ( NDT_Root * Root, \ + NDT_DataStruct_Type Target_Type ); +DST_Status DS_DataStruct_Convert_L ( NDT_Root * Root, \ + NDT_DataStruct_Type Target_Type ); +DST_Status DS_DataStruct_Convert_CL ( NDT_Root * Root, \ + NDT_DataStruct_Type Target_Type ); + +/*------------------------------------------------------------------------------*/ +/* Affichage de la valeur de tous les noeuds d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Print_I ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Print_L ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Print_CL ( NDT_Root * Root, FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Fonction de vérification / réparation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ +/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ +/* (I) Out : flux de sortie du rapport */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Check_I ( NDT_Root * Root, int * Nb_Detected, \ + int * Nb_Corrected, FILE * Out ); +DST_Status DS_DataStruct_Check_L ( NDT_Root * Root, int * Nb_Detected, \ + int * Nb_Corrected, FILE * Out ); +DST_Status DS_DataStruct_Check_CL ( NDT_Root * Root, int * Nb_Detected, \ + int * Nb_Corrected, FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Affichage de la structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Dump_I ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Dump_L ( NDT_Root * Root, FILE * Out ); +DST_Status DS_DataStruct_Dump_CL ( NDT_Root * Root, FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Récupération du premier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_First_Get_I ( NDT_Root * Root, NDT_Node ** Node ); +DST_Status DS_Node_First_Get_L ( NDT_Root * Root, NDT_Node ** Node ); +DST_Status DS_Node_First_Get_CL ( NDT_Root * Root, NDT_Node ** Node ); + +/*------------------------------------------------------------------------------*/ +/* Récupération du dernier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le dernier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Last_Get_I ( NDT_Root * Root, NDT_Node ** Node ); +DST_Status DS_Node_Last_Get_L ( NDT_Root * Root, NDT_Node ** Node ); +DST_Status DS_Node_Last_Get_CL ( NDT_Root * Root, NDT_Node ** Node ); + +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud suivant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le suivant */ +/* (O) Next_Node : pointeur sur le noeud suivant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Next_Get_I ( NDT_Node * Node, NDT_Node ** Next_Node ); +DST_Status DS_Node_Next_Get_L ( NDT_Node * Node, NDT_Node ** Next_Node ); +DST_Status DS_Node_Next_Get_CL ( NDT_Node * Node, NDT_Node ** Next_Node ); + +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud précédant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le précédant */ +/* (O) Prev_Node : pointeur sur le noeud précédant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Previous_Get_I ( NDT_Node * Node, NDT_Node ** Prev_Node ); +DST_Status DS_Node_Previous_Get_L ( NDT_Node * Node, NDT_Node ** Prev_Node ); +DST_Status DS_Node_Previous_Get_CL ( NDT_Node * Node, NDT_Node ** Prev_Node ); + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un noeud à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Node : pointeur sur le noeud à ajouter */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Add_I ( NDT_Root * Root, NDT_Node * Node ); +DST_Status DS_Node_Add_L ( NDT_Root * Root, NDT_Node * Node ); +DST_Status DS_Node_Add_CL ( NDT_Root * Root, NDT_Node * Node ); + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un noeud dans une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Node: pointeur sur le noeud à supprimer de la structure de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Remove_I ( NDT_Node * Node ); +DST_Status DS_Node_Remove_L ( NDT_Node * Node ); +DST_Status DS_Node_Remove_CL ( NDT_Node * Node ); + +/*------------------------------------------------------------------------------*/ +/* Recherche un noeud dans un arbre et retourne le pointeur sur le noeud */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de l'abre */ +/* (O) Node : adresse du pointeur sur le noeud à récuperer */ +/* (I) Value : pointeur sur la valeur à rechercher */ +/* (I) Data : pointeur de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Find_I ( NDT_Root * Root, NDT_Node ** Node, \ + void * Value, void * Data ); +DST_Status DS_Node_Find_L ( NDT_Root * Root, NDT_Node ** Node, \ + void * Value, void * Data ); +DST_Status DS_Node_Find_CL ( NDT_Root * Root, NDT_Node ** Node, \ + void * Value, void * Data ); + +/*------------------------------------------------------------------------------*/ +/* Allocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (O) Value : adresse d'un pointeur sur la valeur à allouer */ +/* (I) ... : arguments relatifs à l'allocation de la valeur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Alloc_I ( NDT_Root * Root, void ** Value, ... ); +DST_Status DS_Value_Alloc_L ( NDT_Root * Root, void ** Value, ... ); +DST_Status DS_Value_Alloc_CL ( NDT_Root * Root, void ** Value, ... ); + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une valeur à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à ajouter */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Add_I ( NDT_Root * Root, void * Value ); +DST_Status DS_Value_Add_L ( NDT_Root * Root, void * Value ); +DST_Status DS_Value_Add_CL ( NDT_Root * Root, void * Value ); + +/*------------------------------------------------------------------------------*/ +/* Suppression du premier noeud correspondant à une valeur donnée */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Reference_Value : pointeur sur la valeur de référence */ +/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Remove_I ( NDT_Root * Root, void * Reference_Value, \ + void ** Removed_Value); +DST_Status DS_Value_Remove_L ( NDT_Root * Root, void * Reference_Value, \ + void ** Removed_Value); +DST_Status DS_Value_Remove_CL ( NDT_Root * Root, void * Reference_Value, \ + void ** Removed_Value); + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Free_I ( NDT_Root * Root, void * Value ); +DST_Status DS_Value_Free_L ( NDT_Root * Root, void * Value ); +DST_Status DS_Value_Free_CL ( NDT_Root * Root, void * Value ); + +/*------------------------------------------------------------------------------*/ +/* Allocation de mémoire pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Size : taille mémoire à allouer */ +/* (O) Ptr : adresse du pointeur sur la zone de données allouée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Alloc_I ( NDT_Root * Root, size_t Size, void ** Ptr ); +DST_Status DS_Alloc_L ( NDT_Root * Root, size_t Size, void ** Ptr ); +DST_Status DS_Alloc_CL ( NDT_Root * Root, size_t Size, void ** Ptr ); + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une ressource pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Ptr : pointeur sur la zone à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Free_I ( NDT_Root * Root, void * Ptr ); +DST_Status DS_Free_L ( NDT_Root * Root, void * Ptr ); +DST_Status DS_Free_CL ( NDT_Root * Root, void * Ptr ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libdatastr.3 b/lib/libdatastr.3 new file mode 100644 index 0000000..f5a096c --- /dev/null +++ b/lib/libdatastr.3 @@ -0,0 +1,737 @@ +'\" t +.\" @(#)LIBDATASTR.3 99/10/12 SMI; +.TH LIBDATASTR 3 "10 Oct 1999" +.SH NOM +LIBDATASTR (librairie de structure de donnees a base de noeuds dans un contexte de memoire partagee) +.SH SYNOPSIS +.LP +.BI "cc [flag ...] file ... -lver -ldl -lnode -lshmem -ldatastr [library ...]" +.LP +.BI "#include " +.LP +.BI "DST_Status DS_Library_Open ( int " Instance " , char * " Context_Name ", DST_Flags " Debug_Mode " );" +.LP +.BI "DST_Status DS_Library_Close ( " void " ); +.LP +.BI "DST_Status DS_Library_Stderr_Set ( FILE * " Out " );" +.LP +.BI "DST_Status DS_DataStruct_Open ( char * " DS_Name ", NDT_Root ** " Root ", ND_DataStruct_Type " DS_Type ", char * " Manager_File_Name ", size_t " Segment_Size ", DST_Flags " Open_Mode ", int " Own_Values " );" +.LP +.BI "DST_Status DS_DataStruct_Lock ( NDT_Root * " Root ", DST_Flags " Lock_Mode " , int * " Locked " );" +.LP +.BI "DST_Status DS_DataStruct_Unlock ( NDT_Root * " Root " );" +.LP +.BI "DST_Status DS_DataStruct_Close ( NDT_Root * " Root ", DST_Flags " Close_Mode " );" +.LP +.BI "DST_Status DS_DataStruct_Info_Print ( NDT_Root * " Root ", FILE * " Out " );" +.LP +.BI "DST_Status DS_DataStruct_Reorg ( NDT_Root * " Root ");" +.LP +.BI "DST_Status DS_DataStruct_Traverse ( NDT_Root * " Root ", NDT_Command " Command ", void * " Data " );" +.LP +.BI "DST_Status DS_DataStruct_Convert ( NDT_Root * " Root ", NDT_DataStruct_Type " Target_Type " );" +.LP +.BI "DST_Status DS_DataStruct_Print ( NDT_Root * " Root ", FILE * " Out " );" +.LP +.BI "DST_Status DS_DataStruct_Check ( NDT_Root * " Root ", int * " Nb_Detected ", * int " Nb_Corrected ", FILE * " Out " );" +.LP +.BI "DST_Status DS_DataStruct_Dump ( NDT_Root * " Root ", FILE * " Out " );" +.LP +.BI "DST_Status DS_Node_First_Get ( NDT_Root * " Root ", NDT_Node ** " Node " );" +.LP +.BI "DST_Status DS_Node_Last_Get ( NDT_Root * " Root ", NDT_Node ** " Node " );" +.LP +.BI "DST_Status DS_Node_Next_Get ( NDT_Node * " Node ", NDT_Node ** " Next_Node " );" +.LP +.BI "DST_Status DS_Node_Previous_Get ( NDT_Node * " Node ", NDT_Node ** " Prev_Node " );" +.LP +.BI "DST_Status DS_Node_Add ( NDT_Root * " Root ", ND_Node * " Node " );" +.LP +.BI "DST_Status DS_Node_Remove (ND_Node * " Node " );" +.LP +.BI "DST_Status DS_Node_Find ( NDT_Root * " Root ", NDT_Node ** " Node ", void * " To_Search ", void * " Data " );" +.LP +.BI "DST_Status DS_Value_Alloc ( NDT_Root * " Root ", void ** " Value ", ... );" +.LP +.BI "DST_Status DS_Value_Add ( NDT_Root * " Root ", void * " To_Add " );" +.LP +.BI "DST_Status DS_Value_Remove ( NDT_Root * " Root ", void * " Reference_Value ", void ** " Removed_Value " );" +.LP +.BI "DST_Status DS_Value_Free ( NDT_Root * " Root ", void * " Value " );" +.LP +.BI "DST_Status DS_Alloc ( NDT_Root * " Root ", size_t " Size ", void ** " Ptr " );" +.LP +.BI "DST_Status DS_Free ( NDT_Root * " Root ", void * " Ptr " );" +.LP +.SH DESCRIPTION +.LP +La librairie LIBDATASTR implemente des structures de donnees a base de noeuds dans +un contexte de memoire partagee. +.LP +Elle est basee sur deux librairies sous-jacentes : +.LP +.RS 3 +- LIBNODE +: gestion de structure a base de noeuds +.LP +- LIBSHMEM +: gestion de contextes de memoire partagee +.RS -3 +.LP +La librairie LIBDATASTR gere les memes types de structure de donnees que la librairie LIBNODE +et propose les memes fonctionnalites que cette derniere. +.LP +L'utilisateur est donc prie de se referer a la documentation de la librairie LIBNODE +pour toute information relative aux structures de donnees manipulees. +.LP +La librairie LIBDATASTR propose une interface (API) tres similaire a celle de la librairie LIBNODE +. +.LP +Toutefois, une premiere difference reside dans le fait que chaque structure de donnees possede un nom. +Chaque structure pourra ainsi etre facilement identifiee dans la base de memoire partagee. +.LP +Par ailleurs, puisque chaque structure gere des valeurs qui lui sont propres, les fonctions de +manipulation (Manager, Allocator, Desallocator) de ces valeurs doivent aussi etre partageables. +C'est pourquoi chaque processus initiateur d'une structure doit fournir un fichier qui definit ces fonctions. +Le nom de ce fichier (.so) sera rattache a la racine de la structure lors de sa creation. +Ainsi, tout processus voulant acceder a une structure dont il ne connait pas les valeurs n'aura qu'a charger dynamiquement ce fichier pour pouvoir les manipuler. +.LP +.SH FONCTIONS +.LP +.BI "DST_Status DS_Library_Open ( int " Instance " , char * " Context_Name ", DST_Flags " Debug_Mode " );" +.RS 3 +.LP +Permet d'acceder aux ressources de la librairie LIBDATASTR. +Elle permet notamment d'acceder a la base de memoire partagee d'une instance donnee (voir la librairie LIBSHMEM) et de manipuler des structures de donnees dans un contexte donne. +.LP +Cette fonction attend les arguments suivants : +.LP +.RS 3 +- (In) +.I Instance +: designe le numero de l'instance a ouvrir. +.LP +Si cet argument est NULL, alors c'est la variable d'environnement $PROFILE qui definira le numero de l'instance. +.LP +- (In) +.I Context_Name +: designe le nom du contexte a utiliser. +.LP +- (In) +.I Debug_Mode +: mode d'affichage des messages d'erreur : +.LP +.RS 3 +- +.B DS_DEBUG_NONE +: aucun message d'erreur n'est affiche +.LP +- +.B DS_DEBUG +: les messages d'erreur generes par la librairie LIBDATASTR sont affiches sur la sortie standard d'erreur +.LP +- +.B DS_DEBUG_ALL +: les messages d'erreur generes par toutes les librairies sous-jacentes a la LIBDATASTR sont affiches sur la sortie standard d'erreur +.RS -3 +.LP +.RS -3 +.I Rappels +: la notion de contexte permet de creer plusieurs environnements parfaitement distincts au sein d'une meme instance. +.LP +.I Important +: cette fonction devra etre systematiquement appelee au debut de chaque programme utilisant la librairie LIBDATASTR. +.LP +Cette fonction echouera si l'instance de la librairie LIBSHMEM n'a pas ete creee. +.LP +.RS -3 +.BI "DST_Status DS_Library_Close ( " void " );" +.RS 3 +.LP +Permet de fermer les ressources de l'instance de la librairie LIBDATASTR. +.I NB +: cette fonction etre systematiquement appelee a la fin de chaque programme utilisant la librairie LIBDATASTR. +.LP +.RS -3 +.BI "DST_Status DS_Library_Stderr_Set ( FILE * " Out " );" +.LP +.RS 3 +Cette fonction permet de definir +.I Out +comme la sortie standard des messages d'erreur de la librarie. +.RS -3 +.LP +.BI "DST_Status DS_DataStruct_Open ( char * " DS_Name ", NDT_Root ** " Root ", ND_DataStruct_Type " DS_Type ", char * " Manager_File_Name ", size_t " Segment_Size ", DST_Flags " Open_Mode ", int " Own_Values " );" +.RS 3 +.LP +Cette fonction permet d'ouvrir ou de creer une structure de donnees. +.LP +La fonction doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I DS_Name +: le nom de la structure de donnees +.LP +* (Out) +.I Root +: l'adresse du pointeur sur la racine de la structure de donnees +.LP +* (In) +.I DS_Type +: le type de la nouvelle structure de donnees. +Dans le cas de l'ouverture d'une structure de donnees existante, cet argument n'est pas pris en compte. +.LP +* (In) +.I Manager_File_Name +: le nom du fichier (.so) definissant les fonctions manager de la structure. +Dans le cas de l'ouverture d'une structure de donnees existante, cet argument n'est pas pris en compte. +.LP +* (In) +.I Segment_Size +: la taille des segments de donnees du heap sous-jacent. +Bien entendu, cet argument n'est pris en compte que lors de la creation d'une structure dans un nouveau heap. +.LP +* (In) +.I Open_Mode +: le mode d'ouverture pouvant prendre les valeurs suivantes combinees : +.LP +* (In) +.I Own_Values +: indique si la data structure est proprietaire de ses valeurs (TRUE ou FALSE) +.LP +.RS 3 +- +.B DSD_OPEN +pour autoriser l'ouverture d'une structure existante. +.LP +- +.B DSD_CREATE +pour autoriser la creation de la structure si elle n'existe pas. +.LP +- +.B DSD_NEW +pour autoriser la creation d'une autre structure dans le meme heap si elle existe deja. +.RS -3 +.LP +.RS -3 +.I NB +: une fois qu'une structure de donnees est ouverte, l'utilisateur est assure de son existence, au moins jusqu'a ce que celle-ci soit fermee. +.LP +.I Information +: toutes les structures de donnees manipulees sont basees sur des heaps dont les noms seront prefixes par "datastr" afin d'indiquer que ces heaps ont ete crees par l'intermediaire de cette librairie. +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Lock ( NDT_Root * " Root ", DST_Flags " Lock_Mode " , int * " Locked " );" +.RS 3 +.LP +Cette fonction permet de verrouiller une structure de donnees. +.LP +La fonction doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Lock_Mode +: le mode de verrouillage ( +.B DSD_READ +ou +.B DSD_WRITE +) +.LP +* (Out) +.I Locked +: un pointeur sur un indicateur de verrouillage qui prendra la valeur : +.LP +.RS 3 +- TRUE si le verrouillage est effectif +.LP +- FALSE si la structure etait deja verrouillee dans ce mode +.RS -3 +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Unlock ( NDT_Root * " Root " );" +.RS 3 +.LP +Cette fonction permet de deverrouiller une structure de donnees. +.LP +L'argument +.I Root +est un pointeur sur la racine de la structure de donnees a deverrouiller. +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Close ( NDT_Root * " Root ", DST_Flags " Close_Mode " );" +.RS 3 +.LP +Cette fonction permet de fermer ou de detruire une structure de donnees. +.LP +La fonction doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Close_Mode +: le mode de fermeture ( +.B DSD_CLOSE +ou +.B DSD_DESTROY +) +.RS -3 +.LP +.I NB +: une structure de donnees ne pourra etre detruite que si elle n'est plus accedee par aucun autre processus. +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Info_Print ( NDT_Root * " Root ", FILE * " Out " );" +.RS 3 +.LP +Cette fonction permet d'afficher les informations d'une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees. +.LP +* (In) +.I Out +: le flux de sortie de l'affichage. +.LP +.RS -3 +.RS -3 +.BI "DST_Status DS_DataStruct_Traverse ( NDT_Root * " Root ", NDT_Command " Command ", void * " Data " );" +.RS 3 +.LP +Cette fonction permet de parcourir tous les noeuds d'une structure de donnees avec execution d'une commande sur chacun d'eux. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: le pointeur sur la racine de la structure de donnees a parcourir. +.LP +* (In) +.I Command +: la commande a executer sur chaque noeud traverse +.LP +* (In) +.I Data +: un pointeur de donnees propre a la commande +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Reorg ( NDT_Root * " Root "); +.RS 3 +.LP +Cette fonction permet de reorganiser les donnees d'une structure (tri pour une liste, reequilibrage pour un arbre). +.LP +.I Root +est un pointeur sur la racine de la structure de donnees a reorganiser. +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Convert ( NDT_Root * " Root ", NDT_DataStruct_Type " Target_Type " );" +.RS 3 +.LP +Cette fonction permet de convertir une structure de donnees d'un type en un autre. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees a convertir. +.LP +* (In) +.I Target_Type +: le type de la structure cible +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Print ( NDT_Root * " Root ", FILE * " Out " );" +.RS 3 +.LP +Cette fonction permet d'afficher toutes les valeurs des noeuds d'une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: le pointeur sur la racine de la structure de donnees a afficher. +.LP +* (In) +.I Out +: un pointeur sur le flux de sortie +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Check ( NDT_Root * " Root ", int * " Nb_Detected ", * int " Nb_Corrected ", FILE * " Out " );" +.RS 3 +.LP +Cette fonction realise des controles d'integrite sur une structure de donnees : +.LP +.RS 3 +- controle du heap sous-jacent a la structure +.LP +- controle de la structure de noeuds +.LP +.RS -3 +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees a corriger. +.LP +* (Out) +.I Nb_Detected +: un pointeur sur le nombre d'erreurs detectees. +.LP +* (Out) +.I Nb_Corrected +: un pointeur sur le nombre d'erreurs corrigees. +.LP +* (In) +.I Out +: un pointeur sur le flux de sortie du rapport. +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_DataStruct_Dump ( NDT_Root * " Root ", FILE * " Out " );" +.RS 3 +.LP +Cette fonction permet d'afficher une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees a corriger. +.LP +* (In) +.I Out +: un pointeur sur le flux de sortie de l'affichage +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_First_Get ( NDT_Root * " Root ", NDT_Node ** " Node " );" +.LP +.RS 3 +Cette fonction permet de recuperer le premier noeud d'une structure. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure +.LP +* (Out) +.I Node +: l'adresse d'un pointeur sur le premier noeud a recuperer +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_Last_Get ( NDT_Root * " Root ", NDT_Node ** " Node " );" +.LP +.RS 3 +Cette fonction permet de recuperer le dernier noeud d'une structure. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure +.LP +* (Out) +.I Node +: un pointeur sur le dernier noeud a recuperer +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_Next_Get ( NDT_Node * " Node ", NDT_Node ** " Next_Node " );" +.LP +.RS 3 +Cette fonction permet de recuperer le noeud qui suit immediatement un noeud particulier. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Node +: un pointeur sur le noeud de reference +.LP +* (Out) +.I Next_Node +: l'adresse d'un pointeur sur le noeud qui suit le noeud de reference +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_Previous_Get ( NDT_Node * " Node ", NDT_Node ** " Prev_Node " );" +.LP +.RS 3 +Cette fonction permet de recuperer le noeud qui precede immediatement un noeud particulier. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Node +: un pointeur sur le noeud de reference +.LP +* (Out) +.I Prev_Node +: l'adresse d'un pointeur sur le noeud qui precede le noeud de reference +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_Add ( NDT_Root * " Root ", ND_Node * " Node " );" +.RS 3 +.LP +Cette fonction permet d'ajouter un noeud a une structure. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Node +: un pointeur sur le noeud a ajouter +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Node_Remove (ND_Node * " Node " );" +.RS 3 +.LP +Cette fonction permet de supprimer le noeud d'une structure de donnees. +.LP +.I Node +est un pointeur sur le noeud a supprimer. +.LP +.I NB +: le noeud supprime n'est pas detruit mais simplement detache de la structure +.LP +.RS -3 +.BI "DST_Status DS_Node_Find ( NDT_Root * " Root ", NDT_Node ** " Node ", void * " To_Search ", void * " Data " );" +.RS 3 +.LP +Cette fonction permet de rechercher dans une structure de donnees le premier noeud correspondant a une valeur. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (Out) +.I Node +: l'adresse d'un pointeur sur le noeud resultat +.LP +* (In) +.I To_Search +: un pointeur sur la valeur a rechercher +.LP +* (In) +.I Data +: un pointeur de donnees a passer au manager pour la recherche +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Value_Alloc ( NDT_Root * " Root ", void ** " Value ", ... );" +.LP +.RS 3 +Cette fonction permet d'allouer une valeur pour une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (Out) +.I Value +: l'adresse d'un pointeur sur la valeur a allouer +.LP +* (In) +.I ... +: des arguments supplementaires pour l'allocation de la valeur +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Value_Add ( NDT_Root * " Root ", void * " To_Add " );" +.RS 3 +.LP +Cette fonction permet d'ajouter une valeur a une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I To_Add +: un pointeur sur la valeur a ajouter +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Value_Remove ( NDT_Root * " Root ", void * " Reference_Value ", void ** " Removed_Value " );" +.RS 3 +.LP +Cette fonction permet de supprimer une valeur d'une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.RS 3 +.LP +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Reference_Value +: un pointeur sur la valeur de reference +.LP +* (Out) +.I Removed_Value +: l'adresse d'un pointeur sur la valeur du noeud supprime +.LP +.RS -3 +.I NB +: la suppression d'un noeud implique son retrait de la structure et sa desallocation. +.LP +.RS -3 +.BI "DST_Status DS_Value_Free ( NDT_Root * " Root ", void * " Value " );" +.LP +.RS 3 +Cette fonction permet de desallouer une valeur faisant partie d'une structure de donnees. +.LP +Elle doit recevoir les arguments suivants : +.LP +.RS 3 +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Value +: un pointeur sur la valeur a desallouer +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Alloc ( NDT_Root * " Root ", size_t " Size ", void ** " Ptr " );" +.RS 3 +.LP +Cette fonction permet d'allouer de la memoire dans le meme contexte (meme heap) qu'une structure de donnees. +Elle sera utilisee notamment pour l'allocation des valeurs rattachees aux noeuds de la structure. +.LP +Elle doit recevoir les arguments suivants : +.RS 3 +.LP +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Size +: la taille de la memoire a allouer. +.LP +* (Out) +.I Ptr +: l'adresse d'un pointeur sur la zone a allouer +.RS -3 +.LP +.RS -3 +.BI "DST_Status DS_Free ( NDT_Root * " Root ", void * " Ptr " );" +.RS 3 +.LP +Cette fonction permet de liberer de la memoire qui a ete allouee dans le meme contexte qu'une structure de donnees (meme heap). +Elle sera utilisee notamment pour desallouer des valeurs rattachees aux noeuds de la structure. +.LP +Elle doit recevoir les arguments suivants : +.RS 3 +.LP +* (In) +.I Root +: un pointeur sur la racine de la structure de donnees +.LP +* (In) +.I Ptr +: un pointeur sur la zone a desallouer. +.RS -3 +.LP +.SH "CODES RETOUR" +.LP +Toutes les fonctions de la librairie LIBDATASTR retournent une valeur de type +.B DST_Status +: +.LP +.RS 3 +- +.B DSS_OK +: la fonction s'est correctement executee et a produit un resultat +.LP +- +.B DSS_KO +: la fonction s'est correctement executee mais n'a pas produit de resultat +.LP +- +.B DSS_ERRAPI +: la fonction a ete appelee avec des arguments de valeur incorrecte +.LP +- +.B DSS_ERRMEM +: la fonction ne s'est pas correctement executee pour un probleme d'allocation memoire +.LP +- +.B DSS_ERRSHM +: la fonction ne s'est pas correctement executee pour un probleme relatif a la memoire partagee +.LP +- +.B DSS_ERRSIG +: une operation sur semaphore a ete interrompue par un signal +.LP +- +.B DSS_ERRSEM +: la fonction ne s'est pas correctement executee pour un probleme relatif a l'utilisation des semaphores +.LP +- +.B DSS_ERRDLL +: la fonction ne s'est pas correctement executee pour un probleme de chargement dynamique d'objet +.LP +.RS -3 +.I NB +: la macro +.B DS_ERROR() +permet de tester si un code retour correspond a une erreur. +.LP +En cas d'erreur, la variable +.B DS_Error_Msg +contient un message du type : +.LP +.RS 3 +Error : +.RS -3 +.LP +.SH VOIR AUSSI +.B libnode +(3) +, +.B libshmem +(3) diff --git a/lib/libdatastr.c b/lib/libdatastr.c new file mode 100644 index 0000000..3f5d02a --- /dev/null +++ b/lib/libdatastr.c @@ -0,0 +1,3071 @@ +/* Utilisation des API sans vérification des arguments */ + +#define ND_MODE 1 +#define SM_MODE 1 + +#include + +VER_INFO_EXPORT (libdatastr,"$Revision: 1.1 $", "$Name: $",__FILE__,"$Author: smas $") + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS PUBLIQUES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* FONCTIONS OPTIMISATION MAXIMALE (DS_MODE = 2) */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Ouverture d'une instance de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance de la librairie */ +/* (I) Context : nom du contexte */ +/* (I) Debug_Mode : mode d'affichage des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Open_I ( int Instance, const char * Context, DST_Flags Debug_Mode ) +{ + DST_Status rc; + int SM_Debug = SMD_DEBUG_NONE; + + /* Définition du mode debug */ + + if (Debug_Mode & DSD_DEBUG) + { + DS_stderr = stderr; + SM_Debug = SMD_DEBUG; + } + else if (Debug_Mode & DSD_DEBUG_ALL) + { + DS_stderr = stderr; + SM_Debug = SMD_DEBUG_ALL; + } + + /* Ouverture de la librairie LIBSHMEM */ + + rc = SM_Library_Open (Instance, Context, SMD_OPEN | SM_Debug); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Library_Open : unable to open the LIBSHMEM library"); + DS_Error_Print (); + + return rc; + } + + /* + Lors de la première ouverture de la librairie LIBDATASTR, + on crée une structure locale permettant de référencer + les data structures ouvertes. + */ + + if (DS_Open_Counter == 0) + { + rc = ND_DataStruct_Open (&OpenedDS_List, NDD_DS_TREE | NDD_MN_AUTO_EQU, NULL, NULL, NULL, TRUE); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Library_Open : unable to create the opened data structure list"); + DS_Error_Print (); + SM_Library_Close (SMD_CLOSE); + return rc; + } + else strcpy (OpenedDS_List->Manager, "DS_OpenedDS_List_Manager"); + } + + DS_Open_Counter++; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture de l'instance de la librairie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Close_I ( void ) +{ + DST_Status rc; + + /* + A la dernière fermeture de la librairie LIBDATASTR, on détruit + la structure locale qui référence les data structures ouvertes. + */ + + if (DS_Open_Counter == 1) + { + rc = ND_DataStruct_Close (OpenedDS_List); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Library_Close : unable to close the opened data structure list"); + DS_Error_Print (); + + if (DS_ERROR(rc)) return rc; + } + } + + /* Fermeture de la librairie LIBSHMEM */ + + rc = SM_Library_Close (SMD_CLOSE); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Library_Close : unable to close the LIBSHMEM library"); + DS_Error_Print (); + + if (DS_ERROR(rc)) return rc; + } + + DS_Open_Counter--; + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Stderr_Set_I ( FILE * Out ) +{ + DS_stderr = Out; + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Création / ouverture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) DS_Name : nom de la structure */ +/* (O) Root : adresse du pointeur sur la racine de la structure */ +/* (I) Type : type de la structure de données */ +/* (I) Manager_FileName : nom du fichier qui définit les fonctions manager */ +/* (I) Segment_Size : taille ds segments du heap sous-jacent */ +/* (I) Open_Mode : mode d'ouverture de la structure */ +/* (I) Own_Values : indique si la structure possède ses valeurs */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Open_I ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Values ) +{ + DST_Status rc; + SMT_Heap * Heap; + SMT_DSH * DSH; + int Locked, Mode; + DST_RootDesc * RootDesc, Tmp_RootDesc; + DST_DataStruct * Opened_DataStruct; + char * Prefixed_Name = DS_Name_Prefix (DS_Name); + union semun Sem_Ctl; + + *Root = NULL; + + /* On définit ce qu'on va faire en fonction du mode d'ouverture demandé et de ce qui existe déjà ou non */ + + if (SM_Heap_Exist (Prefixed_Name) == SMS_YES) + { + if (DSD_MSK_OPEN (Open_Mode)) Mode = 2; + else if (DSD_MSK_NEW (Open_Mode)) Mode = 1; + else + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the data structure already exists and (Flags & DSD_OPEN & DSD_NEW) is false"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + } + else if (DSD_MSK_CREATE (Open_Mode)) Mode = 3; + else + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the data structure \"%s\" does no exist and (Flags & DSD_CREATE) is false", DS_Name); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + switch (Mode) + { + case 1: + + /*--------------- Création d'une nouvelle data structure dans un heap existant ---------------*/ + + /* Ouverture du heap en écriture */ + + rc = SM_Heap_Open (Prefixed_Name, &Heap, 0, SMD_OPEN | SMD_WRITE, &Locked); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to open the data structure heap \"%s\" for writing", Prefixed_Name); + DS_Error_Print (); + + return rc; + } + + /* Création de la node structure */ + + Tmp_RootDesc.Heap_Name = Prefixed_Name; + + rc = ND_DataStruct_Open (Root, Type, "DS_DataStruct_Alloc", "DS_DataStruct_Free", &Tmp_RootDesc, Own_Values); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to create a new node structure in the existing heap \"%s\"", Heap->Name); + DS_Error_Print (); + + if (Locked == TRUE) SM_Heap_Unlock (Heap); + *Root = NULL; + + return rc; + } + + /* Allocation de mémoire pour la description de la nouvelle data structure */ + + rc = DS_DataStruct_Alloc (sizeof (DST_RootDesc) + strlen (Prefixed_Name) + strlen (Manager_FileName) + 2, (void **)(&RootDesc), &Tmp_RootDesc); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to allocate memory for the new data structure description"); + DS_Error_Print (); + + DS_DataStruct_Free (*Root, &Tmp_RootDesc); + if (Locked == TRUE) SM_Heap_Unlock (Heap); + *Root = NULL; + + return rc; + } + + RootDesc->Heap_Name = (char *)((size_t)RootDesc + sizeof (DST_RootDesc) ); + strcpy (RootDesc->Heap_Name, Prefixed_Name); + + RootDesc->Manager_FileName = (char *)((size_t)RootDesc + sizeof (DST_RootDesc) + strlen (Prefixed_Name) + 1); + strcpy (RootDesc->Manager_FileName, Manager_FileName); + + /* On indique que la structure n'est pas propriétaire de son heap */ + + RootDesc->Heap_Owner = FALSE; + + /* On indique que la structure est valide */ + + RootDesc->Valid = TRUE; + + /* On rattache la desription de la data structure à la racine */ + + (*Root)->User = RootDesc; + + /* Pour une telle data structure, on ne crée pas de sémaphore d'ouverture */ + + /* Déverrouillage du heap */ + + if (Locked == TRUE) + { + rc = SM_Heap_Unlock (Heap); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to unlock the data structure heap \"%s\"", Prefixed_Name); + DS_Error_Print (); + return rc; + } + } + + return DSS_OK; + + break; + + case 2: + + /*--------------- Ouverture d'une data structure existante --------------------*/ + + /* Si la structure a déjà été ouverte, on ne recommence pas */ + + rc = DS_DataStruct_IsOpen (DS_Name, Root); + if (rc == DSS_YES) return DSS_OK; + else if (DS_ERROR(rc)) return rc; + + /* Accès au heap sous-jacent en lecture */ + + rc = SM_Heap_Open (Prefixed_Name, &Heap, 0, SMD_OPEN | SMD_READ, &Locked); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to open the data structure heap \"%s\" for reading", Prefixed_Name); + DS_Error_Print (); + return rc; + } + + DSH = Heap->MHH->DSR->Head->Value; + + /* La racine de la structure se trouve dans le premier chunk du premier segment du heap */ + + *Root = ( NDT_Root *)((size_t)(DSH->Start) + sizeof (NDT_Node) + sizeof (SMT_Chunk)); + + /* Chargement des fonctions manager de la structure */ + + RootDesc = (*Root)->User; + + if (!RootDesc) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : data structure \"%s\" has no description defined", DS_Name); + DS_Error_Print (); + if (Locked == TRUE) SM_Heap_Unlock (Heap); + *Root = NULL; + return DSS_ERRAPI; + } + + if (!RootDesc->Manager_FileName || !dlopen (( const char *)(RootDesc->Manager_FileName), RTLD_LAZY | RTLD_GLOBAL)) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to load the manager file %s of data structure \"%s\" (%s)", RootDesc->Manager_FileName == NULL ? "undefined" : (char *)(RootDesc->Manager_FileName), DS_Name, dlerror ()); + DS_Error_Print (); + if (Locked == TRUE) SM_Heap_Unlock (Heap); + *Root = NULL; + return DSS_ERRDLL; + } + + break; + + case 3: + + /*--------------- Création d'une nouvelle structure de données dans un nouveau heap -------------------*/ + + if (!Manager_FileName) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the manager file name (.so) is undefined"); + DS_Error_Print (); + return DSS_ERRAPI; + } + + /* Création d'un nouveau heap */ + + rc = SM_Heap_Open (Prefixed_Name, &Heap, Segment_Size, SMD_CREATE | SMD_WRITE, &Locked); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to create a heap for the data structure \"%s\"", DS_Name); + DS_Error_Print (); + return rc; + } + + /* Création de la structure de données dans le heap */ + + Tmp_RootDesc.Heap_Name = Prefixed_Name; + + rc = ND_DataStruct_Open (Root, Type, "DS_DataStruct_Alloc", "DS_DataStruct_Free", &Tmp_RootDesc, Own_Values); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to create the node structure"); + DS_Error_Print (); + SM_Heap_End (Prefixed_Name); + *Root = NULL; + return rc; + } + + /* Allocation de mémoire pour la description de la structure */ + + rc = DS_DataStruct_Alloc (sizeof (DST_RootDesc) + strlen (Prefixed_Name) + strlen (Manager_FileName) + 2, (void **)(&RootDesc), &Tmp_RootDesc); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to allocate memory for the data structure description"); + DS_Error_Print (); + SM_Heap_End (Prefixed_Name); + *Root = NULL; + return rc; + } + + RootDesc->Heap_Name = (char *)((size_t)RootDesc + sizeof (DST_RootDesc) ); + strcpy (RootDesc->Heap_Name, Prefixed_Name); + + RootDesc->Manager_FileName = (char *)((size_t)RootDesc + sizeof (DST_RootDesc) + strlen (Prefixed_Name) + 1); + strcpy (RootDesc->Manager_FileName, Manager_FileName); + + /* On indique que la structure est propriétaire du heap */ + + RootDesc->Heap_Owner = TRUE; + + /* On indique que la structure est valide */ + + RootDesc->Valid = TRUE; + + /* On rattache la desription de la data structure à la racine */ + + (*Root)->User = RootDesc; + + /* On crée un sémaphore pour compter le nombre de processus qui ouvrent la structure */ + + rc = DS_Semaphore_Create (*Root); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to create a semaphore for the data structure \"%s\"", DS_Name); + DS_Error_Print (); + SM_Heap_End (Prefixed_Name); + *Root = NULL; + return rc; + } + + break; + + default: + break; + } + + /* On incrémente le sémaphore qui compte le nombre de processus qui ouvrent la structure */ + + rc = DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Open, 1); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to incremente the semaphore of data structure \"%s\"", DS_Name); + DS_Error_Print (); + + if (Locked == TRUE) SM_Heap_Unlock (Heap); + + if (Mode == 3) + { + semctl (RootDesc->OpenSemID, 0, IPC_RMID, Sem_Ctl); + SM_Heap_End (Prefixed_Name); + } + else DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Close, 1); + + *Root = NULL; + + return rc; + } + + /* On ajoute la data structure à la liste des structures ouvertes par le processus courant */ + + Opened_DataStruct = (DST_DataStruct *)malloc (sizeof (DST_DataStruct)); + Opened_DataStruct->Name = strdup (DS_Name); + Opened_DataStruct->Root = *Root; + + rc = ND_Value_Add (OpenedDS_List, Opened_DataStruct); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to add structure \"%s\" to the opened structure list", DS_Name); + DS_Error_Print (); + + if (Locked == TRUE) SM_Heap_Unlock (Heap); + + if (Mode == 3) + { + semctl (RootDesc->OpenSemID, 0, IPC_RMID, Sem_Ctl); + SM_Heap_End (Prefixed_Name); + } + else DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Close, 1); + + *Root = NULL; + + return rc; + } + + /* Déverrouillage du heap */ + + if (Locked == TRUE) + { + rc = SM_Heap_Unlock (Heap); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to unlock the data structure heap \"%s\"", Prefixed_Name); + DS_Error_Print (); + + ND_Value_Remove (OpenedDS_List, Opened_DataStruct, (void **)&Opened_DataStruct); + ND_Value_Free (OpenedDS_List, Opened_DataStruct); + + if (Mode == 3) + { + semctl (RootDesc->OpenSemID, 0, IPC_RMID, Sem_Ctl); + SM_Heap_End (Prefixed_Name); + } + else DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Close, 1); + + *Root = NULL; + + return rc; + } + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Verrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Lock_Mode : type de verrou à poser sur la structure */ +/* (O) Locked : verrou effectif (TRUE ou FALSE) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Lock_I ( NDT_Root * Root, DST_Flags Lock_Mode, int * Locked ) +{ + DST_Status rc; + SMT_Heap * Heap; + char * Heap_Name = ((DST_RootDesc *)(Root->User))->Heap_Name; + + /* Réouverture du heap sous-jacent (rafraîchissement des segments) + verrouillage */ + + rc = SM_Heap_Open (Heap_Name, &Heap, 0, SMD_OPEN | Lock_Mode, Locked); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Lock : unable to reopen the data structure heap \"%s\" for %s", + Heap_Name, DSD_MSK_READ (Lock_Mode) ? "reading" : "writing"); + DS_Error_Print (); + + return rc; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Déverrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Unlock_I ( NDT_Root * Root ) +{ + DST_Status rc; + SMT_Heap * Heap; + char * Heap_Name = ((DST_RootDesc *)(Root->User))->Heap_Name; + + rc = SM_Heap_IsOpen (Heap_Name, &Heap); + if (rc != SMS_YES) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Unlock : the data structure heap \"%s\" is not open", Heap_Name); + DS_Error_Print (); + + return rc; + } + + rc = SM_Heap_Unlock (Heap); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Unlock : unable to unlock the data structure heap \"%s\"", Heap_Name); + DS_Error_Print (); + + return rc; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à fermer */ +/* (I) Close_Mode : mode de fermeture de la structure (destruction ou non) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Close_I ( NDT_Root * Root, DST_Flags Close_Mode ) +{ + DST_Status rc; + SMT_Heap * Heap; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + char Heap_Name [256], * DS_Name; + DST_DataStruct To_Remove, * Opened_DataStruct; + union semun Sem_Ctl; + + strcpy (Heap_Name, RootDesc->Heap_Name); + + DS_Name = strstr (Heap_Name, DS_PREFIX); + if (DS_Name) DS_Name += strlen (DS_PREFIX) + 1; + else DS_Name = Heap_Name; + + if (Close_Mode == DSD_DESTROY) /* Destruction de la data structure */ + { + /* La data structure est-elle propriétaire du heap sous-jacent ? */ + + if (RootDesc->Heap_Owner == TRUE) + { + /* On vérifie qu'aucun autre processus n'a ouvert la data structure */ + + rc = DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Destroy, 2); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : unable to destroy the data structure \"%s\" because it is opened by another process", DS_Name); + + DS_Error_Print (); + + return rc; + } + + /* On supprime la structure proprement (toutes les valeurs sont supprimées les unes après les autres) */ + + rc = ND_DataStruct_Close (Root); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : unable to close the node structure of \"%s\" data structure", DS_Name); + DS_Error_Print (); + + return rc; + } + + /* Suppression du sémaphore */ + + semctl (RootDesc->OpenSemID, 0, IPC_RMID, Sem_Ctl); + + /* On supprime maintenant le heap */ + + rc = SM_Heap_End (Heap_Name); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : unable to remove heap \"%s\"", Heap_Name); + DS_Error_Print (); + + return rc; + } + } + else + { + /* + Dans le cas où la data structure n'est pas propriétaire du heap sous-jacent, + on ne peut pas garantir qu'aucun autre processus ne l'a ouverte. + + On la supprime donc sans contrôle. + */ + + rc = ND_DataStruct_Close (Root); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : unable to close the node structure of \"%s\" data structure", DS_Name); + DS_Error_Print (); + + return rc; + } + + return DS_DataStruct_Free (RootDesc, (void *)RootDesc); + } + } + else /* Fermeture simple de la data structure */ + { + /* On décrémente le sémaphore qui compte le nombre de processus ayant ouvert la data structure */ + + rc = DS_Semaphore_Operate (RootDesc->OpenSemID, DS_SemOp_Close, 1); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : unable to decremente the semaphore of data structure \"%s\"", DS_Name); + DS_Error_Print (); + + return rc; + } + + /* Fermeture simple du heap */ + + rc = SM_Heap_IsOpen (Heap_Name, &Heap); + if (rc == SMS_YES) + { + rc = SM_Heap_Close (Heap); + if (rc != SMS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : unable to close heap \"%s\"", Heap_Name); + DS_Error_Print (); + + return rc; + } + } + } + + /* Suppression de la data structure de la liste des structures ouvertes */ + + To_Remove.Name = DS_Name; + rc = ND_Value_Remove (OpenedDS_List, &To_Remove, (void **)&Opened_DataStruct); + if (rc == NDS_OK) ND_Value_Free (OpenedDS_List, Opened_DataStruct); + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Affiche les informations d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root: pointeur sur la racine de la structure de données */ +/* (I) Out : flux de sortie de l'affichage */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Info_Print_I ( NDT_Root * Root, FILE * Out ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Info_Print : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Affichage des informations sur la structure */ + + rc = ND_DataStruct_Info_Print (Root, Out); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Info_Print : unable to print info about the data structure"); + DS_Error_Print (); + + return rc; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Réorganisation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à réorganiser */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Reorg_I ( NDT_Root * Root ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Reorg : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide, le temps de sa réorganisation */ + + RootDesc->Valid = FALSE; + + /* Réorganisation de la node structure */ + + rc = ND_DataStruct_Reorg (Root); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Reorg : unable to reorganize the node structure "); + DS_Error_Print (); + + RootDesc->Valid = TRUE; + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Parcours de tous les noeuds d'une structure de données et exécution d'une */ +/* commande sur chacun d'eux */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à parcourir */ +/* (I) Command : commande à exécuter sur chaque noeud traversé */ +/* (I) Data : pointeur de données utilisateur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Traverse_I ( NDT_Root * Root, NDT_Command Command, void * Data ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Traverse : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend éventuellement la structure invalide le temps de sa traversée */ + + switch ((int)Command) + { + case NDD_CMD_PRINT_VALUE: + break; + + default: + RootDesc->Valid = FALSE; + break; + } + + /* Traversée de la node structure */ + + rc = ND_DataStruct_Traverse (Root, Command, Data); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Traverse : unable to traverse the node structure "); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Conversion d'une structure de données d'un type en un autre */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Target_Type : type de structure cible */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Convert_I ( NDT_Root * Root, NDT_DataStruct_Type Target_Type ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Convert : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide le temps de sa conversion */ + + RootDesc->Valid = FALSE; + + /* Conversion de la node structure */ + + rc = ND_DataStruct_Convert (Root, Target_Type); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Convert : unable to convert the node structure"); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Affichage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à afficher */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Print_I ( NDT_Root * Root, FILE * Out ) +{ + return DS_DataStruct_Traverse_I (Root, NDD_CMD_PRINT_VALUE, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Fonction de vérification / réparation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ +/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ +/* (I) Out : flux de sortie du rapport */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Check_I ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) +{ + DST_Status rc; + SMT_Heap * Heap; + int Locked; + char * Heap_Name; + DST_Flags Previous_Lock; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + Heap_Name = RootDesc->Heap_Name; + + /* On sauvegarde l'état de verrouillage précédent */ + + rc = SM_Heap_IsOpen (Heap_Name, &Heap); + if (rc != SMS_YES) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Check : the data structure heap \"%s\" is not open", Heap_Name); + DS_Error_Print (); + + return rc; + } + + Previous_Lock = Heap->Lock_Mode; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error ND_DataStruct_Check : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + /* Vérification du heap sous-jacent à la data structure */ + + rc = SM_Heap_Check (Heap, Nb_Detected, Nb_Corrected, Out); + if (rc != SMS_OK) + { + if (Previous_Lock == SMD_UNDEF) DS_DataStruct_Unlock_I (Root); + else DS_DataStruct_Lock_I (Root, Previous_Lock, &Locked); + + return rc; + } + else + { + /* Vérification de la structure de noeuds */ + + fprintf (Out, "Checking the node structure ...\n"); + + rc = ND_DataStruct_Check (Root, Nb_Detected, Nb_Corrected, Out); + } + + /* On valide ou invalide la structure selon le résultat */ + + if (*Nb_Corrected == *Nb_Detected) RootDesc->Valid = TRUE; + else RootDesc->Valid = FALSE; + + /* Retour au mode de verrouillage précédent */ + + if (Previous_Lock == SMD_UNDEF) DS_DataStruct_Unlock_I (Root); + else DS_DataStruct_Lock_I (Root, Previous_Lock, &Locked); + + /* Affichage du résultat de la procédure de vérification */ + + if (*Nb_Detected) + { + fprintf (Out, "%d/%d error(s) corrected in the data structure\n", *Nb_Corrected, *Nb_Detected); + + if (*Nb_Corrected < *Nb_Detected) return DSS_KO; + } + else fprintf (Out, "No error detected in the data structure\n"); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Affiche la structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Dump_I ( NDT_Root * Root, FILE * Out ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Dump : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Affichage de la node structure */ + + rc = ND_DataStruct_Dump (Root, Out); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Dump : unable to dump the node structure"); + DS_Error_Print (); + + return rc; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du premier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_First_Get_I ( NDT_Root * Root, NDT_Node ** Node ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_First_Get : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Récupération du premier noeud */ + + rc = ND_Node_First_Get (Root, Node); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du dernier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le dernier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Last_Get_I ( NDT_Root * Root, NDT_Node ** Node ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Last_Get : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Récupération du dernier noeud */ + + rc = ND_Node_Last_Get (Root, Node); + + return rc; +} +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud suivant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le suivant */ +/* (O) Next_Node : pointeur sur le noeud suivant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Next_Get_I ( NDT_Node * Node, NDT_Node ** Next_Node ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Node->Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Node->Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Next_Get : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Récupération du noeud suivant */ + + rc = ND_Node_Next_Get (Node, Next_Node); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud précédant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le précédant */ +/* (O) Prev_Node : pointeur sur le noeud précédant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Previous_Get_I ( NDT_Node * Node, NDT_Node ** Prev_Node ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Node->Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + + rc = DS_DataStruct_Check_L (Node->Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Previous_Get : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Récupération du noeud précédent */ + + rc = ND_Node_Previous_Get (Node, Prev_Node); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un noeud à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Node : pointeur sur le noeud à ajouter */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Add_I ( NDT_Root * Root, NDT_Node * Node ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Add : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide le temps de l'ajout */ + + RootDesc->Valid = FALSE; + + /* Ajout du noeud */ + + rc = ND_Node_Add (Root, Node); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Add : unable to add a node to the data structure"); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un noeud dans une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud à supprimer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Remove_I ( NDT_Node * Node ) +{ + DST_Status rc; + NDT_Root * Root; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Node->Root->User); + + Root = Node->Root; + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Remove : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide le temps de la suppression du noeud */ + + RootDesc->Valid = FALSE; + + /* Suppression dans la node structure */ + + rc = ND_Node_Remove (Node); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Remove : unable to remove a node from the structure"); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Recherche un noeud dans un arbre et retourne le pointeur sur le noeud */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de l'abre */ +/* (O) Node : adresse du pointeur sur le noeud à récuperer */ +/* (I) Value : pointeur sur la valeur à rechercher */ +/* (I) Data : pointeur de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Find_I ( NDT_Root * Root, NDT_Node ** Node, void * Value, void * Data ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + *Node = NULL; + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Find : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* Recherche dans la node structure */ + + rc = ND_Node_Find (Root, Node, Value, Data); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Allocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (O) Value : adresse d'un pointeur sur la valeur à allouer */ +/* (I) ... : arguments relatifs à l'allocation de la valeur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Alloc_I ( NDT_Root * Root, void ** Value, ... ) +{ + DST_Status rc; + va_list Args; + + /* Récupération des arguments pour l'allocation de la valeur */ + + va_start (Args, Value); + + /* Appel du manager */ + + rc = ND_Manager_Exec (Root->Manager, NDD_CMD_MAKE_VALUE, Root, Value, Args); + + va_end (Args); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une valeur à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à ajouter à la structure de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Add_I ( NDT_Root * Root, void * Value ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Add : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide le temps de l'ajout */ + + RootDesc->Valid = FALSE; + + /* Ajout de la valeur */ + + rc = ND_Value_Add (Root, Value); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Add : unable to add a value to the data structure"); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression du premier noeud correspondant à une valeur donnée */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Reference_Value : pointeur sur la valeur de référence */ +/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Remove_I ( NDT_Root * Root, void * Reference_Value, void ** Removed_Value ) +{ + DST_Status rc; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* On vérifie que la data structure est valide */ + + if (RootDesc->Valid == FALSE) + { + int Nb_Detected, Nb_Corrected; + + /* On vérifie la structure */ + + Nb_Detected = Nb_Corrected = 0; + rc = DS_DataStruct_Check_L (Root, &Nb_Detected, &Nb_Corrected, DS_stderr); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : unable to check the data structure"); + DS_Error_Print (); + + return rc; + } + } + + /* On rend la structure invalide le temps de la suppression de valeur */ + + RootDesc->Valid = FALSE; + + /* Suppression du noeud correspondant à la valeur de référence */ + + rc = ND_Value_Remove (Root, Reference_Value, Removed_Value); + if (rc != NDS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : unable to remove a value from the data structure"); + DS_Error_Print (); + + if (!DS_ERROR(rc)) RootDesc->Valid = TRUE; + + return rc; + } + + /* On rend la structure à nouveau valide */ + + RootDesc->Valid = TRUE; + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Free_I ( NDT_Root * Root, void * Value ) +{ + return ND_Value_Free (Root, Value); +} + +/*------------------------------------------------------------------------------*/ +/* Allocation de mémoire pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Size : taille mémoire à allouer */ +/* (O) Ptr : adresse du pointeur sur la zone de données allouée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Alloc_I ( NDT_Root * Root, size_t Size, void ** Ptr ) +{ + return DS_DataStruct_Alloc (Size, Ptr, Root->User); +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une ressource pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Ptr : pointeur sur la zone à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Free_I ( NDT_Root * Root, void * Ptr ) +{ + return DS_DataStruct_Free (Ptr, Root->User); +} + + +/*------------------------------------------------------------------------------*/ +/* FONCTIONS OPTIMISATION MOYENNE (DS_MODE = 1) */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Ouverture d'une instance de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance de la librairie */ +/* (I) Context : nom du contexte */ +/* (I) Debug_Mode : mode d'affichage des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Open_L ( int Instance, const char * Context, DST_Flags Debug_Mode ) +{ + return DS_Library_Open_I (Instance, Context, Debug_Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture de l'instance de la librairie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Close_L ( void ) +{ + return DS_Library_Close_I (); +} + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Stderr_Set_L ( FILE * Out ) +{ + return DS_Library_Stderr_Set_I (Out); +} + +/*------------------------------------------------------------------------------*/ +/* Création / ouverture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) DS_Name : nom de la structure */ +/* (O) Root : adresse du pointeur sur la racine de la structure */ +/* (I) Type : type de la structure de données */ +/* (I) Manager_FileName : nom du fichier qui définit les fonctions manager */ +/* (I) Segment_Size : taille ds segments du heap sous-jacent */ +/* (I) Open_Mode : mode d'ouverture de la structure */ +/* (I) Own_Values : indique si la structure possède ses valeurs */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Open_L ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Values ) +{ + return DS_DataStruct_Open_I (DS_Name, Root, Type, Manager_FileName, Segment_Size, Open_Mode, Own_Values); +} + +/*------------------------------------------------------------------------------*/ +/* Verrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Lock_Mode : type de verrou à poser sur la structure */ +/* (O) Locked : verrou effectif (TRUE ou FALSE) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Lock_L ( NDT_Root * Root, DST_Flags Lock_Mode, int * Locked ) +{ + return DS_DataStruct_Lock_I (Root, Lock_Mode, Locked); +} + +/*------------------------------------------------------------------------------*/ +/* Déverrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Unlock_L ( NDT_Root * Root ) +{ + return DS_DataStruct_Unlock_I (Root); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à fermer */ +/* (I) Close_Mode : mode de fermeture de la structure (destruction ou non) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Close_L ( NDT_Root * Root, DST_Flags Close_Mode ) +{ + return DS_DataStruct_Close_I (Root, Close_Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Affiche les informations d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root: pointeur sur la racine de la structure de données */ +/* (I) Out : flux de sortie de l'affichage */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Info_Print_L ( NDT_Root * Root, FILE * Out ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Info_Print : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Info_Print_I (Root, Out); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Réorganisation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à réorganiser */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Reorg_L ( NDT_Root * Root ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Reorg : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Reorg_I (Root); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Parcours de tous les noeuds d'une structure de données et exécution d'une */ +/* commande sur chacun d'eux */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à parcourir */ +/* (I) Command : commande à exécuter sur chaque noeud traversé */ +/* (I) Data : pointeur de données utilisateur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Traverse_L ( NDT_Root * Root, NDT_Command Command, void * Data ) +{ + DST_Status rc; + SMT_Flags Lock_Mode; + int Locked; + + /* Définition du mode de verrouillage de la data structure selon le type de commande */ + + switch ((int)Command) + { + case NDD_CMD_PRINT_VALUE: + Lock_Mode = SMD_READ; + break; + + case NDD_CMD_DELETE_VALUE: + + default: + Lock_Mode = SMD_WRITE; + break; + } + + /* Verrouillage de la data structure */ + + rc = DS_DataStruct_Lock_I (Root, Lock_Mode, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Traverse : unable to lock the data structure for %s", + Lock_Mode == SMD_WRITE ? "writing" : "reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Traverse_I (Root, Command, Data); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Conversion d'une structure de données d'un type en un autre */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Target_Type : type de structure cible */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Convert_L ( NDT_Root * Root, NDT_DataStruct_Type Target_Type ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Convert : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Convert_I (Root, Target_Type); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Affichage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à afficher */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Print_L ( NDT_Root * Root, FILE * Out ) +{ + return DS_DataStruct_Traverse_L (Root, NDD_CMD_PRINT_VALUE, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Fonction de vérification / réparation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ +/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ +/* (I) Out : flux de sortie du rapport */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Check_L ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) +{ + return DS_DataStruct_Check_I (Root, Nb_Detected, Nb_Corrected, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Affiche la structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Dump_L ( NDT_Root * Root, FILE * Out ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Dump : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Dump_I (Root, Out); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du premier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_First_Get_L ( NDT_Root * Root, NDT_Node ** Node ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_First_Get : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_First_Get_I (Root, Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du dernier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le dernier noeud */ +/* (O) Node : pointeur sur le noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Last_Get_L ( NDT_Root * Root, NDT_Node ** Node ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Last_Get : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Last_Get_I (Root, Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud suivant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le suivant */ +/* (O) Next_Node : pointeur sur le noeud suivant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Next_Get_L ( NDT_Node * Node, NDT_Node ** Next_Node ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Node->Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Next_Get : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Next_Get_I (Node, Next_Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Node->Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud précédant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le précédant */ +/* (O) Prev_Node : pointeur sur le noeud précédant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Previous_Get_L ( NDT_Node * Node, NDT_Node ** Prev_Node ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Node->Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Previous_Get : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Previous_Get_I (Node, Prev_Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Node->Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un noeud à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Node : pointeur sur le noeud à ajouter */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Add_L ( NDT_Root * Root, NDT_Node * Node ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Add : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Add_I (Root, Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un noeud dans une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud à supprimer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Remove_L ( NDT_Node * Node ) +{ + DST_Status rc; + int Locked; + NDT_Root * Root = Node->Root; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Remove : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Remove_I (Node); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Recherche un noeud dans un arbre et retourne le pointeur sur le noeud */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de l'abre */ +/* (O) Node : adresse du pointeur sur le noeud à récuperer */ +/* (I) Value : pointeur sur la valeur à rechercher */ +/* (I) Data : pointeur de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Find_L ( NDT_Root * Root, NDT_Node ** Node, void * Value, void * Data ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en lecture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_READ, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Node_Find : unable to lock the data structure for reading"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Node_Find_I (Root, Node, Value, Data); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Allocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (O) Value : adresse d'un pointeur sur la valeur à allouer */ +/* (I) ... : arguments relatifs à l'allocation de la valeur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Alloc_L ( NDT_Root * Root, void ** Value, ... ) +{ + DST_Status rc; + va_list Args; + + /* Récupération des arguments pour l'allocation de la valeur */ + + va_start (Args, Value); + + /* Appel du manager */ + + rc = ND_Manager_Exec (Root->Manager, NDD_CMD_MAKE_VALUE, Root, Value, Args); + + va_end (Args); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une valeur à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à ajouter à la structure de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Add_L ( NDT_Root * Root, void * Value ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Add : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + /* Ajout de la valeur */ + + rc = DS_Value_Add_I (Root, Value); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression du premier noeud correspondant à une valeur donnée */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Reference_Value : pointeur sur la valeur de référence */ +/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Remove_L ( NDT_Root * Root, void * Reference_Value, void ** Removed_Value ) +{ + DST_Status rc; + int Locked; + + /* Verrouillage de la data structure en écriture */ + + rc = DS_DataStruct_Lock_I (Root, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : unable to lock the data structure for writing"); + DS_Error_Print (); + + return rc; + } + + rc = DS_Value_Remove_I (Root, Reference_Value, Removed_Value); + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) DS_DataStruct_Unlock_I (Root); + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Free_L ( NDT_Root * Root, void * Value ) +{ + return ND_Value_Free (Root, Value); +} + +/*------------------------------------------------------------------------------*/ +/* Allocation de mémoire pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Size : taille mémoire à allouer */ +/* (O) Ptr : adresse du pointeur sur la zone de données allouée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Alloc_L ( NDT_Root * Root, size_t Size, void ** Ptr ) +{ + return DS_DataStruct_Alloc (Size, Ptr, Root->User); +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une ressource pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Ptr : pointeur sur la zone à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Free_L ( NDT_Root * Root, void * Ptr ) +{ + return DS_DataStruct_Free (Ptr, Root->User); +} + +/*------------------------------------------------------------------------------*/ +/* FONCTIONS SECURISEES (DS_MODE = 0) */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Ouverture d'une instance de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance de la librairie */ +/* (I) Context : nom du contexte */ +/* (I) Debug_Mode : mode d'affichage des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Open_CL ( int Instance, const char * Context, DST_Flags Debug_Mode ) +{ + return DS_Library_Open_I (Instance, Context, Debug_Mode ); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture de l'instance de la librairie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Close_CL ( void ) +{ + return DS_Library_Close_I (); +} + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Library_Stderr_Set_CL ( FILE * Out ) +{ + return DS_Library_Stderr_Set_I (Out); +} + +/*------------------------------------------------------------------------------*/ +/* Création / ouverture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) DS_Name : nom de la structure */ +/* (O) Root : adresse du pointeur sur la racine de la structure */ +/* (I) Type : type de la structure de données */ +/* (I) Manager_FileName : nom du fichier qui définit les fonctions manager */ +/* (I) Segment_Size : taille ds segments du heap sous-jacent */ +/* (I) Open_Mode : mode d'ouverture de la structure */ +/* (I) Own_Values : indique si la structure possède ses valeurs */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Open_CL ( const char * DS_Name, NDT_Root ** Root,\ + NDT_DataStruct_Type Type, const char * Manager_FileName, \ + size_t Segment_Size, DST_Flags Open_Mode, int Own_Values ) +{ + if (!DS_Name) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the data structure name is undefined"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the root address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (Open_Mode & (DSD_CREATE | DSD_NEW) && !Manager_FileName) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Open : the manager file name must be defined in creation mode"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Open_I (DS_Name, Root, Type, Manager_FileName, Segment_Size, Open_Mode, Own_Values); +} + +/*------------------------------------------------------------------------------*/ +/* Verrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Lock_Mode : type de verrou à poser sur la structure */ +/* (O) Locked : verrou effectif (TRUE ou FALSE) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Lock_CL ( NDT_Root * Root, DST_Flags Lock_Mode, int * Locked ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Lock : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Locked) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Lock : the lock indicator address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Lock_I (Root, Lock_Mode, Locked); +} + +/*------------------------------------------------------------------------------*/ +/* Déverrouillage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Unlock_CL ( NDT_Root * Root ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Unlock : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Unlock_I (Root); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à fermer */ +/* (I) Close_Mode : mode de fermeture de la structure (destruction ou non) */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Close_CL ( NDT_Root * Root, DST_Flags Close_Mode ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Close : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Close_I (Root, Close_Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Affiche les informations d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root: pointeur sur la racine de la structure de données */ +/* (I) Out : flux de sortie de l'affichage */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Info_Print_CL ( NDT_Root * Root, FILE * Out ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Info_Print : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Out) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Info_Print : the out stream is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Info_Print_L (Root, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Réorganisation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à réorganiser */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Reorg_CL ( NDT_Root * Root ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Reorg : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Reorg_L (Root); +} + +/*------------------------------------------------------------------------------*/ +/* Parcours de tous les noeuds d'une structure de données et exécution d'une */ +/* commande sur chacun d'eux */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à parcourir */ +/* (I) Command : commande à exécuter sur chaque noeud traversé */ +/* (I) Data : pointeur de données utilisateur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Traverse_CL ( NDT_Root * Root, NDT_Command Command, void * Data ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Traverse : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Traverse_L (Root, Command, Data); +} + +/*------------------------------------------------------------------------------*/ +/* Conversion d'une structure de données d'un type en un autre */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Target_Type : type de structure cible */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Convert_CL ( NDT_Root * Root, NDT_DataStruct_Type Target_Type ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Convert : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Convert_L (Root, Target_Type); +} + +/*------------------------------------------------------------------------------*/ +/* Affichage d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données à afficher */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Print_CL ( NDT_Root * Root, FILE * Out ) +{ + return DS_DataStruct_Traverse_CL (Root, NDD_CMD_PRINT_VALUE, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Fonction de vérification / réparation d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ +/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ +/* (I) Out : flux de sortie du rapport */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Check_CL ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Nb_Detected || !Nb_Corrected) + { + sprintf (DS_Error_Msg, "Error : one of the error number address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Out) + { + sprintf (DS_Error_Msg, "Error : the out stream is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Check_I (Root, Nb_Detected, Nb_Corrected, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Affiche la structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure */ +/* (I) Out : flux de sortie */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Dump_CL ( NDT_Root * Root, FILE * Out ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Dump : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Out) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Dump : the out stream is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_DataStruct_Dump_L (Root, Out); +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du premier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ +/* (O) First_Node : adresse d'un pointeur sur le premier noeud à récupérer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_First_Get_CL ( NDT_Root * Root, NDT_Node ** First_Node ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Node_First_Get : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!First_Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_First_Get : the first node address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_First_Get_L (Root, First_Node); +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du dernier noeud d'une structure */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la data structure */ +/* (O) Last_Node : adresse d'un pointeur sur le dernier noeud */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Last_Get_CL ( NDT_Root * Root, NDT_Node ** Last_Node ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Node_Last_Get : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Last_Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Last_Get : the last node address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Last_Get_L (Root, Last_Node); +} +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud suivant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le suivant */ +/* (O) Next_Node : pointeur sur le noeud suivant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Next_Get_CL ( NDT_Node * Node, NDT_Node ** Next_Node ) +{ + if (!Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Next_Get : the node is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Next_Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Next_Get : the next node address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Next_Get_L (Node, Next_Node); +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du noeud précédant */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud dont on cherche le précédant */ +/* (O) Prev_Node : pointeur sur le noeud précédant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Previous_Get_CL ( NDT_Node * Node, NDT_Node ** Prev_Node ) +{ + if (!Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Previous_Get : the node is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Prev_Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Previous_Get : the previous node address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Previous_Get_L (Node, Prev_Node); +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un noeud à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Node : pointeur sur le noeud à ajouter */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Add_CL ( NDT_Root * Root, NDT_Node * Node ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Node_Add : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Add : the node is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Add_L (Root, Node); +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un noeud dans une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Node : pointeur sur le noeud à supprimer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Remove_CL ( NDT_Node * Node ) +{ + if (!Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Remove : the node is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Remove_L (Node); +} + +/*------------------------------------------------------------------------------*/ +/* Recherche un noeud dans un arbre et retourne le pointeur sur le noeud */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de l'abre */ +/* (O) Node : adresse du pointeur sur le noeud à récuperer */ +/* (I) Value : pointeur sur la valeur à rechercher */ +/* (I) Data : pointeur de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Node_Find_CL ( NDT_Root * Root, NDT_Node ** Node, void * Value, void * Data ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Node_Find : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Node) + { + sprintf (DS_Error_Msg, "Error DS_Node_Find : the node address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Value) + { + sprintf (DS_Error_Msg, "Error DS_Node_Find : the value is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Node_Find_L (Root, Node, Value, Data); +} + +/*------------------------------------------------------------------------------*/ +/* Allocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (O) Value : adresse d'un pointeur sur la valeur à allouer */ +/* (I) ... : arguments relatifs à l'allocation de la valeur */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Alloc_CL ( NDT_Root * Root, void ** Value, ... ) +{ + DST_Status rc; + va_list Args; + + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Value_Alloc : the structure root is null"); + DS_Error_Print (); + return DSS_ERRAPI; + } + + if (!Value) + { + sprintf (DS_Error_Msg, "Error DS_Value_Alloc : the value address is null"); + DS_Error_Print (); + return DSS_ERRAPI; + } + + /* Récupération des arguments pour l'allocation de la valeur */ + + va_start (Args, Value); + + /* Appel du manager */ + + rc = ND_Manager_Exec (Root->Manager, NDD_CMD_MAKE_VALUE, Root, Value, Args); + + va_end (Args); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une valeur à une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à ajouter à la structure de données */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Add_CL ( NDT_Root * Root, void * Value ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Value_Add : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Value) + { + sprintf (DS_Error_Msg, "Error DS_Value_Add : the value is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Value_Add_L (Root, Value); +} + +/*------------------------------------------------------------------------------*/ +/* Suppression du premier noeud correspondant à une valeur donnée */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Reference_Value : pointeur sur la valeur de référence */ +/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Remove_CL ( NDT_Root * Root, void * Reference_Value, void ** Removed_Value ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Reference_Value) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : the reference value is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Removed_Value) + { + sprintf (DS_Error_Msg, "Error DS_Value_Remove : the removed value adress is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Value_Remove_L (Root, Reference_Value, Removed_Value); +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une valeur d'une structure de données */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Value : pointeur sur la valeur à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Value_Free_CL ( NDT_Root * Root, void * Value ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Value_Free : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Value) + { + sprintf (DS_Error_Msg, "Error DS_Value_Free : the value is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Value_Free_L (Root, Value); +} + +/*------------------------------------------------------------------------------*/ +/* Allocation de mémoire pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Size : taille mémoire à allouer */ +/* (O) Ptr : adresse du pointeur sur la zone de données allouée */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Alloc_CL ( NDT_Root * Root, size_t Size, void ** Ptr ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Alloc : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (Size <= 0) + { + sprintf (DS_Error_Msg, "Error DS_Alloc : the allocation size must be > 0"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Ptr) + { + sprintf (DS_Error_Msg, "Error DS_Alloc : the data pointer address is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Alloc_L (Root, Size, Ptr); +} + +/*------------------------------------------------------------------------------*/ +/* Désallocation d'une ressource pour une structure de données : */ +/*------------------------------------------------------------------------------*/ +/* (I) Root : pointeur sur la racine de la structure de données */ +/* (I) Ptr : pointeur sur la zone à désallouer */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Free_CL ( NDT_Root * Root, void * Ptr ) +{ + if (!Root) + { + sprintf (DS_Error_Msg, "Error DS_Free : the structure root is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + if (!Ptr) + { + sprintf (DS_Error_Msg, "Error DS_Free : the data pointer is null"); + DS_Error_Print (); + + return DSS_ERRAPI; + } + + return DS_Free_L (Root, Ptr); +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS PRIVEES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Teste si une data structure a déjà été ouverte par le processus courant : */ +/*------------------------------------------------------------------------------*/ +/* (I) DS_Name : nom de la data structure */ +/* (O) Root : adresse du pointeur sur la racine de la structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_IsOpen ( const char * DS_Name, NDT_Root ** Root ) +{ + DST_Status rc; + DST_DataStruct To_Find; + NDT_Node * Node; + + To_Find.Name = DS_Name; + + rc = ND_Node_Find (OpenedDS_List, &Node, &To_Find, NULL); + + if (DS_ERROR(rc)) return rc; + + if (rc != NDS_OK) return DSS_NO; + + *Root = ((DST_DataStruct *)(Node->Value))->Root; + + return DSS_YES; +} + +/*------------------------------------------------------------------------------*/ +/* Fonction d'allocation attachée à une structure de données : */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Alloc ( size_t Size, void ** Ptr, void * Data ) +{ + DST_Status rc; + SMT_Heap * Heap; + int Locked; + DST_RootDesc * RootDesc = (DST_RootDesc *)Data; + char * Heap_Name = RootDesc->Heap_Name; + + rc = SM_Heap_IsOpen (Heap_Name, &Heap); + if (rc != SMS_YES) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Alloc : the data structure heap \"%s\" is not open", Heap_Name); + DS_Error_Print (); + + return rc; + } + + /* Verrouillage du heap en écriture */ + + rc = SM_Heap_Lock (Heap, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Alloc : unable to lock the data structure heap \"%s\" for writing", Heap_Name); + DS_Error_Print (); + + return rc; + } + + /* Allocation du chunk */ + + rc = SM_Chunk_Alloc (Heap, Size, Ptr); + if (rc != SMS_OK) + { + if (Locked == TRUE) SM_Heap_Unlock (Heap); + return rc; + } + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) SM_Heap_Unlock (Heap); + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fonction de désallocation attachée à une structure de données : */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Free ( void * Ptr, void * Data ) +{ + DST_Status rc; + SMT_Heap * Heap; + int Locked; + DST_RootDesc * RootDesc = (DST_RootDesc *)Data; + char * Heap_Name = RootDesc->Heap_Name; + + rc = SM_Heap_IsOpen (Heap_Name, &Heap); + if (rc != SMS_YES) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Free : the data structure heap \"%s\" is not open", Heap_Name); + DS_Error_Print (); + + return rc; + } + + /* Verrouillage de la data structure en écriture */ + + rc = SM_Heap_Lock (Heap, SMD_WRITE, &Locked); + if (rc != DSS_OK) + { + sprintf (DS_Error_Msg, "Error DS_DataStruct_Free : unable to lock the data structure heap \"%s\" for writing", Heap_Name); + DS_Error_Print (); + + return rc; + } + + /* Désallocation du chunk */ + + rc = SM_Chunk_Free (Heap, Ptr); + if (rc != SMS_OK) + { + if (Locked == TRUE) SM_Heap_Unlock (Heap); + return rc; + } + + /* Déverrouillage de la data structure si besoin */ + + if (Locked == TRUE) SM_Heap_Unlock (Heap); + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Routine d'affichage d'un message d'erreur */ +/*------------------------------------------------------------------------------*/ +void DS_Error_Print ( void ) +{ + if (DS_stderr) fprintf (DS_stderr, "%s\n", DS_Error_Msg); +} + +/*------------------------------------------------------------------------------*/ +/* Pour préfixer les noms de heap avec l'identifiant de la librairie */ +/*------------------------------------------------------------------------------*/ +static char * DS_Name_Prefix ( const char * Name ) +{ + static char Prefixed [256]; + + sprintf (Prefixed, "%s/%s", DS_PREFIX, Name); + + return Prefixed; +} + +/*------------------------------------------------------------------------------*/ +/* Création d'un sémaphore pour gérer l'ouverture d'une data structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Semaphore_Create ( NDT_Root * Root ) +{ + union semun Sem_Ctl; + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + /* Création du sémaphore */ + + RootDesc->OpenSemID = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL); + if (RootDesc->OpenSemID == -1) + { + switch (errno) + { + case ENOMEM: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Create : the amount of memory is not sufficient to create a new semaphore"); + break; + + case ENOSPC: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Create : the number of semaphores exceeds the system-imposed limit"); + break; + + default: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Create : unknown error (%d) while creating a semaphore", errno); + break; + } + + DS_Error_Print (); + + return DSS_ERRSEM; + } + + /* Initialisation du sémaphore à 0 */ + + Sem_Ctl.val = 0; + if (semctl (RootDesc->OpenSemID, 0, SETVAL, Sem_Ctl)) + { + sprintf (DS_Error_Msg, "Error DS_Semaphore_Create : unable to initialize the value of the semaphore %x", RootDesc->OpenSemID); + DS_Error_Print (); + + semctl (RootDesc->OpenSemID, 0, IPC_RMID, Sem_Ctl); + + return DSS_ERRSEM; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Opération sur un sémaphore */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Semaphore_Operate (int SemID, struct sembuf * Operations, unsigned int Nb_Oper) +{ + if (semop (SemID, Operations, Nb_Oper) == -1) + { + switch (errno) + { + case EAGAIN: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : the operation would result in suspension of the calling process but the operations have been defined in no wait mode"); + break; + + case EACCES: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : current process is not allowed to operate on semaphore %x", SemID); + break; + + case EIDRM: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : semaphore %x does not exist", SemID); + break; + + case EINTR: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : a signal was received while operating on semaphore %x", SemID); + return DSS_ERRSIG; + + case EINVAL: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : the semaphore key %x is incorrect or the number of operations which can be done in UNDO mode exceeds the system-imposed limit", SemID); + break; + + case ENOSPC: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : the maximum number of process which can operate on semaphore in UNDO mode has been reached"); + break; + + case ERANGE: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate: the value of semaphore %x has reached the system-imposed limit", SemID); + break; + + default: + sprintf (DS_Error_Msg, "Error DS_Semaphore_Operate : unknown error %d while operating on semaphore %x", errno, SemID); + break; + } + + DS_Error_Print (); + + return DSS_ERRSEM; + } + + return DSS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fonction manager de la liste des DS ouvertes */ +/*------------------------------------------------------------------------------*/ +NDT_Status DS_OpenedDS_List_Manager ( va_list Args ) +{ + NDT_Command Command = (NDT_Command) va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_COMP_VALUE) + { + DST_DataStruct * DataStruct1 = (DST_DataStruct *) va_arg (Args, void *); + DST_DataStruct * DataStruct2 = (DST_DataStruct *) va_arg (Args, void *); + long comp; + + va_end (Args); + + comp = strcmp (DataStruct1->Name, DataStruct2->Name); + + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + return NDS_EQUAL; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + DST_DataStruct * DataStruct = (DST_DataStruct *) va_arg (Args, void *); + + free (DataStruct->Name); + free (DataStruct); + } + + return NDS_OK; +} diff --git a/lib/libdatastr.doc b/lib/libdatastr.doc new file mode 100644 index 0000000000000000000000000000000000000000..0f7a4c23b9997a44ee0e5960bf2657c101d1054b GIT binary patch literal 101888 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%0A&Q?Rzs zes7t2Q;BOV(s&&vYJZsmO=9=_vWdsHXHJVr_CXFdjId-u{AGu(sdKi;WAHIaae3w|7t-q2%(z_HLEsge|z-4-P`S_2W!jf-n;JVr?hv!K@HQKm<;^xqka!^ z`>Wh^Z3V!cQc%6R_g;sR=o<*3Zy@BgrK*1)x3@;E->v~)0(Uk@TdzP-4hn{rGkQe9 z1UI*6>ck!+@fV-j2U1oO4JyViu3ub@REXYv-9Z|~K&+B0#GoYgu|fR%1`@s2^5`|F z@d_~@P`lO^)m;Y!D|%ef8^pFxD2K5TbT}~sST=uUP*yvG8!3I`s`gGgxonsflkORM zW97UD&6^+S?aE1ScdP95HSfV-P-q?ok$`1hljrrL zgdrQ2TMVaxSRhXr%jAXkc(klYnT>8{1xGfWVuYEPVH2ZyzlOXM!%G9rkk@c9OI2AK zt!C63-0ekhG*$9?4S&Z|iiwlN_kyqxWBWSNZ#J(1amUyvZ{>XgC0M#B4Ff%Yc3v~= zm7sWm1`Pn|GpovUPS*027|HiC-fY=2i(#@-B$*V<3~zuDc)n5!%C

G&v>mOm$*= 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 literal 0 HcmV?d00001 diff --git a/lib/libdatastr.h b/lib/libdatastr.h new file mode 100644 index 0000000..d27094a --- /dev/null +++ b/lib/libdatastr.h @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char * strdup ( const char * ); + +/* Compteur d'ouverture de la librairie */ + +unsigned int DS_Open_Counter = 0; + +/* Tous les heaps créés via la librairie LIBDATASTR seront préfixés par le nom suivant */ + +#define DS_PREFIX "DATASTR" + +/* Flux de sortie des messages d'erreur */ + +FILE * DS_stderr; + +/* + Pour gérer les ouvertures, fermetures ou destructions d'une data structure, on + opère sur un sémaphore (OpenSemID) rattaché à la description de la structure + qui comptabilise les processus ayant ouvert la data structure. +*/ + +struct sembuf DS_SemOp_Open [1] = { {0, 1, SEM_UNDO|IPC_NOWAIT} }; +struct sembuf DS_SemOp_Close [1] = { {0, -1, SEM_UNDO|IPC_NOWAIT} }; +struct sembuf DS_SemOp_Destroy [2] = { {0, -1, SEM_UNDO|IPC_NOWAIT}, {0, 0, SEM_UNDO|IPC_NOWAIT} }; + +typedef union semun { + int val; + struct semid_ds * buf; + unsigned short int * array; +} semun; + +/* Liste des data structure ouvertes par le processus courant */ + +NDT_Root * OpenedDS_List; + +typedef struct { + NDT_Root * Root; + char * Name; +} DST_DataStruct; + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* Fonctions privées de la librairie */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Création d'un sémaphore pour gérer l'ouverture d'une data structure */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Semaphore_Create (NDT_Root * Root); + +/*------------------------------------------------------------------------------*/ +/* Opération sur un sémaphore */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_Semaphore_Operate (int, struct sembuf *, unsigned int); + +/*------------------------------------------------------------------------------*/ +/* Fonction d'allocation attachée à une structure de données : */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Alloc ( size_t Size, void ** Ptr, void * Data ); + +/*------------------------------------------------------------------------------*/ +/* Fonction de désallocation attachée à une structure de données : */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_Free ( void * Ptr, void * Data ); + +/*------------------------------------------------------------------------------*/ +/* Routine d'affichage d'un message d'erreur */ +/*------------------------------------------------------------------------------*/ +void DS_Error_Print ( void ); + +/*------------------------------------------------------------------------------*/ +/* Pour préfixer les noms de heap avec l'identifiant de la librairie */ +/*------------------------------------------------------------------------------*/ +static char * DS_Name_Prefix (const char * Name); + +/*------------------------------------------------------------------------------*/ +/* Teste si une data structure a déjà été ouverte par le processus courant */ +/*------------------------------------------------------------------------------*/ +DST_Status DS_DataStruct_IsOpen (const char * DS_Name, NDT_Root ** Root); + +/*------------------------------------------------------------------------------*/ +/* Fonction manager de la liste des DS ouvertes */ +/*------------------------------------------------------------------------------*/ +NDT_Status DS_OpenedDS_List_Manager (va_list Args); diff --git a/util/dsbench.c b/util/dsbench.c new file mode 100644 index 0000000..3bbff7a --- /dev/null +++ b/util/dsbench.c @@ -0,0 +1,529 @@ +#define DS_MODE 2 + +#include +#include +#include +#include +#include +#include +#include + +extern char * strdup ( const char *); + +#define QUIT 0 +#define CREATE_STRUCT 1 +#define OPEN_STRUCT 2 +#define CLOSE_STRUCT 3 +#define DELETE_STRUCT 4 +#define ADD_VALUE 5 +#define REMOVE_VALUE 6 +#define FIND_VALUE 7 +#define CHG_LIST_TYPE 8 +#define CONVERT_TO_TREE 9 +#define CONVERT_TO_LIST 10 +#define REORG 11 +#define INFO 12 +#define SHOW 13 +#define CHECK 14 + +#define MANAGER_FILE_NAME "dsbench.so" + +char DataStruct_Name [100]; +char menu [1000]; +char buf [100]; +long int random ( void ); +NDT_Status Module_Manager (va_list Args); +void init_menu ( NDT_Root *); +int print_menu ( NDT_Root *); + +/* Mesure des temps d'exécution */ + +typedef struct { + double sec; + struct timeval start; + struct timeval stop; +} T_Cpt; + +#define t_start(x) {gettimeofday (&(x.start), NULL);} +#define t_stop(x) {gettimeofday (&(x.stop), NULL); x.sec = (double)(x.stop.tv_sec) - (double)(x.start.tv_sec) + ((double)(x.stop.tv_usec) - (double)(x.start.tv_usec)) / 1000000;} + +T_Cpt t_exec; + +/* Définition des valeurs attachées aux noeuds de la structure */ + +typedef struct { + int Id; + char * Nom; +} T_Module; + +int main (int argc, char ** argv) +{ + NDT_Root * Root = NULL; + char * tmp; + int n, m, i, j; + int choice, Nb_Removed, Locked; + int Nb_Detected, Nb_Corrected; + T_Module * Module, Ref_Module; + NDT_Node * Node; + + if (argc > 1 && !strcmp (argv[1], "-h")) + { + fprintf (stdout, "Usage : %s [-h] [instance [context]]\n", argv[0]); + return 0; + } + + if (DS_Library_Open (0, NULL, DSD_DEBUG_ALL) != NDS_OK) return 0; + + choice = print_menu (Root); + + while (choice != QUIT) + { + switch (choice) + { + case CREATE_STRUCT: + fprintf (stdout, "\nNom de la structure à créer ? "); + gets (DataStruct_Name); + + if (DS_DataStruct_Open (DataStruct_Name, &Root, NDD_DS_LIST | NDD_MN_FIFO, \ + MANAGER_FILE_NAME, 0, DSD_CREATE, TRUE) != DSS_OK) + printf ("\nNOK\n"); + else + { + strcpy (Root->Manager, "Module_Manager"); + printf ("\nStructure créée : OK\n"); + } + + break; + + case DELETE_STRUCT: + if (DS_DataStruct_Close (Root, DSD_DESTROY) == DSS_KO) printf ("\nNOK\n"); + else + { + printf ("\nStructure détruite : OK\n"); + Root = NULL; + } + + break; + + case OPEN_STRUCT: + fprintf (stdout, "\nNom de la structure à ouvrir ? "); + gets (DataStruct_Name); + + if (DS_DataStruct_Open (DataStruct_Name, &Root, 0, NULL, 0, DSD_OPEN, TRUE) == NDS_KO) + printf ("\nNOK\n"); + else + printf ("\nStructure ouverte : OK\n"); + + break; + + case CLOSE_STRUCT: + if (DS_DataStruct_Close (Root, DSD_CLOSE) == DSS_KO) printf ("\nNOK\n"); + else + { + printf ("\nStructure fermée : OK\n"); + Root = NULL; + } + + break; + + case FIND_VALUE: + fprintf (stdout, "\nPlage de recherche (?->?) : "); + gets (buf); + tmp = strstr (buf, "->"); + if (tmp != NULL) + { + * tmp = '\0'; + n = atoi (buf); + tmp++; + tmp++; + m = atoi (tmp); + if (m < n) + { + printf ("\nEntrées non valides\n"); + break; + } + } + else + { + printf ("\nEntrées non valides\n"); + break; + } + + DS_DataStruct_Lock (Root, DSD_READ, &Locked); + + i = n; + j = m + 1; + t_start (t_exec); + while (i < j) + { + Module->Id = n + (random () % m); + DS_Node_Find (Root, &Node, Module, NULL); + i++; + } + t_stop (t_exec); + + DS_DataStruct_Unlock (Root); + + fprintf (stdout, "\n%d valeur(s) recherchée(s) en %.4f sec (%.2f select/sec)\n", \ + m - n + 1, t_exec.sec, (m - n + 1) / t_exec.sec); + break; + + case ADD_VALUE: + fprintf (stdout, "\nPlage des valeurs à ajouter (?->?) : "); + gets (buf); + tmp = strstr (buf, "->"); + if (tmp != NULL) + { + * tmp = '\0'; + n = atoi (buf); + tmp++; + tmp++; + m = atoi (tmp); + if (m < n) + { + printf ("\nEntrées non valides\n"); + break; + } + } + else + { + printf ("\nEntrées non valides\n"); + break; + } + + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + + fprintf (stdout, "\nOrdre d'ajout (croissant=0 décroissant=1) ? "); + gets (buf); + choice = atoi (buf); + if (choice == 0) + { + i = n; + j = m + 1; + t_start (t_exec); + while (i < j) + { + if (DS_Value_Alloc (Root, (void **)&Module, "x", i) == NDS_OK) DS_Value_Add (Root, Module); + i++; + } + t_stop (t_exec); + } + else + { + i = m; + j = n - 1; + t_start (t_exec); + while (i > j) + { + if (DS_Value_Alloc (Root, (void **)&Module, "x", i) == NDS_OK) DS_Value_Add (Root, Module); + i--; + } + t_stop (t_exec); + } + + DS_DataStruct_Unlock (Root); + + fprintf (stdout, "\n%d valeur(s) ajoutée(s) en %.4f sec (%.2f ajouts/sec)\n", m - n + 1, \ + t_exec.sec, (m - n + 1) / t_exec.sec); + break; + + case REMOVE_VALUE: + Nb_Removed = 0; + fprintf (stdout, "\nPlage des valeurs à supprimer (?->?) : "); + gets (buf); + tmp = strstr (buf, "->"); + if (tmp != NULL) + { + * tmp = '\0'; + n = atoi (buf); + tmp++; + tmp++; + m = atoi (tmp); + if (m < n) + { + printf ("\nEntrées non valides\n"); + break; + } + } + else + { + printf ("\nEntrées non valides\n"); + break; + } + + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + + fprintf (stdout, "\nOrdre de suppression (croissant=0 décroissant=1) ? "); + gets (buf); + choice = atoi (buf); + if (choice == 0) + { + i = n; + j = m + 1; + t_start (t_exec); + while (i < j) + { + Ref_Module.Id = i; + if (DS_Value_Remove (Root, &Ref_Module, (void **)&Module) == NDS_OK) + { + DS_Value_Free (Root, Module); + Nb_Removed++; + } + i++; + } + t_stop (t_exec); + } + else + { + i = m; + j = n - 1; + t_start (t_exec); + while (i > j) + { + Ref_Module.Id = i; + if (DS_Value_Remove (Root, &Ref_Module, (void **)&Module) == NDS_OK) + { + DS_Value_Free (Root, Module); + Nb_Removed++; + } + i--; + } + t_stop (t_exec); + } + + DS_DataStruct_Unlock (Root); + + fprintf (stdout, "\n%d valeur(s) supprimée(s) en %.4f sec (%.2f suppressions/sec)\n",\ + Nb_Removed, t_exec.sec, (m - n + 1) / t_exec.sec); + break; + + case CHG_LIST_TYPE: + fprintf (stdout, "\nType de liste (FIFO=0 ; FILO=1 ; triée=2) ? "); + gets (buf); + choice = atoi (buf); + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + switch (choice) + { + case 0: + Root->Type = NDD_DS_LIST | NDD_MN_FIFO; + break; + case 1: + Root->Type = NDD_DS_LIST | NDD_MN_FILO; + break; + case 2: + Root->Type = NDD_DS_LIST | NDD_MN_ORDERED; + break; + default: + printf ("\nChoix non valide\n"); + break; + } + DS_DataStruct_Unlock (Root); + break; + + case REORG: + t_start (t_exec); + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + DS_DataStruct_Reorg (Root); + DS_DataStruct_Unlock (Root); + t_stop (t_exec); + fprintf (stdout, "\nRéorganisation de la structure en %.4f sec\n", t_exec.sec); + break; + + case CONVERT_TO_LIST: + t_start (t_exec); + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + DS_DataStruct_Convert (Root, NDD_DS_LIST | NDD_MN_ORDERED); + DS_DataStruct_Unlock (Root); + t_stop (t_exec); + fprintf (stdout, "\nConversion arbre vers liste en %.4f sec\n", t_exec.sec); + break; + + case CONVERT_TO_TREE: + t_start (t_exec); + DS_DataStruct_Lock (Root, DSD_WRITE, &Locked); + DS_DataStruct_Convert (Root, NDD_DS_TREE | NDD_MN_AUTO_EQU); + DS_DataStruct_Unlock (Root); + t_stop (t_exec); + fprintf (stdout, "\nConversion liste vers arbre en %.4f sec\n", t_exec.sec); + break; + + case INFO: + DS_DataStruct_Lock (Root, DSD_READ, &Locked); + DS_DataStruct_Info_Print (Root, stdout); + DS_DataStruct_Unlock (Root); + break; + + case SHOW: + DS_DataStruct_Lock (Root, DSD_READ, &Locked); + DS_DataStruct_Dump (Root, stdout); + DS_DataStruct_Unlock (Root); + break; + + case CHECK: + Nb_Corrected = Nb_Detected = 0; + ND_DataStruct_Check (Root, &Nb_Detected, &Nb_Corrected, stderr); + break; + + default: + fprintf (stdout, "\nChoix %d non défini\n", choice); + } + choice = print_menu (Root); + } + DS_Library_Close (); + return 0; +} + + +NDT_Status Module_Manager (va_list Args) +{ + NDT_Command Command = (NDT_Command) va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + T_Module ** Module = va_arg (Args, T_Module **); + va_list Value_Args = va_arg (Args, va_list); + char * Nom = va_arg (Value_Args, char *); + int Id = va_arg (Value_Args, int); + if (DS_Alloc (Root, sizeof (T_Module) + strlen (Nom) + 1, (void **)Module) == DSS_OK) + { + (* Module)->Id = Id; + (* Module)->Nom = (char *)((size_t)(*Module) + sizeof (T_Module)); + strcpy ((* Module)->Nom, Nom); + } + return (NDS_OK); + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + T_Module * Module = (T_Module *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + fprintf (Out, "Id Module=%d Nom Module='%s'", Module->Id, Module->Nom); + return (NDS_OK); + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + T_Module * value = (T_Module *) va_arg (Args, void *); + DS_Free (Root, value); + return (NDS_OK); + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + char * Root_Type; + DST_RootDesc * RootDesc; + + switch ((int)(Root->Type & NDD_DS_MSK)) + { + case NDD_DS_LIST : + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_ORDERED : Root_Type = strdup ("liste triée"); break; + case NDD_MN_FILO : Root_Type = strdup ("liste FILO"); break; + case NDD_MN_FIFO : Root_Type = strdup ("liste FIFO"); break; + default: Root_Type = strdup ("inconnu"); break; + } + break; + + case NDD_DS_TREE : + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = strdup ("arbre auto-équilibré"); break; + default: Root_Type = strdup ("arbre non auto-équilibré"); break; + } + break; + + default: Root_Type = strdup ("inconnu"); break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, \ + "\nStructure de type %s :\n\t- Nom = %s\n\t- Manager = %s\n\t- Nombre de modules = %ld\n", \ + Root_Type, RootDesc->Heap_Name, RootDesc->Manager_FileName, Root->Node_Number); + + if ((Root->Type & NDD_DS_MSK) == NDD_DS_TREE) + fprintf (Out, "\t- Profondeur maxi = %ld\n\t- Profondeur mini = %ld\n\t- Différence maximale autorisée = %ld\n\t- Nombre d'équilibrages = %ld\n", \ + Root->Max_Depth, Root->Min_Depth, Root->Max_Dif, Root->Nb_Equ); + + if (Root_Type) free (Root_Type); + + return (NDS_OK); + } + + if (Command == NDD_CMD_COMP_VALUE) + { + T_Module * Value1, * Value2; + long comp; + + Value1 = (T_Module *) va_arg (Args, void *); + Value2 = (T_Module *) va_arg (Args, void *); + va_end (Args); + comp = Value1->Id - Value2->Id; + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + return NDS_EQUAL; + } + return (NDS_OK); +} + +void init_menu ( NDT_Root * Root ) +{ + sprintf (menu, "Menu :\n"); + sprintf (buf, " - %d) %-30s\n", QUIT, "Quitter"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s", CREATE_STRUCT, "Création de structure"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", OPEN_STRUCT, "Ouverture de structure"); + strcat (menu, buf); + if (Root != NULL) + { + sprintf (buf, " - %d) %-30s", CLOSE_STRUCT, "Fermer la structure"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", DELETE_STRUCT, "Détruire la structure"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s", ADD_VALUE, "Ajout de valeurs"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", REMOVE_VALUE, "Suppression de valeurs"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", FIND_VALUE, "Recherche de valeurs aléatoires"); + strcat (menu, buf); + if (ND_IS_LIST(Root)) + { + sprintf (buf, " - %d) %-30s", CHG_LIST_TYPE, "Changement de type de liste"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", CONVERT_TO_TREE, "Conversion en arbre"); + strcat (menu, buf); + } + else + { + sprintf (buf, " - %d) %-30s", CONVERT_TO_LIST, "Conversion en liste triée"); + strcat (menu, buf); + } + sprintf (buf, " - %d) %-30s\n", REORG, "Réorganisation"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s", INFO, "Informations sur la structure"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", SHOW, "Affichage de la structure"); + strcat (menu, buf); + sprintf (buf, " - %d) %-30s\n", CHECK, "Vérification de la structure"); + strcat (menu, buf); + } +} + +int print_menu ( NDT_Root * Root ) +{ + init_menu (Root); + fprintf (stdout, "\n---------------------------------------------------------\n"); + fprintf (stdout, menu); + buf [0] = '\0'; + while (buf [0] == '\0') + { + printf ("\nChoice ? "); + gets (buf); + } + return atoi (buf); +} diff --git a/util/dsbench.xls b/util/dsbench.xls new file mode 100644 index 0000000000000000000000000000000000000000..d0e3d6aaee81532c195de84c7d9b05833771ff8e GIT binary patch literal 17408 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 literal 0 HcmV?d00001 diff --git a/util/dsdump.c b/util/dsdump.c new file mode 100644 index 0000000..f43b107 --- /dev/null +++ b/util/dsdump.c @@ -0,0 +1,51 @@ +#define SM_MODE 1 + +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char ** argv) +{ + NDT_Node * Node; + + SM_Library_Open (0, NULL, SMD_OPEN | SMD_DEBUG_ALL); + + ND_Node_First_Get (SM_Base->MHR, &Node); + + while (Node) + { + char * ptr; + SMT_MHH * MHH = ( SMT_MHH *)(Node->Value); + + if ((ptr = strstr (MHH->Name, "DATASTR/")) != NULL) + { + int Locked; + SMT_Heap * Heap; + SMT_DSH * DSH; + NDT_Root * Root; + DST_RootDesc * RootDesc; + + SM_Heap_Open (ptr, &Heap, 0, SMD_OPEN | SMD_READ, &Locked); + + DSH = ( SMT_DSH *)(MHH->DSR->Head->Value); + + Root = ( NDT_Root *)((size_t)(DSH->Start) + sizeof (NDT_Node) + sizeof (SMT_Chunk)); + RootDesc = (DST_RootDesc *)(Root->User); + + fprintf (stdout, "Data Structure \"%s\":\n\t- Manager = %s\n\t- Open semaphore = %d\n", ptr + strlen ("datastr/"), RootDesc->Manager_FileName, RootDesc->OpenSemID); + + SM_Heap_Close (Heap); + } + + ND_Node_Next_Get (Node, &Node); + } + + SM_Library_Close (SMD_CLOSE); + + return 0; +} +