commit 43e6f0ee891e06240c007d47918b7f6498a12720 Author: smas Date: Mon Jul 31 13:15:35 2000 +0000 Première version diff --git a/lib/liblog.3 b/lib/liblog.3 new file mode 100644 index 0000000..91172b5 --- /dev/null +++ b/lib/liblog.3 @@ -0,0 +1,638 @@ +'\" t +.\" @(#)LIBLOG.3 1.0 00/07/04 SMA; +.TH LIBLOG 3 "07 Apr 2000" +.SH NOM +LIBLOG (librairie d'interface avec le systeme de suivi et de pilotage) +.SH SYNOPSIS +.LP +.BI "cc [flag ...] file ... -lver -ldl -lnode -lshmem -ldatastr -lmsg -ladm -lgen -llog [library ...]" +.LP +.BI "#include " +.LP +.BI "LOGT_Status LOG_Library_Open ( int " Instance ", LOGT_Flags " Open_Mode ");" +.LP +.BI "LOGT_Status LOG_Library_Close ( LOGT_Flags " Close_Mode ");" +.LP +.BI "LOGT_Status LOG_Library_Stderr_Set ( FILE * " Out ");" +.LP +.BI "LOGT_Status LOG_Channel_Open ( LOGT_Channel ** " Channel ", int " Pid ", int " Channel_Id ", char * " Module_Name ", char * " Master_Module_Name ");" +.LP +.BI "LOGT_Status LOG_Channel_Enter ( LOGT_Channel * " Channel ", char * " Sub_Module_Name ");" +.LP +.BI "LOGT_Status LOG_Channel_Leave ( LOGT_Channel * " Channel ", char * " Sub_Module_Name ");" +.LP +.BI "LOGT_Status LOG_Channel_Close ( LOGT_Channel * " Channel ");" +.LP +.BI "LOGT_Status LOG_RTab_Alloc ( LOGT_RTab ** " Rtab ", char * " Name " );" +.LP +.BI "LOGT_Status LOG_RTab_Setup ( LOGT_RTab * " RTab ", LOGT_RuleClass " Rule_Class ", LOGT_Rule " Rule ", LOGT_Rooting " Value ");" +.LP +.BI "LOGT_Status LOG_RTab_Add ( LOGT_Channel * " Channel ", LOGT_RTab * " RTab ");" +.LP +.BI "LOGT_Status LOG_RTab_Remove ( LOGT_Channel * " Channel ", LOGT_RTab * " RTab ");" +.LP +.BI "LOGT_Status LOG_RTab_Free ( LOGT_RTab * " RTab ");" +.LP +.BI "LOGT_Status LOG_Trigger_Add ( LOGT_Trigger ** " Trigger ", LOGT_Channel * " Channel ", LOGT_RTab * " RTab ", char * " Event_Type ", LOGT_Flags " Trigger_Mode ");" +.LP +.BI "LOGT_Status LOG_Trigger_Remove ( LOGT_Trigger * " Trigger ");" +.LP +.BI "LOGT_Status LOG_Event_Send ( LOGT_Channel * " Channel ", LOGT_RC * " Return_Code ", char * " Cd_Support ", va_list " Data ");" +.LP +.BI "LOGT_RC LOG_Event_External_Send ( LOGT_Channel * " Channel ", char * " Cd_Support ", char * " Data ");" +.LP +.BI "LOGT_Status LOG_Event_Info_Get ( LOGT_Channel * " Channel ", LOGT_Info * " Info ", va_list " Data ");" +.LP +.BI "LOGT_Status LOG_Event_Cpt_Get ( LOGT_Channel * " Channel ", int * " Cpt "[LOGD_RC_SIZE], char * " Reg_Expr ");" +.LP +.SH FONCTIONS +.LP +.BI "LOGT_Status LOG_Library_Open ( int " Instance ", LOGT_Flags " Open_Mode ");" +.LP +.RS 3 +La librairie LIBLOG met en place des ressources partagees par tous les traitements qui utilise la meme instance de la librairie LIBLOG : +.LP +.RS 3 +- les tables de routage systeme (GMRT et GDRT) +.LP +- le cache des modules +.LP +- le cache des formats d'evenement +.LP +- la queue de messages pour inserer les evenements en base +.RS -3 +.LP +Cette fonction permet d'acceder a ces ressources partagees pour une instance particuliere de la librairie: +.LP +.RS 3 +- en creation si +.I Open_Mode +vaut +.B LOGD_CREATE +.LP +- en ouverture simple si +.I Open_Mode +vaut +.B LOGD_OPEN +.RS -3 +.LP +.I NB +: l'indicateur d'ouverture +.I Open_Mode +pourra etre combinee avec un mode de debugging ( +.B MSGD_DEBUG_NONE +: aucun message d'erreur n'est affiche +.LP +.B MSGD_DEBUG +: les messages d'erreur generes par la librairie LIBMSG sont affiches sur la sortie standard d'erreur +.LP +.B MSGD_DEBUG_ALL +: les messages d'erreur generes par toutes les librairies sous-jacentes a la LIBMSG sont affiches sur la sortie standard d'erreur +.LP +.I NB +: l'appel a cette fonction est obligatoire avant d'utiliser toute autre fonction de la librairie LIBLOG. +.LP +Le mode +.B LOGD_CREATE +est exclusivement reserve aux administrateurs ! +.LP +.RS -3 +.BI "LOGT_Status LOG_Library_Close ( LOGT_Flags " Close_Mode " );" +.LP +.RS 3 +Cette fonction permet de fermer ou de supprimer les ressources partagees de l'instance qu a ete ouverte : +.LP +.RS 3 +- Suppression si +.I Close_Mode +vaut +.B LOGD_DESTROY +.LP +- Fermeture simple si +.I Close_Mode +vaut +.B LOGD_CLOSE +.RS -3 +.LP +.I NB +: la fermeture de la librairie est absolument necessaire une fois qu'un traitement a fini de l'utiliser. +.LP +Le mode +.B LOGD_DESTROY +est exclusivement reserve aux administrateurs ! +.LP +.RS -3 +.BI "LOGT_Status LOG_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 "LOGT_Status LOG_Channel_Open ( LOGT_Channel ** " Channel ", int " Pid ", int " Channel_Id ", char * " Module_Name ", char * " Master_Module_Name ");" +.LP +.RS 3 +Cette fonction permet de creer un channel a travers lequel des evenements seront envoyes au systeme de suivi. +Elle requiert les arguments suivants : +.RS 3 +.LP +* (Out) +.I Channel +: l'adresse du pointeur sur le channel a creer +.LP +* (In) +.I Pid +: l'identifiant du processus proprietaire du channel +.LP +* (In) +.I Channel_Id +: l'identifiant du channel +.LP +* (In) +.I Module_Name +: le nom du module proprietaire du channel +.LP +* (In) +.I Master_Module_Name +: le nom du module maitre (facultatif) +.RS -3 +.LP +.I Pour info +: +Le nom du module proprietaire du channel permet de connaitre le traitement qui est a l'origine des evenements qui sont envoyes au suivi. Le nom du module maitre permet de connaitre le contexte de lancement de ce traitement. +.LP +Le numero du processus permet de distinguer differents processus realisant un meme traitement. +.LP +L'identifiant du channel permet de distinguer les differents channels d'un meme processus. +.LP +.I NB +: si le numero de processus passe en parametre vaut 0, alors c'est le processus courant qui sera considere comme processus proprietaire. +Ce parametre doit surtout etre renseigne pour les programmes shell, afin que ce ne soit pas le numero de processus demon qui soit pris en compte. +.LP +Par convention, en fonctionnement mono-thread, l'identifiant du channel sera fixe a 0. En fonctionnement multi-thread, l'utilisateur est libre de fixer ce parametre comme il le veut. +.LP +.I NB +: si le nom du module maitre vaut NULL, alors il sera renseigne avec le nom du module proprietaire du channel. +.LP +.RS -3 +.BI "LOGT_Status LOG_Channel_Enter ( LOGT_Channel * " Channel ", char * " Sub_Module_Name " );" +.LP +.RS 3 +Cette fonction permet d'affecter un sous-module a un channel. +Un sous-module correspond en general au nom d'une fonction du traitement. Il permet de mieux identifier la partie du traitement qui genere les evenements. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (In) +.I Channel +: le pointeur sur le channel de communication +.LP +* (In) +.I Sub_Module_Name +: le nom du sous-module a attacher au channel +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_Channel_Leave ( LOGT_Channel * " Channel ", char * " Sub_Module_Name " );" +.LP +.RS 3 +Cette fonction permet de supprimer un sous-module d'un channel. +Le sous-module qui lui avait ete precedemment affecte est devient alors le sous-module actif. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (In) +.I Channel +: le pointeur sur le channel de communication +.LP +* (In) +.I Sub_Module_Name +: le nom du sous-module a supprimer du channel +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_Channel_Close ( LOGT_Channel * " Channel " );" +.LP +.RS 3 +Cette fonction permet de fermer un channel. +.LP +.I Channel +est un pointeur sur le channel a fermer +.LP +.RS -3 +.BI "LOGT_Status LOG_RTab_Alloc ( LOGT_RTab ** " Rtab ", char * " Name " );" +.LP +.RS 3 +Cette fonction permet de creer une table de routage utilisateur. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (Out) RTab +: adresse d'un pointeur sur la table de routage a creer. +.LP +* (In) Name +: nom de la table de routage. +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_RTab_Setup ( LOGT_RTab * " RTab ", LOGT_RuleClass " Rule_Class ", LOGT_Rule " Rule ", LOGT_Rooting " Value " );" +.LP +.RS 3 +Cette fonction permet de parametrer une table de routage utilisateur, par ajout d'une regle de routage. +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I RTab +: un pointeur sur la table de routage +.LP +* (In) +.I Rule_Class +: la classe de la nouvelle regle +.LP +* (In) +.I Rule +: la nouvelle regle +.LP +* (In) +.I Value +: la valeur de la nouvelle regle +.RS -3 +.LP +La classe de regle designe la maniere de selectionner les types d'evenement concernes par la nouvelle regle : +.LP +.RS 3 +- +.B LOGD_SELECT_ALL +: selection de tous les types d'evenements +.LP +- +.B LOGD_SELECT_GRV +: selection des types d'evenement selon leur gravite +.LP +- +.B LOGD_SELECT_RC +: selection des types d'evenement selon le code retour qui y est associe +.LP +- +.B LOGD_SELECT_TYPE +: selection des types d'evenement selon leur nom +.RS -3 +.LP +La regle depend de la classe de regle choisie: +.LP +.RS 3 +- NULL pour la classe +.B LOGD_SELECT_ALL +.LP +- code gravite pour la classe +.B LOGD_SELECT_GRV +.LP +- code retour pour la classe +.B LOGD_SELECT_RC +.LP +- nom du type d'evenement (expression reguliere) pour la classe +.B LOGD_SELECT_TYPE +.RS -3 +.LP +La valeur de la regle est le type de routage a appliquer aux types d'evenement concernes par la regle : +.RS 3 +.LP +- +.B LOGD_NULL +: routage vers /dev/null (aucun traitement de l'evenement) +.LP +- +.B LOGD_STDERR +: affichage de l'evenement sur la sortie standard d'erreur +.LP +- +.B LOGD_DATABASE +: insertion de l'evenement dans la base de donnees du suivi +.LP +- +.B LOGD_DEFAULT +: routage par defaut +.LP +- +.B LOGD_PREVIOUS +: routage defini dans la table de routage precedente +.RS -3 +.LP +Pour parametrer une table de routage utilisateur, on commencera par definir les regles les plus generales (LOGD_ALL) et finir avec les regles les plus specifiques. +.LP +.RS -3 +.BI "LOGT_Status LOG_RTab_Add ( LOGT_Channel * " Channel ", LOGT_RTab * " RTab " );" +.LP +.RS 3 +Cette fonction permet d'affecter une nouvelle table de routage utilisateur a un channel. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I RTab +: un pointeur sur la table de routage +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_RTab_Remove ( LOGT_Channel * " Channel ", LOGT_RTab * " RTab " );" +.LP +.RS 3 +Cette fonction permet de supprimer l'association d'une table de routage utilisateur a un channel. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I RTab +: un pointeur sur la table de routage +.RS -3 +.LP +L'utilisateur pourra utiliser la constante LOGD_TOP_RTAB comme deuxieme argument, pour supprimer la table de routage de tete (la plus recemment associee au channel). +.LP +.RS -3 +.BI "LOGT_Status LOG_RTab_Free ( LOGT_RTab * " RTab " );" +.LP +.RS 3 +Cette fonction permet de supprimer une table de routage utilisateur. +.LP +.I RTab +est un pointeur sur la table de routage a supprimer. +.LP +NB : avant de supprimer une table de routage, on verifiera qu'elle n'est attachee a aucun channel. +.LP +.RS -3 +.BI "LOGT_Status LOG_Trigger_Add ( LOGT_Trigger ** " Trigger ", LOGT_Channel * " Channel ", LOGT_RTab * "RTab ", char * " Event_Type ", LOGT_Flags " Trigger_Mode " );" +.LP +.RS 3 +Cette fonction permet d'ajouter un trigger a un channel. +.LP +Elle requiert les arguments suivants : +.RS 3 +.LP +* (Out) +.I Trigger +: l'adresse du pointeur sur le nouveau trigger +.LP +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I RTab +: un pointeur sur la table de routage concernee +.LP +* (In) +.I Event_Type +: le type d'evenement declencheur (expression reguliere) +.LP +* (In) +.I Trigger_Mode +: le mode de fonctionnement du trigger +.RS -3 +.LP +.I Rappel +: +.LP +Si un trigger fonctionne sur le mode +.B LOGD_ONESHOT +, il est automatiquement supprime des lors qu'il a ete active. En mode +.B LOGD_PERMANENT +, le trigger reste active en permanence. +.LP +Si un trigger fonctionne sur le mode +.B LOGD_ADD +, l'activation du trigger provoque l'association de la table de routage avec le channel. Avec le mode +.B LOGD_REMOVE +, l'activation du trigger correspond a leur dissociation. +.LP +Les differents modes de fonctionnement peuvent etre combines par addition binaire. +.LP +.I NB +: plusieurs triggers peuvent etre poses sur un meme channel. +.LP +.RS -3 +.BI "LOGT_Status LOG_Trigger_Remove ( LOGT_Trigger * " Trigger " );" +.LP +.RS 3 +Cette fonction permet de supprimer un trigger positionne sur un channel. +.LP +.I Trigger +est un pointeur sur le trigger a supprimer. +.LP +.RS -3 +.BI "LOGT_Status LOG_Event_Send ( LOGT_Channel * " Channel ", LOGT_RC * " Return_Code ", char * " Cd_Support ", va_list " Data ");" +.LP +.RS 3 +Cette fonction permet d'envoyer un evenement a travers un channel et de recuperer le code retour associe au type d'evenement (pilotage). +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (Out) +.I RC +: un pointeur sur le code retour +.LP +* (In) +.I Cd_Support +: le code du support source +.LP +* (In) +.I Data +: une liste d'arguments contenant les donnees de l'evenement +.RS -3 +.LP +.RS -3 +.BI "LOGT_RC LOG_Event_External_Send ( LOGT_Channel * " Channel ", char * " Cd_Support ", char * " Data ");" +.LP +.RS 3 +Cette fonction est definie pour tous les appels a partir de programmes ecrits en PL/SQL. +Elle permet d'envoyer un evenement a travers un channel et de recuperer le code retour associe au type d'evenement (pilotage). +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I Cd_Support +: le code du support source +.LP +* (In) +.I Data +: une chaine de caracteres contenant les donnees de l'evenement +.RS -3 +.LP +.I NB +: la fonction retourne le code retour associe au type d'evenement. +.LP +.RS -3 +.BI "LOGT_Status LOG_Event_Info_Get ( LOGT_Channel * " Channel ", LOGT_Info * " Info ", va_list " Data " );" +.LP +.RS 3 +Cette fonction permet de simuler l'envoi d'un evenement et de recuperer toutes les informations concernant le type par lequel il a ete resolu. +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (Out) +.I Info +: un pointeur sur les informations a recuperer +.LP +* (In) +.I Data +: une liste d'arguments contenant les donnees de l'evenement a tester +.RS -3 +.LP +.I NB +: le type LOGT_Info est une structure qui contient les informations suivantes : +.LP +.RS 3 +- +.B EvtType +(type d'evenement par lequel l'evenement est resolu) de type char * +.LP +- +.B RC +(code retour associe) de type +.B LOGT_RC +.LP +- +.B Gravite +(code gravite associe) de type +.B LOGT_Gravite +.LP +- +.B Rooting +(routage associe) de type +.B LOGT_Rooting +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_Event_Info_External_Get ( LOGT_Channel * " Channel ", LOGT_Info * " Info ", char * " Event_Name " );" +.LP +.RS 3 +Cette fonction permet de simuler l'envoi d'un evenement et de recuperer toutes les informations concernant le type par lequel il a ete resolu. +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (Out) +.I Info +: un pointeur sur les informations a recuperer +.LP +* (In) +.I Event_Name +: le nom de l'evenement a tester +.RS -3 +.LP +.RS -3 +.BI "LOGT_Status LOG_Event_Cpt_Get ( LOGT_Channel * " Channel ", int * " Cpt " [LOGD_RC_SIZE], char * " Reg_Expr " );" +.LP +.RS 3 +Cette fonction permet de recuperer les compteurs d'evenements dont le nom correspond a une expression reguliere. +.LP +Elle requiert les arguments suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (Out) +.I Cpt +: un pointeur sur un tableau de compteurs +.LP +* (In) +.I Reg_Expr +: une expression reguliere +.RS -3 +.LP +.I NB +: le tableau de compteurs doit etre alloue par l'utilisateur. +.LP +La fonction retourne dans ce tableau le nombre d'evenements correspondant a l'expression reguliere ayant ete envoyes via le channel pour chacun des codes retour. +.LP +.I Exemple +: Cpt[LOGD_RC_OK] contiendra le nombre d'evenements envoyes ayant retourne le code LOGD_RC_OK. +.SH CODES RETOUR +.LP +Toutes les fonctions constituant l'API de la librairie LIBLOG retournent un code de type +.B LOGT_Status +: +.LP +.RS 3 +- +.B LOGS_OK +: la fonction s'est correctement executee et a produit un resultat +.LP +- +.B LOGS_KO +: la fonction s'est correctement executee mais n'a pas produit de resultat +.LP +- +.B LOGS_ERRAPI +: la fonction a ete appelee avec des arguments de valeur incorrecte +.LP +- +.B LOGS_ERRMEM +: la fonction ne s'est pas correctement executee pour un probleme d'allocation memoire +.LP +- +.B LOGS_ERRSHM +: la fonction ne s'est pas correctement executee pour un probleme relatif a la memoire partagee +.LP +- +.B LOGS_ERRSIG +: une operation sur semaphore a ete interrompue par un signal +.LP +- +.B LOGS_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 LOG_ERROR() +permet de tester si un code retour correspond a une erreur. +.LP +En cas d'erreur, la variable +.B LOG_Error_Msg +contient un message du type : +.LP +.RS 3 +Error : +.RS -3 +.LP diff --git a/lib/liblog.c b/lib/liblog.c new file mode 100644 index 0000000..d267bf0 --- /dev/null +++ b/lib/liblog.c @@ -0,0 +1,4725 @@ +/* Utilisation des API sans vérification des arguments */ + +#define ND_MODE 1 +#define SM_MODE 1 +#define DS_MODE 1 +#define MSG_MODE 1 + +#include + +VER_INFO_EXPORT (liblog,"$Revision: 1.1 $", "$Name: $",__FILE__,"$Author: smas $") + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS PUBLIQUES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* FONCTIONS OPTIMISEES (LOG_MODE = 1) */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance à ouvrir */ +/* (I) Context : contexte d'utilisation de la librairie */ +/* (I) Open_Mode : mode d'ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Open_I ( int Instance, const char * Context, LOGT_Flags Open_Mode ) +{ + LOGT_Status rc; + int Locked; + int MSG_Debug_Mode = MSGD_DEBUG_NONE; + + /* Définition du mode debug */ + + if (Open_Mode & LOGD_DEBUG) + { + LOG_stderr = stderr; + MSG_Debug_Mode = MSGD_DEBUG; + } + else if (Open_Mode & LOGD_DEBUG_ALL) + { + LOG_stderr = stderr; + MSG_Debug_Mode = MSGD_DEBUG_ALL; + } + + /* Ouverture de la librairie LIBMSG */ + + rc = MSG_Library_Open (Instance, Context, MSGD_OPEN | MSG_Debug_Mode); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the LIBMSG library"); + LOG_Error_Print (); + return rc; + } + + /* Accès aux ressources partagées de la librairie */ + + if (Open_Mode & LOGD_CREATE) + { + /* On vérifie que le processus courant n'a pas déjà ouvert la librairie */ + + if (LOG_Open_Counter > 0) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : the current process has already opened the LIBLOG library"); + LOG_Error_Print (); + MSG_Library_Close (MSGD_CLOSE); + return LOGS_ERRAPI; + } + + /* Création de la base LIBLOG */ + + rc = SM_Heap_Open (LOG_Name_Prefix (LOGD_BASE_HEAP_NAME), &LOG_Base_Heap, LOGD_BASE_HEAP_SEGMENT_SIZE, SMD_CREATE | SMD_WRITE, &Locked); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the heap for the LIBLOG base"); + LOG_Error_Print (); + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + rc = SM_Chunk_Alloc (LOG_Base_Heap, sizeof (LOGT_Base), (void **)&LOG_Base); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to allocate memory for the LIBLOG base structure"); + LOG_Error_Print (); + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Création du cache des modules */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_KMOD_NAME), &(LOG_Base->KMOD), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, LOGD_KMOD_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the KMOD data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->KMOD->Manager, "LOG_KMOD_Manager"); + + /* Création du cache des formats d'événement */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_KFORMAT_NAME), &(LOG_Base->KFORMAT), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, LOGD_KFORMAT_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the KFORMAT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->KFORMAT->Manager, "LOG_KFORMAT_Manager"); + + /* Création de la table de routage globale par défaut (GDRT) */ + + rc = SM_Chunk_Alloc (LOG_Base_Heap, sizeof (LOGT_RTab) + strlen (LOGD_GDRT_NAME) + 1, (void **)(&LOG_Base->GDRT)); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to allocate memory for the GDRT rooting table"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else + { + LOG_Base->GDRT->Name = (char *)((size_t)(LOG_Base->GDRT) + sizeof (LOGT_RTab)); + strcpy (LOG_Base->GDRT->Name, LOGD_GDRT_NAME); + LOG_Base->GDRT->Type = LOGD_GDRT; + } + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_GDRT_NAME), &(LOG_Base->GDRT->Root), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, LOGD_GDRT_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the GDRT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->GDRT->Root->Manager, "LOG_GDRT_Manager"); + + /* Création de la table de routage globale maître (GMRT) */ + + rc = SM_Chunk_Alloc (LOG_Base_Heap, sizeof (LOGT_RTab) + strlen (LOGD_GMRT_NAME) + 1, (void **)(&LOG_Base->GMRT)); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to allocate memory for the GMRT rooting table"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else + { + LOG_Base->GMRT->Name = (char *)((size_t)(LOG_Base->GMRT) + sizeof (LOGT_RTab)); + strcpy (LOG_Base->GMRT->Name, LOGD_GMRT_NAME); + LOG_Base->GMRT->Type = LOGD_GMRT; + } + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_GMRT_NAME), &(LOG_Base->GMRT->Root), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, LOGD_EMPTY_RTAB_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the GMRT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->GMRT->Root->Manager, "LOG_RTab_Manager"); + + /* Création de la liste des tables de routage locales maître (LMRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_LMRT_LIST_NAME), &(LOG_Base->LMRT_List), NDD_DS_LIST | NDD_MN_ORDERED, LOG_FILE_MANAGER, LOGD_RTAB_LIST_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the LMRT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->LMRT_List->Manager, "LOG_Base_RTabList_Manager"); + + /* Création de la liste des tables de routage locale par défaut (LDRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_LDRT_LIST_NAME), &(LOG_Base->LDRT_List), NDD_DS_LIST | NDD_MN_ORDERED, LOG_FILE_MANAGER, LOGD_RTAB_LIST_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the LDRT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->LDRT_List->Manager, "LOG_Base_RTabList_Manager"); + + /* Création de la liste des tables de routage utilisateur (URT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_URT_LIST_NAME), &(LOG_Base->URT_List), NDD_DS_LIST | NDD_MN_ORDERED, LOG_FILE_MANAGER, LOGD_RTAB_LIST_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the URT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->URT_List->Manager, "LOG_Base_RTabList_Manager"); + + /* Création de la liste des channels */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &(LOG_Base->Channel_List), NDD_DS_LIST | NDD_MN_ORDERED, LOG_FILE_MANAGER, LOGD_RTAB_LIST_SEGMENT_SIZE, DSD_CREATE, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the channel list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + else strcpy (LOG_Base->Channel_List->Manager, "LOG_Base_ChannelList_Manager"); + + /* Création du port de messages des événements */ + + rc = MSG_Port_Open (LOGD_EVENT_PORT_NAME, &Send_Port, MSGD_CREATE); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to create the event port list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Verrouillage de la base LIBLOG en lecture */ + + rc = SM_Heap_Unlock (LOG_Base_Heap); + if (rc != SMS_OK && SM_Heap_Lock (LOG_Base_Heap, SMD_READ, &Locked) != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to lock the LIBLOG base for reading"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + } + else + { + SMT_DSH * DSH; + NDT_Root * Root; + + /* Ouverture de la base LIBLOG */ + + rc = SM_Heap_Open (LOG_Name_Prefix (LOGD_BASE_HEAP_NAME), &LOG_Base_Heap, 0, SMD_OPEN | SMD_READ, &Locked); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the heap for the LIBLOG base"); + LOG_Error_Print (); + return rc; + } + + DSH = LOG_Base_Heap->MHH->DSR->Head->Value; + + /* La structure de la base se trouve dans le premier chunk du premier segment du heap */ + + LOG_Base = (LOGT_Base *)((size_t)(DSH->Start) + sizeof (NDT_Node) + sizeof (SMT_Chunk)); + + /* Ouverture du cache des modules */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_KMOD_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the KMOD data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture du cache des formats d'événement */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_KFORMAT_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the KFORMAT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la table de routage globale par défaut (GDRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_GDRT_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the GDRT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la table de routage globale maître (GMRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_GMRT_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the GMRT data structure"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la liste des tables de routage locales maître (LMRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_LMRT_LIST_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the LMRT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la liste des tables de routage locale par défaut (LDRT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_LDRT_LIST_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the LDRT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la liste des tables de routage utilisateur (URT) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_URT_LIST_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the URT list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture de la liste des channels */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &Root, NULL, NULL, 0, DSD_OPEN, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the channel list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + + /* Ouverture du port de messages des événements */ + + rc = MSG_Port_Open (LOGD_EVENT_PORT_NAME, &Send_Port, MSGD_OPEN); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Open : unable to open the event port list"); + LOG_Error_Print (); + LOG_Base = NULL; + MSG_Library_Close (MSGD_CLOSE); + return rc; + } + } + + /* Mise à jour du compteur d'ouverture */ + + LOG_Open_Counter++; + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Close_Mode : mode de fermeture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Close_I ( LOGT_Flags Close_Mode ) +{ + LOGT_Status rc; + + if (Close_Mode == LOGD_DESTROY) + { + /* Suppression du port de messages des événements */ + + MSG_Port_Close (Send_Port, MSGD_DESTROY); + + /* Déverrouillage de la base LIBLOG */ + + rc = SM_Heap_Unlock (LOG_Base_Heap); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to unlock the LIBLOG base"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la liste des channels */ + + rc = DS_DataStruct_Close (LOG_Base->Channel_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the channel list"); + LOG_Error_Print (); + return rc; + } + + /* Destruction du cache des modules */ + + rc = DS_DataStruct_Close (LOG_Base->KMOD, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the KMOD data structure"); + LOG_Error_Print (); + return rc; + } + + /* Destruction du cache des formats d'événement */ + + rc = DS_DataStruct_Close (LOG_Base->KFORMAT, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the KFORMAT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la table de routage globale par défaut (GDRT) */ + + rc = DS_DataStruct_Close (LOG_Base->GDRT->Root, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the GDRT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la table de routage globale maître (GMRT) */ + + rc = DS_DataStruct_Close (LOG_Base->GMRT->Root, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the GMRT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la liste des tables de routage locale maître (LMRT) */ + + rc = DS_DataStruct_Close (LOG_Base->LMRT_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the LMRT list"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la liste des tables de routage locale maître (LMRT) */ + + rc = DS_DataStruct_Close (LOG_Base->LDRT_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the LDRT list"); + LOG_Error_Print (); + return rc; + } + + /* Destruction de la liste des tables de routage utilisateur (URT) */ + + rc = DS_DataStruct_Close (LOG_Base->URT_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the URT list"); + LOG_Error_Print (); + return rc; + } + + /* Destruction du heap contenant la structure de base */ + + rc = SM_Heap_End (LOG_Name_Prefix (LOGD_BASE_HEAP_NAME)); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to destroy the heap of the base structure"); + LOG_Error_Print (); + return rc; + } + + /* Réinitialisation du compteur d'ouverture */ + + LOG_Open_Counter = 0; + } + else + { + /* On ne libère les ressources que lors de la dernière fermeture */ + + if (LOG_Open_Counter == 1) + { + pid_t Pid = getpid (); + NDT_Node * Node, * Next_Node; + + /* Fermeture du port de messages des événements */ + + MSG_Port_Close (Send_Port, MSGD_CLOSE); + + /* Ménage des channels du processus courant qui n'auraient pas été fermés */ + + DS_Node_First_Get (LOG_Base->Channel_List, &Node); + while (Node) + { + LOGT_Channel * Channel = (LOGT_Channel *)(Node->Value); + + DS_Node_Next_Get (Node, &Next_Node); + + if (Channel->Pid == Pid) + { + rc = LOG_Channel_Close (Channel); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close a channel which belongs to the current process"); + LOG_Error_Print (); + } + else + { + /* + Petit message d'alerte à l'encontre de l'utilisateur de la librairie + pour lui préciser qu'il a oublié de fermer l'un de ses channels. + */ + + sprintf (LOG_Error_Msg, "Warning LOG_Library_Close : a channel which belongs to the current process has not been closed. The garbage collector has done the work for you !"); + LOG_Error_Print (); + } + } + + Node = Next_Node; + } + + /* Ménage des tables de routage utilisateur du processus courant qui n'auraient pas été supprimées */ + + DS_Node_First_Get (LOG_Base->URT_List, &Node); + + while (Node) + { + LOGT_RTab * RTab = (LOGT_RTab *)(Node->Value); + + DS_Node_Next_Get (Node, &Next_Node); + + if (RTab->Pid == Pid) + { + rc = LOG_RTab_Free (RTab); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close a user rooting table which belongs to the current process"); + LOG_Error_Print (); + } + else + { + /* + Ici, on n'affiche pas de message d'alerte car ce cas peut ne pas être du fait de l'utilisateur + (notamment si une table de routage est supprimée d'un channel sur trigger, l'utilisateur + ne sait pas forcément qu'elle l'a été et ne peut donc pas savoir qu'il faut la supprimer). + */ + } + } + + Node = Next_Node; + } + + /* Fermeture du cache des modules */ + + rc = DS_DataStruct_Close (LOG_Base->KMOD, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the KMOD data structure"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture du cache des formats d'événement */ + + rc = DS_DataStruct_Close (LOG_Base->KFORMAT, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the KFORMAT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la table de routage globale par défaut (GDRT) */ + + rc = DS_DataStruct_Close (LOG_Base->GDRT->Root, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the GDRT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la table de routage globale maître (GMRT) */ + + rc = DS_DataStruct_Close (LOG_Base->GMRT->Root, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the GMRT data structure"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la liste des tables de routage locale maître (LMRT) */ + + rc = DS_DataStruct_Close (LOG_Base->LMRT_List, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the LMRT list"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la liste des tables de routage locale maître (LDRT) */ + + rc = DS_DataStruct_Close (LOG_Base->LDRT_List, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the LDRT list"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la liste des tables de routage utilisateur (URT) */ + + rc = DS_DataStruct_Close (LOG_Base->URT_List, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the URT list"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture de la liste des channels */ + + rc = DS_DataStruct_Close (LOG_Base->Channel_List, DSD_CLOSE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the channel list"); + LOG_Error_Print (); + return rc; + } + + /* Fermeture du heap contenant la structure de base */ + + rc = SM_Heap_Close (LOG_Base_Heap); + if (rc != SMS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Library_Close : unable to close the heap of the base structure"); + LOG_Error_Print (); + return rc; + } + + LOG_Base = NULL; + + /* Mise à jour du compteur d'ouverture */ + + LOG_Open_Counter--; + } + } + + /* Fermeture de la librairie LIBDATASTR */ + + rc = DS_Library_Close (); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Stderr_Set_I ( FILE * Out ) +{ + LOG_stderr = Out; + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Création d'un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (O) Channel : adresse du pointeur sur le canal créé */ +/* (I) Pid : numéro du processus propriétaire du canal */ +/* (I) Channel_Id : identifiant du canal au sein du processus */ +/* (I) Module_Name : nom du module propriétaire du canal */ +/* (I) Master_Module_Name : nom du module primaire */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Open_I ( LOGT_Channel ** Channel, int Pid, int Channel_Id, const char * Module_Name, const char * Master_Module_Name ) +{ + LOGT_Status rc; + NDT_Node * Node; + LOGT_RTab * LMRT, * LDRT; + char DS_Name [100]; + LOGT_Module To_Find; + +/************************ VERSION AVEC LA LIBRAIRIE LOGEVT ********************** + Id Id_Module; + + Id_Module = logevt_get_id_module (Module_Name); + + if (Id_Module < 0) + { + fprintf (stderr, "Error LOG_Channel_Open : logevt_get_id_module a retourn\351 %d", (int)Id_Module); + return rc; + } + + *Channel = (LOGT_Channel *) malloc (sizeof (LOGT_Channel)); + + (*Channel)->Id = logevt_open_channel (Id_Module, 0, 0); + + if ((int)(*Channel)->Id < 0 ) + { + fprintf (stderr, "Error LOG_Channel_Open : logevt_open_channel a retourn\351 %d", (int)(*Channel)); + return rc; + } +*********************************************************************************/ + + *Channel = NULL; + + /* Recherche de l'identifiant du module envoyeur */ + + To_Find.Name = Module_Name; + + rc = DS_Node_Find (LOG_Base->KMOD, &Node, &To_Find, NULL); + if (DS_ERROR(rc)) return rc; + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to find module \"%s\"", Module_Name); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + /* Création du channel */ + + rc = DS_Value_Alloc (LOG_Base->Channel_List, (void **)Channel); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create a channel"); + LOG_Error_Print (); + return rc; + } + + if (!Pid) (*Channel)->Pid = (int)getpid (); + else (*Channel)->Pid = Pid; + (*Channel)->Id = Channel_Id; + (*Channel)->ModuleId = ((LOGT_Module *)(Node->Value))->Id; + (*Channel)->Master_ModuleId = 0; + (*Channel)->RTab_List = NULL; + (*Channel)->SubModule_List = NULL; + (*Channel)->Trigger_List = NULL; + (*Channel)->Event_Cpt_List = NULL; + + /* Recherche de l'identifiant du module maître */ + + if (Master_Module_Name) To_Find.Name = Master_Module_Name; + else To_Find.Name = getenv (MASTER_MODULE_ENV); + + if (To_Find.Name) + { + rc = DS_Node_Find (LOG_Base->KMOD, &Node, &To_Find, NULL); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to find master module \"%s\"", Master_Module_Name); + LOG_Error_Print (); + } + + (*Channel)->Master_ModuleId = ((LOGT_Module *)(Node->Value))->Id; + } + + /* Création de la liste des sous-modules associée au channel (dans le même heap que la liste des channels) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &((*Channel)->SubModule_List), NDD_DS_LIST | NDD_MN_FILO, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the channel submodule list"); + LOG_Error_Print (); + return rc; + } + else strcpy ((*Channel)->SubModule_List->Manager, "LOG_Channel_SubModuleList_Manager"); + + /* Ajout d'un premier sous-module correspondant au nom du module */ + + rc = LOG_Channel_Enter (*Channel, Module_Name); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add a first submodule to the channel"); + LOG_Error_Print (); + return rc; + } + + /* Création de la liste des triggers associée au channel (dans le même heap que la liste des channels) */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &((*Channel)->Trigger_List), NDD_DS_LIST | NDD_MN_FILO, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the channel trigger list"); + LOG_Error_Print (); + return rc; + } + else strcpy ((*Channel)->Trigger_List->Manager, "LOG_Channel_TriggerList_Manager"); + + /* Création de la liste de compteurs d'événements associée au channel (dans le même heap que la liste des channels)*/ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &((*Channel)->Event_Cpt_List), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the channel event counter list"); + LOG_Error_Print (); + return rc; + } + else strcpy ((*Channel)->Event_Cpt_List->Manager, "LOG_Channel_Event_CptList_Manager"); + + /* Création de la liste des tables de routage associée au channel (dans le même heap que la liste des channels)*/ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_CHANNEL_LIST_NAME), &((*Channel)->RTab_List), NDD_DS_LIST | NDD_MN_ORDERED, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the channel rooting table list"); + LOG_Error_Print (); + return rc; + } + else strcpy ((*Channel)->RTab_List->Manager, "LOG_Channel_RTabList_Manager"); + + /* Ajout de la table de routage globale maître (GMRT) à la liste (pas la GDRT) */ + + rc = LOG_RTab_Add (*Channel, LOG_Base->GMRT); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the GDRT table to the rooting table list"); + LOG_Error_Print (); + return rc; + } + + /* Création de la table de routage locale maître */ + + sprintf (DS_Name, "%s_%d_%d_%d", LOGD_LMRT_NAME, (*Channel)->ModuleId, (int)(*Channel)->Pid, Channel_Id); + + rc = DS_Value_Alloc (LOG_Base->LMRT_List, (void **)&LMRT, LOGD_LMRT, DS_Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the LMRT rooting table"); + LOG_Error_Print (); + return rc; + } + + /* Création de la table de routage locale par défaut */ + + sprintf (DS_Name, "%s_%d_%d_%d", LOGD_LDRT_NAME, (*Channel)->ModuleId, (int)(*Channel)->Pid, Channel_Id); + + rc = DS_Value_Alloc (LOG_Base->LDRT_List, (void **)&LDRT, LOGD_LDRT, DS_Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to create the LMRT rooting table"); + LOG_Error_Print (); + return rc; + } + + /* Ajout des tables de routage locales à la liste des tables de routage du channel */ + + rc = LOG_RTab_Add (*Channel, LMRT); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the LMRT table to the channel rooting table list"); + LOG_Error_Print (); + return rc; + } + + rc = LOG_RTab_Add (*Channel, LDRT); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the LDRT table to the channel rooting table list"); + LOG_Error_Print (); + return rc; + } + + /* Ajout des tables de routage locales aux listes de tables de routage locales de la base */ + + rc = DS_Value_Add (LOG_Base->LMRT_List, (void *)LMRT); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the LMRT table to the base LMRT list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Add (LOG_Base->LDRT_List, (void *)LDRT); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the LDRT table to the base LDRT list"); + LOG_Error_Print (); + return rc; + } + + /* Ajout du channel à la liste des channels */ + + rc = DS_Value_Add (LOG_Base->Channel_List, (void *)(*Channel)); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : unable to add the channel to the base channel list"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Entrée dans un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Enter_I ( LOGT_Channel * Channel, const char * SubModule_Name ) +{ + LOGT_Status rc; + char * SubModule; + + rc = DS_Value_Alloc (Channel->SubModule_List, (void **)&SubModule, SubModule_Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Enter : unable to create a submodule in channel submodule list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Add (Channel->SubModule_List, (void *)SubModule); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Enter : unable to add a submodule to the channel submodule list"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Sortie d'un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Leave_I ( LOGT_Channel * Channel, const char * SubModule_Name ) +{ + LOGT_Status rc; + char * Name; + + rc = DS_Value_Remove (Channel->SubModule_List, (void *)SubModule_Name, (void **)&Name); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Leave : unable to remove the submodule from the channel submodule list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (Channel->SubModule_List, Name); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Leave : unable to free the submodule name"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel à fermer */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Close_I ( LOGT_Channel * Channel ) +{ + LOGT_Status rc; + +/************************ VERSION AVEC LA LIBRAIRIE LOGEVT ********************** + logevt_close_channel ((Channel)Channel->Id); +********************************************************************************/ + + rc = DS_Value_Remove (LOG_Base->Channel_List, (void *)Channel, (void **)&Channel); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Close : unable to remove a channel from the base channel list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (LOG_Base->Channel_List, (void *)Channel); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Close : unable to free the channel"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Création d'une table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +/* (O) RTab : adresse du pointeur sur la table de routage */ +/* (I) Name : nom de la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Alloc_I ( LOGT_RTab ** RTab, char * Name ) +{ + LOGT_Status rc; + *RTab = NULL; + + /* Allocation de la nouvelle table */ + + rc = DS_Value_Alloc (LOG_Base->URT_List, (void **)RTab, LOGD_URT, Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Alloc : unable to create a rooting table"); + LOG_Error_Print (); + return rc; + } + + /* Ajout de la nouvelle table de routage dans la base */ + + rc = DS_Value_Add (LOG_Base->URT_List, (void *)(*RTab)); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Alloc : unable to add the new rooting table to the base list"); + LOG_Error_Print (); + + DS_Value_Free (LOG_Base->URT_List, RTab); + + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une règle à une table de routage */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage */ +/* (I) Rule_Class : classe de la nouvelle règle */ +/* (I) Rule : pointeur sur la nouvelle règle */ +/* (I) Value : valeur de la nouvelle règle */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Setup_I ( LOGT_RTab * RTab, LOGT_RuleClass Rule_Class, LOGT_Rule * Rule, LOGT_Rooting Value ) +{ + RegExp_t * Compiled_RegExp = NULL; + + /* Si la sélection se fait sur le nom du type d'événement, on compile l'expression régulière */ + + if (Rule_Class == LOGD_SELECT_TYPE) + { + Compiled_RegExp = (RegExp_t *) malloc (RegExp_Size); + + if (!RegExp_Compile ((char *)Rule, Compiled_RegExp)) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Setup : unable to compile the regular expression \"%s\"", (char *)Rule); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return LOGS_ERRAPI; + } + } + + /* Sélection récursive de tous les types d'événement de la table de routage par défaut (GDRT) */ + + LOG_GDRT_Recursive_Select (0, LOG_Base->GDRT->Root, RTab, Rule_Class, Rule, Value, "", Compiled_RegExp); + + if (Compiled_RegExp) free (Compiled_RegExp); + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une table de routage utilisateur à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Add_I ( LOGT_Channel * Channel, LOGT_RTab * RTab ) +{ + LOGT_Status rc; + + rc = ND_Value_Add (Channel->RTab_List, (void *)RTab); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Add : unable to add the rooting table to the channel"); + LOG_Error_Print (); + return rc; + } + + (RTab->Nb_Channel)++; + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'une table de routage utilisateur d'un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Remove_I ( LOGT_Channel * Channel, LOGT_RTab * RTab ) +{ + LOGT_Status rc; + NDT_Node * Node; + + /* On vérifie qu'il s'agit bien d'une table de routage utilisateur */ + + if (RTab->Type != LOGD_URT) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Remove : the rooting table is not a user rooting table"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + /* + Pour rechercher la table de routage à supprimer, on ne peut pas utiliser la fonction ND_Node_Find + car le manager compare les tables selon leur type ce qui ne nous intéresse pas dans le cas présent. + */ + + ND_Node_First_Get (Channel->RTab_List, &Node); + + while (Node && strcmp (RTab->Name, ((LOGT_RTab *)(Node->Value))->Name)) + ND_Node_Next_Get (Node, &Node); + + if (!Node) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Remove : unable to find the rooting table \"%s\" in the channel", RTab->Name); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + rc = ND_Node_Remove (Node); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Remove : unable to remove the rooting table from the channel"); + LOG_Error_Print (); + return rc; + } + + (RTab->Nb_Channel)--; + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Destruction d'une table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Free_I ( LOGT_RTab * RTab ) +{ + LOGT_Status rc; + char RTab_Name [50]; + + strcpy (RTab_Name, RTab->Name); + + /* On ne supprime la table de routage que si elle n'est plus rattachée à aucun channel */ + + if (RTab->Nb_Channel > 0) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Free : unable to free rooting table \"%s\" because it is referenced by some channel", RTab_Name); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + rc = DS_Value_Remove (LOG_Base->URT_List, (void *)RTab, (void **)&RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Free : unable to remove user rooting table \"%s\" from the base list", RTab_Name); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (LOG_Base->URT_List, (void *)RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Free : unable to free the user rooting table \"%s\"", RTab_Name); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (O) Trigger : adresse du pointeur sur le trigger mis en place */ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage à appliquer */ +/* (I) Event_Name : type d'événement déclencheur (expression régulière) */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Add_I ( LOGT_Trigger ** Trigger, LOGT_Channel * Channel, LOGT_RTab * RTab, char * Event_Name, LOGT_Flags Mode ) +{ + LOGT_Status rc; + *Trigger = NULL; + + rc = DS_Value_Alloc (Channel->Trigger_List, (void **)Trigger, Event_Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Add : unable to create a trigger in the channel trigger list"); + LOG_Error_Print (); + return rc; + } + + (*Trigger)->RTab = RTab; + (*Trigger)->Channel = Channel; + (*Trigger)->Mode = Mode; + + rc = DS_Value_Add (Channel->Trigger_List, (void *)(*Trigger)); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Add : unable to add a trigger to the channel trigger list"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (I) Trigger : pointeur sur le trigger mis en place */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Remove_I ( LOGT_Trigger * Trigger ) +{ + LOGT_Status rc; + + rc = DS_Value_Remove (Trigger->Channel->Trigger_List, (void *)Trigger, (void **)&Trigger); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Remove : unable to remove a trigger from the channel trigger list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (Trigger->Channel->Trigger_List, (void *)Trigger); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Remove : unable to free the trigger"); + LOG_Error_Print (); + return rc; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) RC : pointeur sur le code retour associé au type de l'événement */ +/* (I) Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Send_I ( LOGT_Channel * Channel, LOGT_RC * RC, char * Support, va_list Data ) +{ + +/************************ VERSION AVEC LA LIBRAIRIE LOGEVT ********************** + if ((*RC = (LOGT_RC)evtutils_vsend_evt ((Channel)(Channel->Id), Support, Data)) < 0) + return rc; +*********************************************************************************/ + + return LOG_Event_Internal_Send (DATA_ARG_LIST, Channel, RC, Support, Data, NULL); +} + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement (PL/SQL ou shell) */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : identifiant du channel */ +/* (I) Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +/* (O) Retourne le code retour associé au type d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_RC LOG_Event_External_Send_I ( LOGT_Channel * Channel, char * Support, char * Data ) +{ + +/************************ VERSION AVEC LA LIBRAIRIE LOGEVT ********************** + char * Commande; + char sChannel[256]; + char Erreur[256]; + LOGT_RC RC; + + sprintf (sChannel, "%d", (int)Channel); + Commande = (char *) malloc (strlen (sChannel) + strlen (Support) + strlen (Data) + 3); + sprintf (Commande, "%d %s %s", (int)Channel, Support, Data); + + RC = evtutils_send_shell_evt (Commande, Erreur); + + free (Commande); +*********************************************************************************/ + + LOGT_RC RC = LOGD_RC_WARNING; + + LOG_Event_Internal_Send (DATA_STRING, Channel, &RC, Support, NULL, Data); + + return RC; +} + +/*------------------------------------------------------------------------------*/ +/* Retourne les informations du type par lequel un événement est résolu */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) Info : pointeur sur les informations à récupérer */ +/* (I) Event_Name : nom de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Info_Get_I ( LOGT_Channel * Channel, LOGT_Info ** Info, char * Event_Name ) +{ + LOGT_Status rc; + LOGT_GDRT_Evt * GDRT_Evt; + char * ptr; + NDT_Node * Node; + LOGT_Event_Format To_Find; + + ptr = (char *) malloc (81); + ptr [80] = (char)0; + ptr += 80; + + /* Recherche des informations dans la table de routage par défaut */ + + rc = LOG_GDRT_Event_Find (&GDRT_Evt, &ptr, Event_Name); + if (LOG_ERROR(rc)) return rc; + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Info_Get : unable to find event %s in the GDRT rooting table", Event_Name); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + (*Info)->Event_Name = ptr; + (*Info)->Event_Type = GDRT_Evt->Id; + (*Info)->RC = GDRT_Evt->RC; + (*Info)->Gravite = GDRT_Evt->Gravite; + + /* Recherche du routage dans la liste des tables de routage du channel, sinon routage par défaut */ + + rc = LOG_Channel_Rooting_Find (Channel, GDRT_Evt->Id, &((*Info)->Rooting)); + if (rc != LOGS_OK || (*Info)->Rooting == LOGD_ROOTING_DEFAULT) + (*Info)->Rooting = GDRT_Evt->Rooting; + + /* Recherche du format du type d'événement */ + + To_Find.Event_Type = (*Info)->Event_Type; + + rc = DS_Node_Find (LOG_Base->KFORMAT, &Node, &To_Find, NULL); + if (rc != DSS_OK) (*Info)->Data_List = NULL; + else (*Info)->Data_List = (NDT_Root *)(((LOGT_Event_Format *)(Node->Value))->Data_List); + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Retourne le nombre d'événements envoyés pour chaque code retour */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) Cpt : pointeur sur un tableau de compteurs d'événement */ +/* (I) RegExpr : expression régulière sur le nom d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Cpt_Get_I ( LOGT_Channel * Channel, int * Cpt [LOGD_RC_SIZE], char * RegExpr ) +{ + LOGT_Status rc; + NDT_Node * Node; + LOGT_Event_Cpt * Event_Cpt; + LOGT_Info * Info; + int i; + RegExp_t * Compiled_RegExp = NULL; + + /* Initialisation du tableau de compteurs */ + + for (i = 0; i < LOGD_RC_SIZE; i++) (*Cpt)[i] = 0; + + /* Compilation de l'expression régulière */ + + Compiled_RegExp = (RegExp_t *) malloc (RegExp_Size); + + if (!RegExp_Compile (RegExpr, Compiled_RegExp)) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Cpt_Get : unable to compile the regular expression \"%s\"", RegExpr); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return LOGS_ERRAPI; + } + + /* Traversée de la structure de compteurs */ + + ND_Node_First_Get (Channel->Event_Cpt_List, &Node); + while (Node) + { + Event_Cpt = (LOGT_Event_Cpt *)(Node->Value); + + /* L'événement matche-t'il avec l'expression régulière ? */ + + if (RegExp_Match (Event_Cpt->Name, Compiled_RegExp)) + { + /* Recherche des informations concernant l'événement */ + + rc = LOG_Event_Info_Get (Channel, &Info, Event_Cpt->Name); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Cpt_Get : unable to retrieve information about event \"%s\"", Event_Cpt->Name); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return rc; + } + + /* Incrémentation du compteur */ + + (*Cpt)[(int)Info->RC] += Event_Cpt->Total; + } + + ND_Node_Next_Get (Node, &Node); + } + + if (Compiled_RegExp) free (Compiled_RegExp); + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* FONCTIONS SECURISEES (LOG_MODE = 0) */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance à ouvrir */ +/* (I) Context : contexte d'utilisation de la librairie */ +/* (I) Open_Mode : mode d'ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Open_C ( int Instance, const char * Context, LOGT_Flags Open_Mode ) +{ + return LOG_Library_Open_I (Instance, Context, Open_Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Close_Mode : mode de fermeture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Close_C ( LOGT_Flags Close_Mode ) +{ + return LOG_Library_Close_I (Close_Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Stderr_Set_C ( FILE * Out ) +{ + return LOG_Library_Stderr_Set_I (Out); +} + +/*------------------------------------------------------------------------------*/ +/* Création d'un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (O) Channel : adresse du pointeur sur le canal créé */ +/* (I) Pid : numéro du processus propriétaire du canal */ +/* (I) Channel_Id : identifiant du canal au sein du processus */ +/* (I) Module_Name : nom du module propriétaire du canal */ +/* (I) Master_Module_Name : nom du module primaire */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Open_C (LOGT_Channel ** Channel, int Pid, int Channel_Id, const char * Module_Name, const char * Master_Module_Name ) +{ + *Channel = NULL; + + if (!LOG_Base) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : the library is not open"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : the channel address is undefined"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Module_Name) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Open : the module name is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Channel_Open_I (Channel, Pid, Channel_Id, Module_Name, Master_Module_Name); +} + +/*------------------------------------------------------------------------------*/ +/* Entrée dans un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Enter_C (LOGT_Channel * Channel, const char * SubModule_Name ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Enter : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!SubModule_Name) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Enter : the submodule name is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Channel_Enter_I (Channel, SubModule_Name); +} + +/*------------------------------------------------------------------------------*/ +/* Sortie d'un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Leave_C (LOGT_Channel * Channel, const char * SubModule_Name ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Leave : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!SubModule_Name) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Leave : the submodule name is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Channel_Leave_I (Channel, SubModule_Name); +} + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel à fermer */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Close_C (LOGT_Channel * Channel) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Close : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Channel_Close_I (Channel); +} + +/*------------------------------------------------------------------------------*/ +/* Création d'une table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +/* (O) RTab : adresse du pointeur sur la table de routage */ +/* (I) Name : nom de la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Alloc_C ( LOGT_RTab ** RTab, char * Name ) +{ + if (!LOG_Base) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Alloc : the library is not open"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Name) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Alloc : the rooting table name is undefined"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_RTab_Alloc_I (RTab, Name); +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une règle à une table de routage */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage */ +/* (I) Rule_Class : classe de la nouvelle règle */ +/* (I) Rule : pointeur sur la nouvelle règle */ +/* (I) Value : valeur de la nouvelle règle */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Setup_C (LOGT_RTab * RTab, LOGT_RuleClass Rule_Class, LOGT_Rule * Rule, LOGT_Rooting Value ) +{ + if (!RTab) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Setup : the rooting table is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + /* On vérifie qu'il s'agit bien d'une table de routage utilisateur */ + + if (RTab->Type != LOGD_URT) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Setup : the rooting table is not a user rooting table"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_RTab_Setup_I (RTab, Rule_Class, Rule, Value); +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une table de routage utilisateur à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Add_C (LOGT_Channel * Channel, LOGT_RTab * RTab ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Add : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!RTab) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Add : the rooting table is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_RTab_Add_I (Channel, RTab); +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'une table de routage utilisateur d'un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Remove_C (LOGT_Channel * Channel, LOGT_RTab * RTab ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Remove : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!RTab) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Remove : the rooting table is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_RTab_Remove_I (Channel, RTab ); +} + +/*------------------------------------------------------------------------------*/ +/* Destruction d'une table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Free_C ( LOGT_RTab * RTab ) +{ + if (!RTab) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Free : the rooting table is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + /* On vérifie qu'il s'agit bien d'une table de routage utilisateur */ + + if (RTab->Type != LOGD_URT) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Free : rooting table \"%s\" is not a user rooting table", RTab->Name); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_RTab_Free_I (RTab); +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (O) Trigger : adresse du pointeur sur le trigger mis en place */ +/* (I) Channel : pointeur sur le channel */ +/* (I) RTab : pointeur sur la table de routage à appliquer */ +/* (I) Event_Name : type d'événement déclencheur (expression régulière) */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Add_C ( LOGT_Trigger ** Trigger, LOGT_Channel * Channel, LOGT_RTab * RTab, char * Event_Name, LOGT_Flags Mode ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Add : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!RTab) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Add : the rooting table is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Event_Name) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Add : the event type is undefined"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Trigger_Add_I (Trigger, Channel, RTab, Event_Name, Mode); +} + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (I) Trigger : pointeur sur le trigger mis en place */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Remove_C ( LOGT_Trigger * Trigger ) +{ + if (!Trigger) + { + sprintf (LOG_Error_Msg, "Error LOG_Trigger_Remove : the trigger is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Trigger_Remove_I (Trigger); +} + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) RC : pointeur sur le code retour associé au type de l'événement */ +/* (I) Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Send_C (LOGT_Channel * Channel, LOGT_RC * RC, char * Support, va_list Data ) +{ + if (!LOG_Base) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Send : the library is not open"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Send : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Event_Send_I (Channel, RC, Support, Data); +} + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement (PL/SQL ou shell) */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : identifiant du channel */ +/* (I) Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +/* (O) Retourne le code retour associé au type d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_RC LOG_Event_External_Send_C ( LOGT_Channel * Channel, char * Support, char * Data ) +{ + if (!LOG_Base) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_External_Send : the library is not open"); + LOG_Error_Print (); + return LOGD_RC_WARNING; + } + + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_External_Send : the channel is null"); + LOG_Error_Print (); + return LOGD_RC_WARNING; + } + + return LOG_Event_External_Send_I (Channel, Support, Data); +} + +/*------------------------------------------------------------------------------*/ +/* Retourne les informations du type par lequel un événement est résolu */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) Info : pointeur sur les informations à récupérer */ +/* (I) Event_Name : nom de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Info_Get_C ( LOGT_Channel * Channel, LOGT_Info ** Info, char * Event_Name ) +{ + if (!LOG_Base) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Info_Get : the library is not open"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Info_Get : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Info) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Info_Get : the info address is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Event_Name) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Info_Get : the event name is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Event_Info_Get_I (Channel, Info, Event_Name); +} + +/*------------------------------------------------------------------------------*/ +/* Retourne le nombre d'événements envoyés pour chaque code retour */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un channel */ +/* (O) Cpt : pointeur sur un tableau de compteurs d'événement */ +/* (I) RegExpr : expression régulière sur le nom d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Cpt_Get_C ( LOGT_Channel * Channel, int * Cpt [LOGD_RC_SIZE], char * RegExpr ) +{ + if (!Channel) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Cpt_Get : the channel is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!Cpt) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Cpt_Get : the counter array address is undefined"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!RegExpr) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Cpt_Get : the regular expression is null"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOG_Event_Cpt_Get_I (Channel, Cpt, RegExpr); +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS PRIVEES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement (partie commune aux fonctions 'LOG_Event_Send' */ +/* et 'LOG_Event_External_Send' : */ +/*------------------------------------------------------------------------------*/ +/* - récupération des données de l'événement */ +/* - résolution du nom d'événement */ +/* - mise à jour du compteur d'événement */ +/* - traitement de l'événement en fonction du routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Internal_Send (int Mode, LOGT_Channel * Channel, LOGT_RC * RC, char * Support, va_list Data_Arg, char * Data_Str) +{ + LOGT_Status rc; + NDT_Node * Node; + LOGT_Info * Info; + char Event_Name [81]; + char * Event_Data, * Event_Data_Ptr; + size_t Data_Size; + LOGT_Event_Cpt To_Find; + unsigned int Length; + RegExp_t * Compiled_RegExp = NULL; + size_t Msg_Size; + LOGT_Event_Msg_Data * Event_Msg_Data; + + *RC = LOGD_RC_WARNING; + + /* Récupération des données de l'événement */ + + rc = LOG_Event_Data_Get (Mode, Support, &Event_Data, &Data_Size, &Data_Arg, Data_Str); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to retrieve event data from the %s", Mode == DATA_ARG_LIST ? "argument list" : "string"); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + return rc; + } + + /* Récupération du nom de l'événement */ + + Length = (unsigned int)Event_Data [0]; + strncpy (Event_Name, Event_Data + 1, Length); + Event_Name [Length] = (char)0; + + /* Résolution du nom d'événement */ + + Info = (LOGT_Info *) malloc (sizeof (LOGT_Info)); + if (!Info) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to allocate memory for event information"); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + return LOGS_ERRMEM; + } + + rc = LOG_Event_Info_Get (Channel, &Info, Event_Name); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to resolve event \"%s\"", Event_Name); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + return rc; + } + + /* Ajout au compteur d'événements du channel */ + + To_Find.Name = Event_Name; + + rc = ND_Node_Find (Channel->Event_Cpt_List, &Node, &To_Find, NULL); + if (rc != NDS_OK) + { + int Locked; + LOGT_Event_Cpt * Event_Cpt; + + /* + Optimisation : on verrouille nous-même la data structure et + on fait appel aux API sans verrouillage systématique (DS_*_I). + */ + + rc = DS_DataStruct_Lock (Channel->Event_Cpt_List, DSD_WRITE, &Locked); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to lock the channel counter list"); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + return rc; + } + + rc = DS_Value_Alloc_I (Channel->Event_Cpt_List, (void **)&Event_Cpt, Event_Name); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to create a counter for event \"%s\"", Event_Name); + LOG_Error_Print (); + if (Locked == TRUE) DS_DataStruct_Unlock (Channel->Event_Cpt_List); + if (Event_Data) free (Event_Data); + return rc; + } + + rc = DS_Value_Add_I (Channel->Event_Cpt_List, (void *)Event_Cpt); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to add the event counter \"%s\" to the data structure", Event_Name); + LOG_Error_Print (); + if (Locked == TRUE) DS_DataStruct_Unlock (Channel->Event_Cpt_List); + if (Event_Data) free (Event_Data); + return rc; + } + + if (Locked == TRUE) DS_DataStruct_Unlock (Channel->Event_Cpt_List); + } + else ((LOGT_Event_Cpt *)(Node->Value))->Total++; + + /* Traitement de l'événement en fonction du routage */ + + if (Info->Rooting & LOGD_ROOTING_STDERR) + { + /* Affichage de l'événement sur la sortie standard du process */ + + fprintf (stderr, "[EVENT] %s\n", Event_Name); + } + + if (Info->Rooting & LOGD_ROOTING_DATABASE) + { + MSGT_Message * Event_Msg; + + /* Allocation du message : entête du format de l'événement + données de l'événement (Data_Size) */ + + Msg_Size = sizeof (LOGT_Event_Msg_Header) + 2 * sizeof (unsigned int) + Data_Size; + + rc = MSG_Message_Alloc (&Event_Msg, Msg_Size); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to allocate %d byte(s) for a new message", Msg_Size); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + return rc; + } + + rc = MSG_Message_Config (Event_Msg, MSGD_CONFIG_TYPE, LOGD_EVENT_MSG_TYPE); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to configure the message as an event message"); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + MSG_Message_Free (Event_Msg); + return rc; + } + + /* On remplit la zone de données du message selon le format d'un message d'événement */ + + Event_Msg_Data = (LOGT_Event_Msg_Data *)(Event_Msg->Data); + + strcpy (Event_Msg_Data->Header.Version, EVENT_FORMAT_VERSION); + Event_Msg_Data->Header.Sending_Pid = Channel->Pid; + Event_Msg_Data->Header.ModuleId = Channel->ModuleId; + Event_Msg_Data->Header.Master_ModuleId = Channel->Master_ModuleId; + Event_Msg_Data->Event_Type = Info->Event_Type; + Event_Msg_Data->Data_Size = Data_Size; + + Event_Data_Ptr = &(Event_Msg_Data->Event_Data); + strncpy (Event_Data_Ptr, Event_Data, Data_Size); + + /* Envoi du message pour insertion de l'événement en base */ + + rc = MSG_Message_Send (0, Send_Port, Event_Msg); + if (rc != MSGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to send the event through message port \"%s\"", Send_Port->Name); + LOG_Error_Print (); + if (Event_Data) free (Event_Data); + MSG_Message_Free (Event_Msg); + return rc; + } + } + + if (Event_Data) free (Event_Data); + + Compiled_RegExp = (RegExp_t *) malloc (RegExp_Size); + + /* Déclenchement des triggers */ + + ND_Node_First_Get (Channel->Trigger_List, &Node); + + while (Node) + { + LOGT_Trigger * Trigger = (LOGT_Trigger *)(Node->Value); + NDT_Node * Next_Node; + + ND_Node_Next_Get (Node, &Next_Node); + + /* Compilation de l'expression régulière du trigger */ + + if (!RegExp_Compile (Trigger->Event_Name, Compiled_RegExp)) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to compile the trigger regular expression \"%s\"", Trigger->Event_Name); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return LOGS_ERRAPI; + } + + /* L'événement déclencheur matche-t'il avec l'événement courant ? */ + + if (RegExp_Match (Event_Name, Compiled_RegExp)) + { + /* Déclenchement du trigger */ + + if (LOGD_ADD_MSK (Trigger->Mode)) + { + rc = LOG_RTab_Add (Channel, Trigger->RTab); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to add a rooting table on event \"%s\" when specified by a trigger", Event_Name); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return rc; + } + } + else if (LOGD_REMOVE_MSK (Trigger->Mode)) + { + rc = LOG_RTab_Remove (Channel, Trigger->RTab); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to remove rooting table \"%s\" on event \"%s\" when specified by a trigger", Trigger->RTab->Name, Event_Name); + LOG_Error_Print (); + + /* On continue quand même */ + } + } + + /* Retrait du trigger s'il n'est actif qu'une seule fois */ + + if (LOGD_ONE_SHOT_MSK (Trigger->Mode)) + { + rc = LOG_Trigger_Remove (Trigger); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Internal_Send : unable to remove a \"one-shot\" trigger on event %s", Event_Name); + LOG_Error_Print (); + if (Compiled_RegExp) free (Compiled_RegExp); + return rc; + } + } + } + + Node = Next_Node; + } + + if (Compiled_RegExp) free (Compiled_RegExp); + + /* Récupération du code retour */ + + *RC = Info->RC; + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* BASE */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +NDT_Status LOG_Base_ChannelList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Channel ** Channel = va_arg (Args, LOGT_Channel **); + + *Channel = NULL; + + rc = DS_Alloc (Root, sizeof (LOGT_Channel), (void **)Channel); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to allocate a new channel"); + LOG_Error_Print (); + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_Channel * Channel = (LOGT_Channel *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Channel (address %d) :\n\t- pid = %ld\n\t- ID = %d\n\t- module = %d\n\t- %ld sous-module(s)\n\t- %ld table(s)\n\t- %ld trigger(s)\n\t- %ld compteur(s) d'événement", (int)Channel, Channel->Pid, Channel->Id, Channel->ModuleId, Channel->SubModule_List->Node_Number, Channel->RTab_List->Node_Number, Channel->Trigger_List->Node_Number, Channel->Event_Cpt_List->Node_Number); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Channel * Channel = (LOGT_Channel *) va_arg (Args, void *); + + rc = DS_DataStruct_Close (Channel->RTab_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to destroy the channel rooting table list"); + LOG_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Close (Channel->SubModule_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to destroy the channel submodule list"); + LOG_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Close (Channel->Trigger_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to destroy the channel trigger list"); + LOG_Error_Print (); + + return rc; + } + + rc = DS_DataStruct_Close (Channel->Event_Cpt_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to destroy the channel event counter list"); + LOG_Error_Print (); + + return rc; + } + + rc = DS_Free (Root, Channel); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_ChannelList_Manager : unable to free the channel"); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de channels = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_Channel * Channel1, *Channel2; + long comp; + + Channel1 = (LOGT_Channel *) va_arg (Args, void *); + Channel2 = (LOGT_Channel *) va_arg (Args, void *); + + va_end (Args); + + comp = (int)Channel1 - (int)Channel2; + + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager d'une liste de tables de routage attachées à la base */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_Base_RTabList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_RTab ** RTab = va_arg (Args, LOGT_RTab **); + va_list Args_Value = va_arg (Args, va_list); + LOGT_RTType Type = va_arg (Args_Value, LOGT_RTType); + char * Name = va_arg (Args_Value, char *); + char * Heap_Name; + + *RTab = NULL; + + /* Allocation de la table de routage dans le même heap que celui de la liste des tables de routage */ + + rc = DS_Alloc (Root, sizeof (LOGT_RTab) + strlen (Name) + 1, (void **)RTab); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_RTabList_Manager : unable to allocate a new table %s", Name); + LOG_Error_Print (); + return rc; + } + + (*RTab)->Type = Type; + (*RTab)->Nb_Channel = 0; + (*RTab)->Root = NULL; + (*RTab)->Pid = getpid (); + + (*RTab)->Name = (char *)((size_t)(*RTab) + sizeof (LOGT_RTab)); + strcpy ((*RTab)->Name, Name); + + /* Création de la data structure sous-jacente toujours dans le même heap */ + + switch ((int)Type) + { + case LOGD_LMRT: + Heap_Name = LOG_Name_Prefix (LOGD_LMRT_LIST_NAME); + break; + + case LOGD_LDRT: + Heap_Name = LOG_Name_Prefix (LOGD_LDRT_LIST_NAME); + break; + + case LOGD_URT: + default : + Heap_Name = LOG_Name_Prefix (LOGD_URT_LIST_NAME); + break; + } + + rc = DS_DataStruct_Open (Heap_Name, &((*RTab)->Root), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_RTabList_Manager : unable to create the data structure for the rooting table \"%s\"", Name); + LOG_Error_Print (); + return rc; + } + else strcpy ((*RTab)->Root->Manager, "LOG_RTab_Manager"); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_RTab * RTab = (LOGT_RTab *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Table de routage \"%s\" :\n\t- creator = %d\n\t- type = %s\n\t- nombre d'événements = %ld\n\t- attachée à %d channel(s)", RTab->Name, (int)RTab->Pid, LOG_RTType_Label_Get (RTab->Type), RTab->Root->Node_Number, RTab->Nb_Channel); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_RTab * RTab = (LOGT_RTab *) va_arg (Args, void *); + char RTab_Name [50]; + + strcpy (RTab_Name, RTab->Name); + + rc = DS_DataStruct_Close (RTab->Root, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_RTabList_Manager : unable to destroy the data structure of rooting table \"%s\"", RTab_Name); + LOG_Error_Print (); + + return rc; + } + + rc = DS_Free (Root, RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Base_RTabList_Manager : unable to desallocate the rooting table \"%s\"", RTab_Name); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de tables de routage = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_RTab * RTab1, * RTab2; + long comp; + + RTab1 = (LOGT_RTab *) va_arg (Args, void *); + RTab2 = (LOGT_RTab *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (RTab1->Name, RTab2->Name); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* CHANNEL */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Manager de la liste de tables de routage d'un channel */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_Channel_RTabList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_RTab * RTab = (LOGT_RTab *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Table de routage \"%s\" :\n\t- type = %s\n\t- nombre d'événements = %ld\n\t- attachée à %d channel(s)", RTab->Name, LOG_RTType_Label_Get (RTab->Type), RTab->Root->Node_Number, RTab->Nb_Channel); + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_RTab * RTab = (LOGT_RTab *) va_arg (Args, void *); + + /* La table de routage globale maître n'est même pas fermée car peut être utilisée par d'autres channels */ + + /* Les tables de routage locales sont supprimées */ + + if (RTab->Type == LOGD_LMRT) + { + rc = DS_Value_Remove (LOG_Base->LMRT_List, (void *)RTab, (void **)&RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to remove the LMRT rooting table from the base list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (LOG_Base->LMRT_List, (void *)RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to free the LMRT rooting table"); + LOG_Error_Print (); + return rc; + } + } + + if (RTab->Type == LOGD_LDRT) + { + rc = DS_Value_Remove (LOG_Base->LDRT_List, (void *)RTab, (void **)&RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to remove a LDRT rooting table from the base list"); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (LOG_Base->LDRT_List, (void *)RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to free the LDRT rooting table"); + LOG_Error_Print (); + return rc; + } + } + + /* Les tables de routage utilisateur ne sont supprimées que si elles ne sont plus rattachées à aucun channel */ + + if (RTab->Type == LOGD_URT && RTab->Nb_Channel == 1) + { + rc = DS_Value_Remove (LOG_Base->URT_List, (void *)RTab, (void **)&RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to remove a user rooting table (%p) from the base list", (void *)RTab); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Free (LOG_Base->URT_List, (void *)RTab); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_RTabList_Manager : unable to free the user rooting table (%p)", (void *)RTab); + LOG_Error_Print (); + return rc; + } + } + else (RTab->Nb_Channel)--; + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de tables de routage = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_RTab * RTab1, * RTab2; + long comp; + + RTab1 = (LOGT_RTab *) va_arg (Args, void *); + RTab2 = (LOGT_RTab *) va_arg (Args, void *); + + va_end (Args); + + /* + Pour le tri des tables de routage, la comparaison se fait sur le type : + + - GMRT en 1er + - LMRT en 2ème + - URT ensuite + - LDRT en dernier + + Les types ont été choisis pour qu'on puisse se contenter de trier sur leur valeur. + */ + + comp = RTab1->Type - RTab2->Type; + + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + if (comp == 0) return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager de la structure de compteurs d'événements d'un channel */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_Channel_Event_CptList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Event_Cpt ** Event_Cpt = va_arg (Args, LOGT_Event_Cpt **); + va_list Args_Value = va_arg (Args, va_list); + char * Name = va_arg (Args_Value, char *); + + *Event_Cpt = NULL; + + rc = DS_Alloc (Root, sizeof (LOGT_Event_Cpt) + strlen (Name) + 1, (void **)Event_Cpt); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Event_CptList_Manager : unable to allocate a new event counter"); + LOG_Error_Print (); + return rc; + } + + (*Event_Cpt)->Total = 1; + + (*Event_Cpt)->Name = (char *)((size_t)(*Event_Cpt) + sizeof (LOGT_Event_Cpt)); + strcpy ((*Event_Cpt)->Name, Name); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_Event_Cpt * EventCpt = (LOGT_Event_Cpt *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Compteur :\n\t- événement = %s\n\t- valeur = %d", EventCpt->Name, EventCpt->Total); + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Event_Cpt * EventCpt = (LOGT_Event_Cpt *) va_arg (Args, void *); + + rc = DS_Free (Root, EventCpt); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_Event_CptList_Manager : unable to free an event counter"); + LOG_Error_Print (); + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de compteurs = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_Event_Cpt *Event_Cpt1, *Event_Cpt2; + long comp; + + Event_Cpt1 = (LOGT_Event_Cpt *) va_arg (Args, void *); + Event_Cpt2 = (LOGT_Event_Cpt *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (Event_Cpt1->Name, Event_Cpt2->Name); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager de la liste de sous-modules d'un channel */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_Channel_TriggerList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Trigger ** Trigger = va_arg (Args, LOGT_Trigger **); + va_list Args_Value = va_arg (Args, va_list); + char * Event_Name = va_arg (Args_Value, char *); + + *Trigger = NULL; + + rc = DS_Alloc (Root, sizeof (LOGT_Trigger) + strlen (Event_Name) + 1, (void **)Trigger); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_TriggerList_Manager : unable to allocate a new trigger"); + LOG_Error_Print (); + + return rc; + } + + (*Trigger)->Event_Name = (char *)((size_t)(*Trigger) + sizeof (LOGT_Trigger)); + strcpy ((*Trigger)->Event_Name, Event_Name); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_Trigger * Trigger = (LOGT_Trigger *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Trigger :\n\t- événement déclencheur = \"%s\"\n\t- mode = %s (%s)\n\t- table de routage concernée = \"%s\"", Trigger->Event_Name, LOGD_ADD_MSK (Trigger->Mode) == LOGD_ADD ? "ajout" : "suppression", LOGD_ONE_SHOT_MSK (Trigger->Mode) == LOGD_ONE_SHOT ? "une seule fois" : "permanent", Trigger->RTab->Name); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Trigger * Trigger = (LOGT_Trigger *) va_arg (Args, void *); + + rc = DS_Free (Root, Trigger); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_TriggerList_Manager : unable to free submodule"); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de sous-module = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + char * Trigger1, * Trigger2; + long comp; + + Trigger1 = (char *) va_arg (Args, void *); + Trigger2 = (char *) va_arg (Args, void *); + + va_end (Args); + + comp = (long)Trigger1 - (long)Trigger2; + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager de la liste de sous-modules d'un channel */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_Channel_SubModuleList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + char ** SubModule = va_arg (Args, char **); + va_list Args_Value = va_arg (Args, va_list); + char * Name = va_arg (Args_Value, char *); + + *SubModule = NULL; + + rc = DS_Alloc (Root, strlen (Name) + 1, (void **) SubModule); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_SubModuleList_Manager : unable to allocate a new submodule"); + LOG_Error_Print (); + return rc; + } + + strcpy (*SubModule, Name); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + char *SubModule = (char *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Sous-module \"%s\"", SubModule); + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + char *SubModule = (char *) va_arg (Args, void *); + + rc = DS_Free (Root, SubModule); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Channel_SubModuleList_Manager : unable to free submodule"); + LOG_Error_Print (); + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de sous-module = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + char * SubModule1, * SubModule2; + long comp; + + SubModule1 = (char *) va_arg (Args, void *); + SubModule2 = (char *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (SubModule1, SubModule2); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Recherche du routage d'un événement pour un channel donné */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Rooting_Find (LOGT_Channel * Channel, int EvtId, LOGT_Rooting * Rooting) +{ + LOGT_Status rc; + LOGT_RTab * RTab; + NDT_Node * RTab_Node; + NDT_Node * Event_Node = NULL; + LOGT_RTab_Evt To_Find; + + if (!Channel) return LOGS_ERRAPI; + + To_Find.Id = EvtId; + + /* Recherche dans toutes les tables de routage du channel */ + + ND_Node_First_Get (Channel->RTab_List, &RTab_Node); + + while (RTab_Node) + { + RTab = (LOGT_RTab *)(RTab_Node->Value); + + rc = DS_Node_Find (RTab->Root, &Event_Node, &To_Find, NULL); + if (DS_ERROR(rc)) return rc; + if (rc == DSS_OK) + { + *Rooting = ((LOGT_RTab_Evt *)(Event_Node->Value))->Rooting; + + /* Si le routage n'est pas celui de la table précédente, alors on a trouvé ! */ + + if (*Rooting != LOGD_ROOTING_PREVIOUS) return LOGS_OK; + } + + ND_Node_Next_Get (RTab_Node, &RTab_Node); + } + + return LOGS_KO; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* CACHE DES MODULES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Manager du cache de modules */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_KMOD_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Module ** Module = va_arg (Args, LOGT_Module **); + va_list Args_Value = va_arg (Args, va_list); + char * Name = va_arg (Args_Value, char *); + int Id = va_arg (Args_Value, int); + + *Module = NULL; + + rc = DS_Alloc (Root, sizeof (LOGT_Module) + strlen (Name) + 1, (void **)Module); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_KMOD_Manager : unable to allocate a new module for the module cache data structure"); + LOG_Error_Print (); + return rc; + } + + (*Module)->Id = Id; + + (*Module)->Name = (char *)((size_t)(*Module) + sizeof (LOGT_Module)); + strcpy ((*Module)->Name, Name); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_Module * Module = (LOGT_Module *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Module \"%s\" (ID = %d)", Module->Name, Module->Id); + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Module * Module = (LOGT_Module *) va_arg (Args, void *); + + DS_Free (Root, Module); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de modules = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_Module * Module1, * Module2; + long comp; + + Module1 = (LOGT_Module *) va_arg (Args, void *); + Module2 = (LOGT_Module *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (Module1->Name, Module2->Name); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* CACHE DES FORMATS D'EVENEMENT */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Manager du cache des formats d'événement */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_KFORMAT_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Event_Format ** Event_Format = va_arg (Args, LOGT_Event_Format **); + va_list Args_Value = va_arg (Args, va_list); + unsigned int Event_Type = va_arg (Args_Value, unsigned int); + + *Event_Format = NULL; + + /* Allocation de la structure LOGT_Event_Format */ + + rc = DS_Alloc (Root, sizeof (LOGT_Event_Format), (void **)Event_Format); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_KFORMAT_Manager : unable to allocate a new event format for the KFORMAT data structure"); + LOG_Error_Print (); + + return rc; + } + + (*Event_Format)->Event_Type = Event_Type; + + /* Création de la liste des données associée au format */ + + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_KFORMAT_NAME), &((*Event_Format)->Data_List), NDD_DS_LIST | NDD_MN_FIFO, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_KFORMAT_Manager : unable to create the event format data list"); + LOG_Error_Print (); + + DS_Free (Root, *Event_Format); + + return rc; + } + else strcpy ((*Event_Format)->Data_List->Manager, "LOG_KFORMAT_DataList_Manager"); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_Event_Format * Event_Format = (LOGT_Event_Format *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Format du type d'événement %d : %ld donnée(s) associée(s)", Event_Format->Event_Type, Event_Format->Data_List->Node_Number); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_Event_Format * Event_Format = (LOGT_Event_Format *) va_arg (Args, void *); + + rc = DS_DataStruct_Close (Event_Format->Data_List, DSD_DESTROY); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_KFORMAT_Manager : unable to destroy the event format data list"); + LOG_Error_Print (); + + return rc; + } + + DS_Free (Root, Event_Format); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de formats d'événement = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_Event_Format * Event_Format1, *Event_Format2; + long comp; + + Event_Format1 = (LOGT_Event_Format *) va_arg (Args, void *); + Event_Format2 = (LOGT_Event_Format *) va_arg (Args, void *); + + va_end (Args); + + comp = Event_Format1->Event_Type - Event_Format2->Event_Type; + + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager d'une liste de données associée à un format d'événement */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_KFORMAT_DataList_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + char ** Event_Data = va_arg (Args, char **); + va_list Args_Value = va_arg (Args, va_list); + char * Data = va_arg (Args_Value, char *); + + *Event_Data = NULL; + + rc = DS_Alloc (Root, strlen (Data) + 1, (void **)Event_Data); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_KFORMAT_DataList_Manager : unable to allocate a new data for the event format data list"); + LOG_Error_Print (); + + return rc; + } + + strcpy (*Event_Data, Data); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + char * Event_Data = (char *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Données de format \"%s\"", Event_Data); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + char * Event_Data = (char *) va_arg (Args, void *); + + DS_Free (Root, Event_Data); + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de données associées aux format = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + char * Event_Data1, *Event_Data2; + long comp; + + Event_Data1 = (char *) va_arg (Args, void *); + Event_Data2 = (char *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (Event_Data1, Event_Data2); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* TABLE GDRT */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Manager de la table GDRT */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_GDRT_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + char * Event_Name = va_arg (Args, char *); + int EvtId = va_arg (Args, int); + LOGT_Gravite Gravite = va_arg (Args, LOGT_Gravite); + LOGT_RC RC = va_arg (Args, LOGT_RC); + LOGT_Rooting Rooting = va_arg (Args, LOGT_Rooting); + int * Nb_Tree = va_arg (Args, int *); + + return LOG_GDRT_Event_Create (Event_Name, EvtId, Gravite, RC, Rooting, Nb_Tree); + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_GDRT_Evt * GDRT_Evt = (LOGT_GDRT_Evt *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Evénement \"%s\" : ", GDRT_Evt->Name); + + if (GDRT_Evt->Terminal == TRUE) + fprintf (Out, "terminal (ID=%d Gravité='%c' RC=%s Routage=%s) / %ld sous-valeur(s)", GDRT_Evt->Id, (char)(GDRT_Evt->Gravite), LOG_RC_Label_Get (GDRT_Evt->RC), LOG_Rooting_Label_Get (GDRT_Evt->Rooting), GDRT_Evt->Next_Dim ? ((NDT_Root *)(GDRT_Evt->Next_Dim))->Node_Number : 0); + else + fprintf (Out, "non terminal / %ld sous-valeur(s)", GDRT_Evt->Next_Dim ? ((NDT_Root *)(GDRT_Evt->Next_Dim))->Node_Number : 0); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_GDRT_Evt *GDRT_Evt = (LOGT_GDRT_Evt *) va_arg (Args, void *); + + if (GDRT_Evt->Next_Dim) + { + rc = DS_DataStruct_Traverse (GDRT_Evt->Next_Dim, NDD_CMD_DELETE_VALUE, NULL); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Manager : unable to destroy the next dimension of value %s from the GDRT data structure", GDRT_Evt->Name); + LOG_Error_Print (); + + return rc; + } + } + + rc = DS_Free (Root, GDRT_Evt); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Manager : unable to free a value from the GDRT data structure"); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre d'événements = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_GDRT_Evt *GDRT_Evt1, *GDRT_Evt2; + long comp; + + GDRT_Evt1 = (LOGT_GDRT_Evt *) va_arg (Args, void *); + GDRT_Evt2 = (LOGT_GDRT_Evt *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (GDRT_Evt1->Name, GDRT_Evt2->Name); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Manager des dimensions des événements de la table GDRT */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_GDRT_Dim_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_GDRT_Evt *GDRT_Evt = (LOGT_GDRT_Evt *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Dimension \"%s\" :\n\t- ID = %d\n\t- Gravité = '%c'\n\t- Code retour = %s\n\t- Routage = %s\n\t- Dimension suivante = %ld valeur(s)", GDRT_Evt->Name, GDRT_Evt->Id, (char)(GDRT_Evt->Gravite), LOG_RC_Label_Get (GDRT_Evt->RC), LOG_Rooting_Label_Get (GDRT_Evt->Rooting), GDRT_Evt->Next_Dim ? ((NDT_Root *)(GDRT_Evt->Next_Dim))->Node_Number : 0); + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_GDRT_Evt *GDRT_Evt = (LOGT_GDRT_Evt *) va_arg (Args, void *); + + if (GDRT_Evt->Next_Dim) + { + rc = DS_DataStruct_Traverse (GDRT_Evt->Next_Dim, NDD_CMD_DELETE_VALUE, NULL); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Dim_Manager : unable to destroy the next dimension of value %s from the GDRT data structure", GDRT_Evt->Name); + LOG_Error_Print (); + + return rc; + } + } + + rc = DS_Free (Root, GDRT_Evt); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Dim_Manager : unable to free a value from the GDRT data structure"); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre de contextes = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_GDRT_Evt *GDRT_Evt1, *GDRT_Evt2; + long comp; + + GDRT_Evt1 = (LOGT_GDRT_Evt *) va_arg (Args, void *); + GDRT_Evt2 = (LOGT_GDRT_Evt *) va_arg (Args, void *); + + va_end (Args); + + comp = strcmp (GDRT_Evt1->Name, GDRT_Evt2->Name); + + if (comp < 0) return NDS_LOWER; + + if (comp > 0) return NDS_GREATER; + + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Création d'un événement dans la table GDRT */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_GDRT_Event_Create (const char * Event_Name, int Id, LOGT_Gravite Gravite, LOGT_RC RC, LOGT_Rooting Rooting, int *Nb_Tree) +{ + LOGT_Status rc; + int i; + char * ptr; + NDT_Node * Node; + char * Tab_Dim [EVENT_NB_DIM]; + LOGT_GDRT_Evt * Evt; + NDT_Root * Root; + LOGT_GDRT_Evt To_Find; + + ptr = strdup (Event_Name); + + for (i = 0; i < EVENT_NB_DIM; i++) Tab_Dim [i] = NULL; + + /* Récupération des dimensions du type d'événement */ + + i = 0; + + while (i < EVENT_NB_DIM) + { + Tab_Dim [i] = ptr; + + if (i < EVENT_NB_DIM - 1) + { + char sep = (i == 0 ? '@' : ':'); + + if ((ptr = strchr (Tab_Dim [i], sep))) + { + *ptr = (char)0; + ptr++; + } + else i = EVENT_NB_DIM; + } + i++; + } + + /* Création des différentes dimensions (1 dimension = 1 arbre) */ + + Root = LOG_Base->GDRT->Root; + + for (i = 0; i < EVENT_NB_DIM; i++) + { + if (!Tab_Dim [i]) return LOGS_OK; + + /* Ajout de la dimension si elle n'existe pas */ + + To_Find.Name = Tab_Dim [i]; + + rc = ND_Node_Find (Root, &Node, &To_Find, NULL); + if (rc != NDS_OK) + { + /* Allocation de la nouvelle valeur */ + + rc = DS_Alloc (Root, sizeof (LOGT_GDRT_Evt) + strlen (Tab_Dim [i]) + 1, (void **)(&Evt)); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Event_Create : unable to allocate memory for a new value of the dimension %d", i); + LOG_Error_Print (); + return rc; + } + + Evt->Id = 0; + Evt->Gravite = 0; + Evt->RC = 0; + Evt->Rooting = 0; + Evt->Next_Dim = NULL; + Evt->Terminal = FALSE; + + Evt->Name = (char *)((size_t)Evt + sizeof (LOGT_GDRT_Evt)); + strcpy (Evt->Name, Tab_Dim [i]); + + /* Ajout de la valeur */ + + rc = ND_Value_Add (Root, Evt); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Event_Create : unable to add a new value in the data structureof dimension %d", i); + LOG_Error_Print (); + return rc; + } + } + else Evt = (LOGT_GDRT_Evt *)(Node->Value); + + /* Est-on à la fin du nom du type d'événement */ + + if (i == EVENT_NB_DIM - 1 || !Tab_Dim [i + 1]) + { + Evt->Terminal = TRUE; + Evt->Id = Id; + Evt->Gravite = Gravite; + Evt->RC = RC; + Evt->Rooting = Rooting; + return LOGS_OK; + } + + /* Création de la dimension suivante si elle n'existe pas déjà */ + + if (!Evt->Next_Dim) + { + rc = DS_DataStruct_Open (LOG_Name_Prefix (LOGD_GDRT_NAME), &(Evt->Next_Dim), NDD_DS_TREE | NDD_MN_AUTO_EQU, LOG_FILE_MANAGER, 0, DSD_NEW, TRUE); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Event_Create : unable to create a data structure for the dimension %d", i + 1); + LOG_Error_Print (); + return rc; + } + + strcpy (Evt->Next_Dim->Manager, "LOG_GDRT_Dim_Manager"); + + (*Nb_Tree)++; + } + + Root = Evt->Next_Dim; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Recherche dans la table de routage par défaut (GDRT) */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_GDRT_Event_Find (LOGT_GDRT_Evt ** Evt, char ** Complete_Name, char * Event_Name) +{ + LOGT_Status rc; + char * ptr; + int i; + char * Tab_Dim [EVENT_NB_DIM]; + + *Evt = NULL; + + **Complete_Name = (char)0; + + ptr = strdup (Event_Name); + + for (i = 0; i < EVENT_NB_DIM; i++) Tab_Dim [i] = NULL; + + /* Récupération des dimensions du type d'événement */ + + i = 0; + + while (i < EVENT_NB_DIM) + { + Tab_Dim [i] = ptr; + + if (i < EVENT_NB_DIM - 1) + { + char sep = (i == 0 ? '@' : ':'); + + if ((ptr = strchr (Tab_Dim [i], sep))) + { + *ptr = (char)0; + ptr++; + } + else i = EVENT_NB_DIM; + } + i++; + } + + /* Recherche de l'événement */ + + rc = LOG_GDRT_Recursive_Find (Tab_Dim, LOG_Base->GDRT->Root, 0, Evt, Complete_Name); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_GDRT_Event_Find : unable to find event \"%s\"", Event_Name); + LOG_Error_Print (); + + free (Tab_Dim [0]); + + return rc; + } + + free (*Tab_Dim); + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Fonction de recherche récursive dans les différentes dimensions */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_GDRT_Recursive_Find (char ** Tab_Dim, NDT_Root * Root, int Dim, LOGT_GDRT_Evt ** Evt, char ** Complete_Name) +{ + LOGT_Status rc; + int Found, End; + NDT_Node * Node; + char Default_Name [10]; + char * Dim_Name; + char * ptr; + LOGT_GDRT_Evt To_Find; + + if (!Root || !Tab_Dim [Dim]) return LOGS_ERRAPI; + + /* Définition de la valeur par défaut à rechercher */ + + if (Dim == 0) strcpy (Default_Name, "DEFAULT"); + else strcpy (Default_Name, ""); + + Dim_Name = strdup (Tab_Dim [Dim]); + + /* Recherche du type d'événement le plus proche */ + + Found = End = FALSE; + + while (Found == FALSE && End == FALSE) + { + To_Find.Name = Dim_Name; + + if (ND_Node_Find (Root, &Node, &To_Find, NULL) == NDS_OK) + { + /* Résolution de la dimension suivante */ + + if (LOG_GDRT_Recursive_Find (Tab_Dim, ((LOGT_GDRT_Evt *)(Node->Value))->Next_Dim, Dim + 1, Evt, Complete_Name) == LOGS_OK) + { + Found = TRUE; + End = TRUE; + } + else + { + /* Le noeud trouvé est-il terminal ? */ + + if (((LOGT_GDRT_Evt *)(Node->Value))->Terminal == TRUE) + { + *Evt = (LOGT_GDRT_Evt *)(Node->Value); + Found = TRUE; + End = TRUE; + } + } + } + + if (End == FALSE) + { + ptr = strchr (Dim_Name, '.'); + if (ptr) *ptr = (char)0; + else + { + /* + Dernière chance de résoudre la dimension : + - "DEFAULT" pour le nom du type d'événement + - "" pour le contexte + */ + + if (!strcmp (Dim_Name, Default_Name)) End = TRUE; + else strcpy (Dim_Name, Default_Name); + } + } + } + + if (Found == TRUE) + { + if (strlen (Dim_Name)) + { + *Complete_Name -= strlen (Dim_Name); + memcpy (*Complete_Name, Dim_Name, strlen (Dim_Name)); + } + + if (Dim > 0) + { + *Complete_Name -= 1; + **Complete_Name = (Dim == 1 ? '@' : ':'); + } + + rc = LOGS_OK; + } + else rc = LOGS_KO; + + free (Dim_Name); + + return rc; +} + +/*------------------------------------------------------------------------------*/ +/* Sélection récursive des types d'événements dans la GDRT */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_GDRT_Recursive_Select (int Dim, NDT_Root * Root, LOGT_RTab * RTab, LOGT_RuleClass Rule_Class, LOGT_Rule * Rule, LOGT_Rooting Value, const char * Name, char * Compiled_RegExp) +{ + LOGT_Status rc; + NDT_Node * Node; + + if (!Root) return LOGS_ERRAPI; + + ND_Node_First_Get (Root, &Node); + + while (Node) + { + LOGT_GDRT_Evt * GDRT_Evt = (LOGT_GDRT_Evt *)(Node->Value); + int Selected = FALSE; + char Event_Name [81]; + LOGT_Rooting Rooting = (Value == LOGD_ROOTING_DEFAULT ? GDRT_Evt->Rooting : Value); + + if (Dim == 0) strcpy (Event_Name, GDRT_Evt->Name); + else sprintf (Event_Name, "%s%c%s", Name, Dim == 1 ? '@' : ':', GDRT_Evt->Name); + + if (GDRT_Evt->Terminal == TRUE) + { + /* On vérifie si le type d'événement correspond au critère de sélection */ + + switch (Rule_Class) + { + case LOGD_SELECT_ALL: + + Selected = TRUE; + break; + + case LOGD_SELECT_GRV: + + if (GDRT_Evt->Gravite == *(LOGT_Gravite *)Rule) Selected = TRUE; + break; + + case LOGD_SELECT_RC: + + if (GDRT_Evt->RC == *(LOGT_RC *)Rule) Selected = TRUE; + break; + + case LOGD_SELECT_TYPE: + + /* L'événement matche-t'il avec l'expression régulière ? */ + + if (RegExp_Match (Event_Name, Compiled_RegExp) && GDRT_Evt->Terminal == TRUE) Selected = TRUE; + break; + } + } + + if (Selected == TRUE) + { + NDT_Node * Tmp_Node; + LOGT_RTab_Evt Tmp_Evt; + + Tmp_Evt.Id = GDRT_Evt->Id; + + /* Si le type d'événement n'existe pas déjà, on l'ajoute à la table de routage utilisateur */ + + rc = DS_Node_Find (RTab->Root, &Tmp_Node, (void *)&Tmp_Evt, NULL); + if (rc != DSS_OK) + { + LOGT_RTab_Evt * RTab_Evt; + + rc = DS_Value_Alloc (RTab->Root, (void **)&RTab_Evt, GDRT_Evt->Id, Rooting); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Setup : unable to create event type %d for the user rooting table", GDRT_Evt->Id); + LOG_Error_Print (); + return rc; + } + + rc = DS_Value_Add (RTab->Root, (void *)RTab_Evt); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Setup : unable to add event type %d to the user rooting table", GDRT_Evt->Id); + LOG_Error_Print (); + return rc; + } + } + } + + LOG_GDRT_Recursive_Select (Dim + 1, GDRT_Evt->Next_Dim, RTab, Rule_Class, Rule, Value, Event_Name, Compiled_RegExp); + + ND_Node_Next_Get (Node, &Node); + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* AUTRES TABLES DE ROUTAGE (GMRT, LMRT, LDRT, URT) */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Manager des tables de routage autres que GDRT */ +/*------------------------------------------------------------------------------*/ +NDT_Status LOG_RTab_Manager (va_list Args) +{ + LOGT_Status rc; + NDT_Command Command = va_arg (Args, NDT_Command); + + if (Command == NDD_CMD_MAKE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_RTab_Evt ** RTab_Evt = (LOGT_RTab_Evt **) va_arg (Args, void **); + va_list Args_Value = va_arg (Args, va_list); + int Id = (int) va_arg (Args_Value, int); + LOGT_Rooting Rooting = (LOGT_Rooting) va_arg (Args_Value, LOGT_Rooting); + + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + rc = DS_Alloc (Root, sizeof (LOGT_RTab_Evt), (void **)RTab_Evt); + if (rc != NDS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Manager : unable to allocate a new event for rooting table \"%s\"", RootDesc ? RootDesc->Heap_Name : "User"); + LOG_Error_Print (); + return rc; + } + + (*RTab_Evt)->Id = Id; + (*RTab_Evt)->Rooting = Rooting; + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_VALUE) + { + LOGT_RTab_Evt * RTab_Evt = (LOGT_RTab_Evt *) va_arg (Args, void *); + FILE * Out = va_arg (Args, FILE *); + + fprintf (Out, "Evénement :\n\t- ID = %d\n\t- Routage = %s", RTab_Evt->Id, LOG_Rooting_Label_Get (RTab_Evt->Rooting)); + + return NDS_OK; + } + + if (Command == NDD_CMD_DELETE_VALUE) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + LOGT_RTab_Evt * RTab_Evt = (LOGT_RTab_Evt *) va_arg (Args, void *); + DST_RootDesc * RootDesc = (DST_RootDesc *)(Root->User); + + rc = DS_Free (Root, (void *)RTab_Evt); + if (rc != DSS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_RTab_Manager : unable to free an event of rooting table \"%s\"", RootDesc ? RootDesc->Heap_Name : "User"); + LOG_Error_Print (); + + return rc; + } + + return NDS_OK; + } + + if (Command == NDD_CMD_PRINT_INFO) + { + NDT_Root * Root = va_arg (Args, NDT_Root *); + FILE * Out = va_arg (Args, FILE *); + const 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 = "liste triée"; break; + case NDD_MN_FILO : Root_Type = "liste FILO"; break; + case NDD_MN_FIFO : Root_Type = "liste FIFO"; break; + default : Root_Type = "inconnu"; break; + } + break; + + case NDD_DS_TREE : + + switch ((int)(Root->Type & NDD_MN_MSK)) + { + case NDD_MN_AUTO_EQU : Root_Type = "arbre auto-équilibré"; break; + default : Root_Type = "arbre non auto-équilibré"; break; + } + break; + + default : Root_Type = "inconnu"; break; + } + + RootDesc = (DST_RootDesc *)(Root->User); + fprintf (Out, "\n%s\n\t- Structure = %s\n\t- Manager = %s\n\t- Nombre d'événements = %ld\n", RootDesc->Heap_Name, Root_Type, RootDesc->Manager_FileName, Root->Node_Number); + + if (Root->Type & 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); + + return NDS_OK; + } + + if (Command == NDD_CMD_COMP_VALUE) + { + LOGT_RTab_Evt * RTab_Evt1, * RTab_Evt2; + long comp; + + RTab_Evt1 = (LOGT_RTab_Evt *) va_arg (Args, void *); + RTab_Evt2 = (LOGT_RTab_Evt *) va_arg (Args, void *); + + va_end (Args); + + comp = RTab_Evt1->Id - RTab_Evt2->Id; + + if (comp < 0) return NDS_LOWER; + if (comp > 0) return NDS_GREATER; + return NDS_EQUAL; + } + + return NDS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS RELATIVES AUX EVENEMENTS */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Récupération des données de l'événement à partir d'une liste d'arguments */ +/* ou d'une chaîne de caractères. */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Data_Get (int Mode, char * Support, char ** Event_Data, size_t * Data_Size, va_list * Arg_Data, char * Str_Data) +{ + LOGT_Status rc; + char Event_Name [81]; + int Tag; + char Value [256]; + char Macro [256]; + int End = FALSE; + int Context = FALSE; + char * even [3] = {NULL, NULL, NULL}; + char * module [3] = {NULL, NULL, NULL}; + char * mode [3] = {NULL, NULL, NULL}; + char * geo [3] = {NULL, NULL, NULL}; + char * ptr; + char * Ptr_Data = Str_Data; + unsigned int i; + size_t New_Size; + + *Event_Data = NULL; + *Data_Size = 0; + + /* + Récupération des composants du nom de l'événement : + + EVEN1[.EVEN2[.EVEN3]]@[MODULE1[.MODULE2[.MODULE3]]]:[MODE1[.MODE2[.MODE3]]]:[GEO1[.GEO2[.GEO3]]] + + NB : le nom de l'événement est délimité par le tag END_NAME. + */ + + while (End == FALSE) + { + rc = LOG_Event_Data_Tag_Get (Mode, Arg_Data, &Ptr_Data, &Tag, Value); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Get : unable to retrieve event name from the data %s", Mode == DATA_ARG_LIST ? "argument list" : "string"); + LOG_Error_Print (); + return rc; + } + + switch (Tag) + { + case EVEN1: + even [0] = strdup (Value); + break; + + case EVEN2: + even [1] = strdup (Value); + break; + + case EVEN3: + even [2] = strdup (Value); + break; + + case MODULE1: + module [0] = strdup (Value); + Context = TRUE; + break; + + case MODULE2: + module [1] = strdup (Value); + Context = TRUE; + break; + + case MODULE3: + module [2] = strdup (Value); + Context = TRUE; + break; + + case MODE1: + mode [0] = strdup (Value); + Context = TRUE; + break; + + case MODE2: + mode [1] = strdup (Value); + Context = TRUE; + break; + + case MODE3: + mode [2] = strdup (Value); + Context = TRUE; + break; + + case GEO1: + geo [0] = strdup (Value); + Context = TRUE; + break; + + case GEO2: + geo [1] = strdup (Value); + Context = TRUE; + break; + + case GEO3: + geo [2] = strdup (Value); + Context = TRUE; + break; + + case END_NAME: + End = TRUE; + break; + + default : + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Get : unexpected tag %d before END_NAME", Tag); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + } + + /* Reconstitution du nom de l'événement */ + + if (!even [0]) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Get : tag EVEN1 must be defined before END_NAME"); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + strcpy (Event_Name, even [0]); + + for (i = 1; i < 3; i++) + { + if (even [i]) + { + strcat (Event_Name, "."); + strcat (Event_Name, even [i]); + free (even [i]); + } + else break; + } + + if (Context == TRUE) strcat (Event_Name, "@"); + else return LOGS_OK; + + for (i = 0; i < 3; i++) + { + if (module [i]) + { + strcat (Event_Name, i > 0 ? "." : ""); + strcat (Event_Name, module [i]); + free (module [i]); + } + else break; + } + + strcat (Event_Name, ":"); + + for (i = 0; i < 3; i++) + { + if (mode [i]) + { + strcat (Event_Name, i > 0 ? "." : ""); + strcat (Event_Name, mode [i]); + free (mode [i]); + } + else break; + } + + strcat (Event_Name, ":"); + + for (i = 0; i < 3; i++) + { + if (geo [i]) + { + strcat (Event_Name, i > 0 ? "." : ""); + strcat (Event_Name, geo [i]); + free (geo [i]); + } + else break; + } + + /* On recopie le nom de l'événement au début de la chaîne de caractères contenant les données */ + + *Data_Size = 0; + *Event_Data = NULL; + + i = strlen (Event_Name); + New_Size = *Data_Size + i + 1; + *Event_Data = (char *)realloc (*Event_Data, New_Size); + ptr = *Event_Data + *Data_Size; + *Data_Size = New_Size; + *ptr = (char)i; + ptr ++; + memcpy (ptr, (void *)Event_Name, i); + + /* On recopie le code support comme étant la première macro-donnée */ + + i = strlen (Support); + New_Size = *Data_Size + i + 1; + *Event_Data = (char *)realloc (*Event_Data, New_Size); + ptr = *Event_Data + *Data_Size; + *Data_Size = New_Size; + *ptr = (char)i; + ptr ++; + memcpy (ptr, (void *)Support, i); + + /* Récupération des macro-données associées à l'événement */ + + End = FALSE; + + while (End == FALSE) + { + unsigned int j; + + rc = LOG_Event_Data_Macro_Get (Mode, Arg_Data, &Ptr_Data, Macro, Value); + if (rc != LOGS_OK) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Get : unable to retrieve event macro data from the data %s", Mode == DATA_ARG_LIST ? "argument list" : "string"); + LOG_Error_Print (); + return rc; + } + + if (!strcmp (Macro, END_DATA)) break; + + i = strlen (Macro); + j = strlen (Value); + + New_Size = *Data_Size + i + j + 2; + *Event_Data = (char *)realloc (*Event_Data, New_Size); + ptr = *Event_Data + *Data_Size; + *Data_Size = New_Size; + *ptr = (char)i; + ptr ++; + memcpy (ptr, (void *)Macro, i); + ptr += i; + *ptr = (char)j; + ptr ++; + memcpy (ptr, (void *)Value, j); + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération d'un composant (tag et valeur) d'un nom d'événement */ +/* à partir d'une liste d'arguments ou d'une chaîne de caractères. */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Data_Tag_Get (int Mode, va_list * Arg_Data, char ** ptr, int * Tag, char * Value) +{ + if (Mode == DATA_ARG_LIST) + { + *Tag = va_arg (*Arg_Data, int); + if (*Tag != END_NAME) strcpy (Value, va_arg (*Arg_Data, char *)); + return LOGS_OK; + } + + if (Mode == DATA_STRING) + { + char sTag [256]; + + if (LOG_NextString_Get (ptr, sTag) != TRUE) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Tag_Get : missing tag after value %s", Value); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!strcmp (sTag, "EVEN1")) *Tag = EVEN1; + else if (!strcmp (sTag, "EVEN2")) *Tag = EVEN2; + else if (!strcmp (sTag, "EVEN3")) *Tag = EVEN3; + else if (!strcmp (sTag, "MODULE1")) *Tag = MODULE1; + else if (!strcmp (sTag, "MODULE2")) *Tag = MODULE2; + else if (!strcmp (sTag, "MODULE3")) *Tag = MODULE3; + else if (!strcmp (sTag, "MODE1")) *Tag = MODE1; + else if (!strcmp (sTag, "MODE2")) *Tag = MODE2; + else if (!strcmp (sTag, "MODE3")) *Tag = MODE3; + else if (!strcmp (sTag, "GEO1")) *Tag = GEO1; + else if (!strcmp (sTag, "GEO2")) *Tag = GEO2; + else if (!strcmp (sTag, "GEO3")) *Tag = GEO3; + else if (!strcmp (sTag, "END_NAME")) *Tag = END_NAME; + else *Tag = 0; + + if (*Tag != END_NAME) + { + char str [256]; + + if (LOG_NextString_Get (ptr, str) != TRUE) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Tag_Get : missing value after tag %s", sTag); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + strcpy (Value, str); + } + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération d'une macro donnée (tag et valeur) associé à une événement */ +/* à partir d'une liste d'arguments ou d'une chaîne de caractères. */ +/*------------------------------------------------------------------------------*/ +/* Pour une liste d'arguments, une macro-donnée est donnée par un triplet : */ +/* - nom (char *) */ +/* - type (int) */ +/* - valeur (char *) */ +/* */ +/* Pour une chaîne de caractères, une macro-donnée est donnée par un couple : */ +/* - nom (char *) */ +/* - valeur (char *) : les espaces sont remplacés par des '~' */ +/* */ +/* NB : les macro-données sont délimitées par le tag END_DATA. */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Data_Macro_Get (int Mode, va_list * Arg_Data, char ** ptr, char * Macro, char * Value) +{ + if (Mode == DATA_ARG_LIST) + { + int Type; + + strcpy (Macro, va_arg (*Arg_Data, char *)); + + if (!strcmp (Macro, END_DATA)) return LOGS_OK; + + Type = va_arg (*Arg_Data, int); + + switch (Type) + { + case STRING: + strcpy (Value, va_arg (*Arg_Data, char *)); + break; + + case CHAR: + sprintf (Value, "%c", *va_arg (*Arg_Data, char *)); + break; + + case SHORT: + sprintf (Value, "%d", *va_arg (*Arg_Data, short *)); + break; + + case INT: + sprintf (Value, "%d", *va_arg (*Arg_Data, int *)); + break; + + case LONG: + sprintf (Value, "%ld", *va_arg (*Arg_Data, long *)); + break; + + case FLOAT: + sprintf (Value, "%f", *va_arg (*Arg_Data, float *)); + break; + + case DOUBLE: + sprintf (Value, "%f", *va_arg (*Arg_Data, double *)); + break; + + default : + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Macro_Get : unexpected type %d after macro \"%s\"", Type, Macro); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + return LOGS_OK; + } + + if (Mode == DATA_STRING) + { + char * tmp; + + if (LOG_NextString_Get (ptr, Macro) != TRUE) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Macro_Get : missing macro after value %s", Value); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + if (!strcmp (Macro, END_DATA)) return LOGS_OK; + + if (LOG_NextString_Get (ptr, Value) != TRUE || !strcmp (Value, END_DATA)) + { + sprintf (LOG_Error_Msg, "Error LOG_Event_Data_Macro_Get : missing value after macro %s", Macro); + LOG_Error_Print (); + return LOGS_ERRAPI; + } + + /* On remplace les '~' par des espaces */ + + while ((tmp = strchr (Value, '~'))) *tmp = ' '; + + return LOGS_OK; + } + + return LOGS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération de la prochaine valeur dans une chaîne de caractères (valeurs */ +/* séparées par des espaces) */ +/*------------------------------------------------------------------------------*/ +int LOG_NextString_Get (char ** ptr, char * result) +{ + int i = 0; + + /* On recherche le premier caractère différent non blanc (espace, tab, newline) */ + + while (isspace ((int)(**ptr)) && **ptr != (char)0) (*ptr)++; + + if (**ptr == (char)0) return FALSE; + + /* On recopie le pointeur dans la chaîne résultat jusqu'au premier caractère blanc */ + + while (!isspace ((int)(**ptr)) && **ptr != (char)0) + { + result [i] = **ptr; + i++; + (*ptr)++; + } + + result [i] = (char)0; + + return TRUE; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* FONCTIONS DIVERSES */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Récupération du libellé d'un code retour */ +/*------------------------------------------------------------------------------*/ +char * LOG_RC_Label_Get (LOGT_RC RC) +{ + static char Label [20]; + + switch ((int)RC) + { + case LOGD_RC_OK: + strcpy (Label, "OK"); + break; + + case LOGD_RC_ANOERR: + strcpy (Label, "ANOERR"); + break; + + case LOGD_RC_REJDON: + strcpy (Label, "REJDON"); + break; + + case LOGD_RC_REJENR: + strcpy (Label, "REJENR"); + break; + + case LOGD_RC_WARNING: + strcpy (Label, "WARNING"); + break; + + case LOGD_RC_RECYCLE: + strcpy (Label, "RECYCLE"); + break; + + case LOGD_RC_EXIT: + strcpy (Label, "EXIT"); + break; + + case LOGD_RC_ABEND: + strcpy (Label, "ABEND"); + break; + + default : + strcpy (Label, "unknown"); + break; + } + + return Label; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du libellé d'un type de routage */ +/*------------------------------------------------------------------------------*/ +char * LOG_Rooting_Label_Get (LOGT_Rooting Rooting) +{ + static char Label [20]; + + switch ((int)Rooting) + { + case LOGD_ROOTING_NULL: + strcpy (Label, "NULL"); + break; + + case LOGD_ROOTING_STDERR: + strcpy (Label, "STDERR"); + break; + + case LOGD_ROOTING_DATABASE: + strcpy (Label, "BASE"); + break; + + case LOGD_ROOTING_DEFAULT: + strcpy (Label, "DEFAULT"); + break; + + case LOGD_ROOTING_PREVIOUS: + strcpy (Label, "PREVIOUS"); + break; + + default : + strcpy (Label, "unknown"); + break; + } + + return Label; +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du type de table de routage */ +/*------------------------------------------------------------------------------*/ +char * LOG_RTType_Label_Get ( LOGT_RTType RTabType ) +{ + static char Label [20]; + + switch ((int)RTabType) + { + case LOGD_GDRT: + strcpy (Label, "Global Default Rooting Table"); + break; + + case LOGD_GMRT: + strcpy (Label, "Global Master Rooting Table"); + break; + + case LOGD_LDRT: + strcpy (Label, "Local Default Rooting Table"); + break; + + case LOGD_LMRT: + strcpy (Label, "Local Master Rooting Table"); + break; + + case LOGD_URT: + strcpy (Label, "User Rooting Table"); + break; + + default : + strcpy (Label, "unknown"); + break; + } + + return Label; +} + +/*------------------------------------------------------------------------------*/ +/* Routine d'affichage d'un message d'erreur */ +/*------------------------------------------------------------------------------*/ +void LOG_Error_Print ( void ) +{ + if (LOG_stderr) fprintf (LOG_stderr, "%s\n", LOG_Error_Msg); +} + +/*------------------------------------------------------------------------------*/ +/* Pour préfixer les noms de heap avec le contexte de la librairie LIBLOG */ +/*------------------------------------------------------------------------------*/ +static char * LOG_Name_Prefix ( const char * Name ) +{ + static char Prefixed [256]; + + sprintf (Prefixed, "%s/%s", LOG_PREFIX, Name); + + return Prefixed; +} diff --git a/lib/liblog.doc b/lib/liblog.doc new file mode 100644 index 0000000..1629082 Binary files /dev/null and b/lib/liblog.doc differ diff --git a/lib/liblog.h b/lib/liblog.h new file mode 100644 index 0000000..622a80b --- /dev/null +++ b/lib/liblog.h @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Expressions régulières */ + +#ifdef LINUX +#include +typedef regex_t RegExp_t; +#define RegExp_Size sizeof (regex_t) +#define RegExp_Compile(s, e) regcomp (e, s, REG_NOSUB) == 0 +#define RegExp_Match(s, e) regexec (e, s, 0, NULL, 0) != REG_NOMATCH +#else +#include +typedef char RegExp_t; +#define RegExp_Size 256 +#define RegExp_Compile(s, e) compile (s, e, e + RegExp_Size) +#define RegExp_Match(s, e) step (s, e) +#endif + +extern char * strdup (const char *); + +/* Nom de la variable d'environnement définissant la valeur par défaut du module maître */ + +#define MASTER_MODULE_ENV "MASTER" + +#define LOG_FILE_MANAGER "liblog.so" + +/* Tous les heaps et data structures générés par la librairie LIBLOG sont préfixés */ + +#define LOG_PREFIX "LOG" + +/* Port de messages d'envoi des événements */ + +MSGT_Port * Send_Port; + +/* Elément du cache des modules */ + +typedef struct { + char * Name; /* Nom du module (sert à la recherche) */ + int Id; /* Identifiant numérique du type d'événement */ +} LOGT_Module; + +/* Elément de la table de routage GDRT */ + +typedef struct { + char * Name; /* Nom du type d'événement (base de recherche) */ + int Terminal; /* Signifie que le type d'événement existe sans contexte */ + int Id; /* Identifiant numérique du type d'événement */ + LOGT_Gravite Gravite; /* Code gravité */ + LOGT_RC RC; /* Code de retour servant au pilotage */ + LOGT_Rooting Rooting; /* Type de routage par défaut */ + NDT_Root * Next_Dim; /* Dimension suivante = pointeur sur un arbre */ +} LOGT_GDRT_Evt; + +#define EVENT_NB_DIM 4 + +/* Elément d'une table de routage quelconque (hormis la GDRT) */ + +typedef struct { + int Id; /* Identifiant numérique du type d'événement (sert à la recherche) */ + LOGT_Rooting Rooting; /* Type de routage */ +} LOGT_RTab_Evt; + + +/* Définition du nom des différentes ressources de la librairie */ + +/* + Heap dans lequel sera stockée la base de la librairie LIBLOG : + Ce heap ne contient que la structure LOGT_Base qui permet de référencer + les autres ressources système de la librairie. + + Ce heap ne sera constitué que d'une unique segment très petit. +*/ + +#define LOGD_BASE_HEAP_NAME "BASE" +#define LOGD_BASE_HEAP_SEGMENT_SIZE 100 + +/* + Heap dans lequel sont stockées les caches : + Ces heaps contiennent à priori un grand nombre de valeurs. + On les crée donc avec des segments de données suffisamment grands. +*/ + +#define LOGD_KMOD_SEGMENT_SIZE 50000 +#define LOGD_KMOD_NAME "KMOD" + +#define LOGD_KFORMAT_SEGMENT_SIZE 1100000 +#define LOGD_KFORMAT_NAME "KFORMAT" + +#define LOGD_GDRT_SEGMENT_SIZE 400000 +#define LOGD_GDRT_NAME "GDRT" + +/* + En règle générale, les tables de routage suivantes resteront vides : + Leur heap sont donc créés avec des segments de données relativement petits. +*/ + +#define LOGD_EMPTY_RTAB_SEGMENT_SIZE 3000 +#define LOGD_GMRT_NAME "GMRT" +#define LOGD_LDRT_NAME "LDRT" +#define LOGD_LMRT_NAME "LMRT" + +/* + Heap dans lequel sera stockée les listes de tables de routage : + Ces liste ne contiendront pas à priori un grand nombre de valeurs. + Les heaps sous-jacents n'ont donc pas besoin besoin d'être très grands. +*/ + +#define LOGD_RTAB_LIST_SEGMENT_SIZE 100240 +#define LOGD_CHANNEL_LIST_NAME "CHANNEL_REF" +#define LOGD_LDRT_LIST_NAME "LDRT_REF" +#define LOGD_LMRT_LIST_NAME "LMRT_REF" +#define LOGD_URT_LIST_NAME "URT_REF" + +/* Elément d'une structure de compteurs d'événement */ + +typedef struct { + char * Name; /* Nom du type d'événement */ + int Total; /* Nombre total d'envois */ +} LOGT_Event_Cpt; + +SMT_Heap * LOG_Base_Heap; + +/* Compteur d'ouverture de la librairie */ + +unsigned int LOG_Open_Counter = 0; + +/* Flux de sortie des messages d'erreur générés par la librairie */ + +FILE * LOG_stderr; + +/* Entêtes des fonctions privées */ + +NDT_Status LOG_Base_RTabList_Manager (va_list args_ptr); +NDT_Status LOG_Base_ChannelList_Manager (va_list args_ptr); + +NDT_Status LOG_GDRT_Manager (va_list); +NDT_Status LOG_GDRT_Dim_Manager (va_list); +LOGT_Status LOG_GDRT_Event_Find (LOGT_GDRT_Evt **, char **, char *); +LOGT_Status LOG_GDRT_Recursive_Find (char **, NDT_Root *, int, LOGT_GDRT_Evt **, char **); +LOGT_Status LOG_GDRT_Event_Create (const char *, int, LOGT_Gravite, LOGT_RC, LOGT_Rooting, int *); +LOGT_Status LOG_GDRT_Recursive_Select (int, NDT_Root *, LOGT_RTab *, LOGT_RuleClass, LOGT_Rule *, LOGT_Rooting, const char *, char *); + +NDT_Status LOG_KMOD_Manager (va_list); + +NDT_Status LOG_KFORMAT_Manager (va_list); +NDT_Status LOG_KFORMAT_DataList_Manager (va_list); + +NDT_Status LOG_Channel_RTabList_Manager (va_list); +NDT_Status LOG_Channel_Event_CptList_Manager (va_list); +NDT_Status LOG_Channel_SubModuleList_Manager (va_list); +NDT_Status LOG_Channel_TriggerList_Manager (va_list); +LOGT_Status LOG_Channel_Rooting_Find (LOGT_Channel *, int, LOGT_Rooting *); + +NDT_Status LOG_RTab_Manager (va_list); + +#define DATA_ARG_LIST 1 +#define DATA_STRING 2 + +LOGT_Status LOG_Event_Internal_Send (int, LOGT_Channel *, LOGT_RC *, char *, va_list, char *); +LOGT_Status LOG_Event_Data_Get (int, char *, char **, size_t *, va_list *, char *); +LOGT_Status LOG_Event_Data_Tag_Get (int, va_list *, char **, int *, char *); +LOGT_Status LOG_Event_Data_Macro_Get (int, va_list *, char **, char *, char *); + +int LOG_NextString_Get (char ** ptr, char * result); + +char * LOG_RTType_Label_Get (LOGT_RTType); +char * LOG_RC_Label_Get (LOGT_RC); +char * LOG_Rooting_Label_Get (LOGT_Rooting); + +void LOG_Error_Print(void); + +static char * LOG_Name_Prefix (const char *); diff --git a/lib/libtool.3 b/lib/libtool.3 new file mode 100644 index 0000000..a639100 --- /dev/null +++ b/lib/libtool.3 @@ -0,0 +1,424 @@ +'\" t +.\" @(#)LIBTOOL.3 1.0 00/22/02 SMA; +.TH LIBTOOL 3 "22 Feb 2000" +.SH NOM +LIBTOOL (utilitaires pour la librairie LIBLOG) +.SH SYNOPSIS +.LP +.BI "cc [flag ...] file ... -lver -ldl -lnode -lshmem -ldatastr -ladm -llog -ltool [library ...]" +.LP +.BI "#include " +.LP +.BI "TLT_Status TL_Library_Stderr_Set ( FILE * " Out ");" +.LP +.BI "TLT_Status TL_LIBLOG_Load ( TL_Cache " To_Load " );" +.LP +.BI "TLT_Status TL_LIBLOG_Unload ( TL_Cache " To_Unload " );" +.LP +.BI "TLT_Status TL_Channel_RTab_Add ( LOGT_Channel * " Channel ", char * " Kunf_Name " );" +.LP +.BI "TLT_Status TL_Channel_Trigger_Add ( LOGT_Channel * " Channel ", char * " Kunf_Name " );" +.LP +.SH DESCRIPTION +.LP +La bibliotheque LIBTOOL fournit un ensemble d'utilitaires lies a la librairie LIBLOG : +.LP +.RS 3 +- Creation de tables de routage et de triggers a partir de fichiers de configuration KUNF +.LP +- Mise a jour des caches de donnees de la librairie LIBLOG (cache des modules, cache des formats d'evenement, table de routage par defaut +.RS -3 +.LP +.SH FONCTIONS +.LP +.BI "TLT_Status TL_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 "TLT_Status TL_LIBLOG_Load ( TL_Cache " To_Load " );" +.LP +.RS 3 +Cette fonction permet de charger les caches de donnees de la base de la librairie LIBLOG +.LP +L'argument +.I To_Load +represente la liste des caches de donnees a charger +, sous forme d'une combinaison binaire des trois valeurs suivantes : +.LP +.RS 3 +- +.B TLD_KMOD +: pour charger le cache de modules +.LP +- +.B TLD_KFORMAT +: pour charger le cache de formats d'evenement +.LP +- +.B TLD_GDRT +: pour charger la table de routage par defaut +.LP +.RS -3 +NB : les caches doivent etre prealablement vides avant d'etre charges. +.LP +.RS -3 +.BI "TLT_Status TL_LIBLOG_Unload ( TL_Cache " To_Unload " );" +.LP +.RS 3 +Cette fonction permet de vider les caches de donnees de la base de la librairie LIBLOG +.LP +L'argument +.I To_Unload +represente la liste des caches de donnees a vider +, sous forme d'une combinaison binaire des trois valeurs suivantes : +.RS 3 +.LP +- +.B TLD_KMOD +: pour vider le cache de modules +.LP +- +.B TLD_KFORMAT +: pour vider le cache de formats d'evenement +.LP +- +.B TLD_GDRT +: pour vider la table de routage par defaut +.RS -3 +.LP +.RS -3 +.BI "TLT_Status TL_Channel_RTab_Add ( LOGT_Channel * " Channel ", char * " Kunf_Name " );" +.LP +.RS 3 +Cette fonction permet d'ajouter toutes les tables de routage d'une section KUNF a un channel. +.LP +Elle attend les parametres suivants : +.LP +.RS 3 +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I Kunf_Name +: le nom de la section KUNF +.RS -3 +.LP +.RS -3 +.BI "TLT_Status TL_Channel_Trigger_Add ( LOGT_Channel * " Channel ", char * " Kunf_Name " );" +.LP +.RS 3 +Cette fonction permet d'ajouter tous les triggers d'une section KUNF a un channel. +.LP +Elle attend les parametres suivants : +.RS 3 +.LP +* (In) +.I Channel +: un pointeur sur le channel +.LP +* (In) +.I Kunf_Name +: le nom de la section KUNF +.RS -3 +.LP +.SH FICHIER DE CONFIGURATION +.LP +Le fichier KUNF contient deux types de sections: +.RS 3 +.LP +- +.B [ROOTING_TABLE] +: liste des tables de routage +.LP +- +.B [TRIGGER] +: liste des triggers +.RS -3 +.LP +Chaque table de routage est identifiee par une sous-section de la forme +.B [ROOTING_TABLE:] +. +.LP +Les regles de routage sont designees par une section de la forme +.B [ROOTING_TABLE::] +. +.LP +Une regle de routage definit les proprietes suivantes : +.RS 3 +.LP +* +.B class +: ce tag definit la classe de la regle et peut prendre les valeurs suivantes : +.LP +.RS 3 +- +.B ALL +pour selectionner tous les evenements +.LP +- +.B GRV +pour selectionner les evenements selon leur gravite +.LP +- +.B RC +pour selectionner les evenements selon leur code retour associe +.LP +- +.B TYPE +pour selectionner les evenements selon leur type +.RS -3 +.LP +* +.B rule +: ce tag definit la regle elle-meme et peut prendre les valeurs suivantes : +.LP +.RS 3 +- pour la classe +.B ALL +: aucune valeur a definir +.LP +- pour la classe +.B GRV +: +.B INFO +, +.B TRACE +, +.B FONCT +, +.B DETAIL +, +.B STAT +, +.B ERR +, +.B REJDON +, +.B REJENR +, +.B WARNING +, +.B RECYCLE +, +.B EXIT +, +.B ABEND +.LP +- pour la classe +.B RC +: +.B OK +, +.B ANOERR +, +.B REJDON +, +.B REJENR +, +.B WARNING +, +.B RECYCLE +, +.B EXIT +, +.B ABEND +.LP +- pour la classe +.B TYPE +: expression reguliere sur le type d'evenement +.LP +.I Attention +: le caractere ':' etant interdit dans les sections kunf, on le notera conventionnellement par "{2pts}". +.LP +Les expressions regulieres seront notees selon le standard UNIX (voir regexp). +.LP +.RS -3 +* +.B rooting +: ce tag definit le routage associe a la regle et peut prendre les valeurs suivantes : +.LP +.RS 3 +- +.B DATABASE +: routage de l'evenement vers la base de suivi +.LP +- +.B STDERR +: routage de l'evenement vers la sortie standard d'erreur +.LP +- +.B NULL +: routage de l'evenement vers /dev/null (i.e l'evenement n'est pas traite) +.LP +- +.B DEFAULT +: routage par defaut +.LP +- +.B PREVIOUS +: routage de la table precedente du channel +.RS -3 +.LP +.RS -3 +Chaque trigger est identifie par une section de la forme +.B [ROOTING_TABLE:] +. +.LP +A un trigger sont associees plusieurs proprietes : +.RS 3 +.LP +* +.B event +: ce tag designe le type d'evenement declencheur du trigger (expression reguliere) +.LP +* +.B type +: ce tag definit le type du trigger et peut prendre les valeurs suivantes : +.RS 3 +.LP +- +.B ADD +pour un trigger qui ajoute une table de routage a un channel +.LP +- +.B REMOVE +pour un trigger qui supprime une table de routage d'un channel +.RS -3 +.LP +* +.B mode +: ce tag designe la persistance du trigger et peut prendre les valeurs suivantes : +.RS 3 +.LP +- +.B ONE_SHOT +pour un trigger qui ne fonctionne qu'une seule fois +.LP +- +.B PERMANENT +pour un trigger qui fonctionne tant qu'il n'est pas desactive +.RS -3 +.LP +* +.B rooting_table +: ce tag definit le nom de la table de routage concernee par le trigger +.RS -3 +.LP +.LP +.I Exemple +: +.LP +.RS 3 +[ROOTING_TABLE] +.LP +[ROOTING_TABLE:TOTO] +.LP +[ROOTING_TABLE:TOTO:RULE1] +.LP +class=ALL +.LP +rooting=DATABASE +.LP +[ROOTING_TABLE:TOTO:RULE2] +.LP +class=RC +.LP +rule=REJENR +.LP +rooting=STDERR+DATABASE +.LP +[ROOTING_TABLE:TOTO:RULE3] +.LP +class=TYPE +.LP +rule=COMPTEUR.* +.LP +rooting=NULL +.LP +[ROOTING_TABLE:TITI] +.LP +[ROOTING_TABLE:TOTO:RULE1] +.LP +class=ALL +.LP +rooting=PREVIOUS +.LP +[ROOTING_TABLE:TOTO:RULE2] +.LP +class=GRV +.LP +rule=WARNING +.LP +rooting=DEFAULT +.LP +[ROOTING_TABLE:TOTO:RULE3] +.LP +class=RC +.LP +rule=ABEND +.LP +rooting=STDERR +.LP +[ROOTING_TABLE:TOTO:RULE4] +.LP +class=TYPE +.LP +rule=*SQLERR* +.LP +rooting=STDERR +.LP +[TRIGGER] +.LP +[TRIGGER:TATA] +.LP +event=COMPTEUR.*@.*{2pts}.*{2pts}TB.* +.LP +type=ADD +.LP +rooting_table=TOTO +.LP +mode=ONE_SHOT +.LP +.RS -3 +Dans l'exemple ci-dessus, le fichier de configuration definit deux tables de routage nommees TOTO (3 regles) et TITI (4 regles) et un trigger nomme TATA. +.LP +.I NB +: les noms des regles de routage sont libres. Ils doivent seulement etre differents les uns des autres pour une meme table de routage. +.LP +Pour davantage de precisions sur la notion de table de routage ou de trigger, le lecteur se referera a la documentation de la librairie LIBLOG. +.LP +.RS -3 +.SH CODES RETOUR +.LP +Toutes les fonctions constituant l'API de la librairie LIBTOOL retournent un code de type +.B TLT_Status +: +.LP +.RS 3 +- +.B TLS_OK +si la fonction s'est correctement executee +.LP +- +.B TLS_KO +si une erreur s'est produite +.RS -3 +.LP +En cas d'erreur, la variable +.B TL_Error_Msg +contient un message du type : +.LP +.RS 3 +Error : +.RS -3 +.LP +Dans une prochaine version, la librairie proposera des codes retour plus explicites, permettant de distinguer les differents types d'erreur. +.LP +.SH VOIR AUSSI +.B liblog +(3) diff --git a/lib/libtool.doc b/lib/libtool.doc new file mode 100644 index 0000000..20c6108 Binary files /dev/null and b/lib/libtool.doc differ diff --git a/lib/libtool.h b/lib/libtool.h new file mode 100644 index 0000000..c36daa2 --- /dev/null +++ b/lib/libtool.h @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +extern char * strdup (const char *); + +FILE * TL_stderr = NULL; + +char TL_Info_Msg[256]; + +/* Déclarations pour ORACLE */ + +void pipo(void); +void pipo(void) +{ + unsigned int x; + x = sqlstm.sqlvsn; +} + +#define sqlstm _sqlstm + +extern void sqlglm(char *, size_t *, size_t *); + +#define SQL_OK 0 +#define SQL_NO_DATA_FOUND 1403 +#define SQL_FETCHED_COLUMN_NULL -1405 + +char * oracx = NULL; + +void TL_Info_Print (void); +void TL_Error_Print (void); +TLT_Status TL_RTab_Add (LOGT_Channel *, char *); +TLT_Status TL_Trigger_Add (LOGT_Channel *, char *); +TLT_Status TL_GDRT_Load(void); +TLT_Status TL_KMOD_Load(void); +TLT_Status TL_KFORMAT_Load(void); +TLT_Status TL_GDRT_Unload(void); +TLT_Status TL_KMOD_Unload(void); +TLT_Status TL_KFORMAT_Unload(void); +TLT_Status TL_Param_Get (void); +TLT_Status TL_Database_Connect (void); +char * Oracle_Message_Get (void); +char * trim (char *); + diff --git a/lib/libtool.pc b/lib/libtool.pc new file mode 100644 index 0000000..583f83c --- /dev/null +++ b/lib/libtool.pc @@ -0,0 +1,1369 @@ +/* + Utilisation des API de la LIBDATASTR en mode optimisé : + - pas de vérif systématique des arguments + - pas de verrouillage systématique des data structures +*/ + +#define DS_MODE 2 + +/* Utilisation des API de la LIBLOG en mode optimisé */ + +#define LOG_MODE 1 + +#include + +VER_INFO_EXPORT (libtool, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") + +EXEC SQL INCLUDE SQLCA; +EXEC SQL INCLUDE ORACA; +EXEC ORACLE OPTION (ORACA=YES); + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Library_Stderr_Set ( FILE * Out ) +{ + TL_stderr = Out; + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Chargement des caches de la librairie LIBLOG */ +/*------------------------------------------------------------------------------*/ +/* (I) ToLoad : liste des caches de données à charger */ +/* (combinaison de TLD_KMOD, TLD_KFORMAT et TLD_GDRT) */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_LIBLOG_Load ( TLT_Cache ToLoad ) +{ + int Locked; + + if (!LOG_Base) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : the LIBLOG library is not open"); + TL_Error_Print (); + return TLS_KO; + } + + if (TL_Param_Get () != TLS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to retrieve parameters from KUNF"); + TL_Error_Print (); + return TLS_KO; + } + + /* Connexion à la base de données du suivi */ + + if (TL_Database_Connect () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to connect to database"); + TL_Error_Print (); + return TLS_KO; + } + + if (ToLoad & TLD_KMOD) + { + /* Verrouillage du cache des modules */ + + if (DS_DataStruct_Lock (LOG_Base->KMOD, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to lock the KMOD data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion du cache des modules en liste FIFO pour faciliter les insertions */ + + if (DS_DataStruct_Convert (LOG_Base->KMOD, NDD_DS_LIST|NDD_MN_FIFO) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the KMOD data structure to a FIFO list"); + TL_Error_Print (); + return TLS_KO; + } + + /* Chargement du cache des modules */ + + if (TL_KMOD_Load () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to load KMOD data structure from database"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion du cache des modules en arbre auto-équilibré pour faciliter les recherches */ + + if (DS_DataStruct_Convert (LOG_Base->KMOD, NDD_DS_TREE|NDD_MN_AUTO_EQU) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the KMOD data structure to a tree"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déverrouillage du cache des modules */ + + if (DS_DataStruct_Unlock (LOG_Base->KMOD) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to unlock the KMODdata structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + if (ToLoad & TLD_KFORMAT) + { + /* Verrouillage du cache des formats d'événement */ + + if (DS_DataStruct_Lock (LOG_Base->KFORMAT, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to lock the KFORMAT data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion du cache des formats d'événement en liste FIFO pour faciliter les insertions */ + + if (DS_DataStruct_Convert (LOG_Base->KFORMAT, NDD_DS_LIST|NDD_MN_FIFO) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the KFORMAT data structure to a FIFO list"); + TL_Error_Print (); + return TLS_KO; + } + + /* Chargement du cache des formats d'événement */ + + if (TL_KFORMAT_Load () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to load KFORMAT data structure from database"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion du cache des formats d'événement en arbre auto-équilibré pour faciliter les recherches */ + + if (DS_DataStruct_Convert (LOG_Base->KFORMAT, NDD_DS_TREE|NDD_MN_AUTO_EQU) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the KFORMAT data structure to a tree"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déverrouillage du cache des formats d'événement */ + + if (DS_DataStruct_Unlock (LOG_Base->KFORMAT) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to unlock the KFORMAT data structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + if (ToLoad & TLD_GDRT) + { + /* Verrouillage de la table de routage GDRT en écriture */ + + if (DS_DataStruct_Lock (LOG_Base->GDRT->Root, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to lock the GDRT data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion de la table de routage GDRT en liste FIFO pour faciliter les insertions */ + + if (DS_DataStruct_Convert (LOG_Base->GDRT->Root, NDD_DS_LIST|NDD_MN_FIFO) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the GDRT data structure to a FIFO list"); + TL_Error_Print (); + return TLS_KO; + } + + /* Chargement de la table de routage GDRT */ + + if (TL_GDRT_Load () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to load the GDRT data structure from database"); + TL_Error_Print (); + return TLS_KO; + } + + /* Conversion de la table de routage GDRT en arbre auto-équilibré pour faciliter les recherches */ + + if (DS_DataStruct_Convert (LOG_Base->GDRT->Root, NDD_DS_TREE|NDD_MN_AUTO_EQU) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to convert the GDRT data structure to a tree"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déverrouillage de la table de routage GDRT */ + + if (DS_DataStruct_Unlock (LOG_Base->GDRT->Root) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Load : unable to unlock the GDRT data structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Déchargement des caches de la librairie LIBLOG */ +/*------------------------------------------------------------------------------*/ +/* (I) ToUnload : liste des caches de données à décharger */ +/* (combinaison de TLD_KMOD, TLD_KFORMAT et TLD_GDRT) */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_LIBLOG_Unload (TLT_Cache ToUnload) +{ + SMT_Heap * Heap; + size_t Size; + int Locked; + + if (!LOG_Base) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : the LIBLOG library is not open"); + TL_Error_Print (); + return TLS_KO; + } + + if (ToUnload & TLD_KMOD) + { + /* Verrouillage du cache des modules */ + + if (DS_DataStruct_Lock (LOG_Base->KMOD, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to lock the KMOD data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déchargement du cache des modules */ + + if (TL_KMOD_Unload () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unload KMOD data structure"); + TL_Error_Print (); + return TLS_KO; + } + + /* Compression du heap sous-jacent */ + + if (SM_Heap_IsOpen (( (DST_RootDesc *)(LOG_Base->KMOD->User))->Heap_Name, &Heap) == SMS_OK) + SM_Heap_Compress (Heap, &Size); + + /* Déverrouillage du cache des modules */ + + if (DS_DataStruct_Unlock (LOG_Base->KMOD) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unlock the KMOD data structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + if (ToUnload & TLD_KFORMAT) + { + /* Verrouillage du cache des formats d'événement en écriture */ + + if (DS_DataStruct_Lock (LOG_Base->KFORMAT, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to lock the KFORMAT data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déchargement du cache des formats d'événement */ + + if (TL_KFORMAT_Unload () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unload KFORMAT data structure"); + TL_Error_Print (); + return TLS_KO; + } + + /* Compression du heap sous-jacent */ + + if (SM_Heap_IsOpen (( (DST_RootDesc *)(LOG_Base->KFORMAT->User))->Heap_Name, &Heap) == SMS_OK) + SM_Heap_Compress (Heap, &Size); + + /* Déverrouillage du cache des formats d'événement */ + + if (DS_DataStruct_Unlock (LOG_Base->KFORMAT) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unlock the KFORMAT data structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + if (ToUnload & TLD_GDRT) + { + /* Verrouillage de la table de routage GDRT en écriture */ + + if (DS_DataStruct_Lock (LOG_Base->GDRT->Root, DSD_WRITE, &Locked) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to lock the GDRT data structure for writing"); + TL_Error_Print (); + return TLS_KO; + } + + /* Déchargement de la table GDRT */ + + if (TL_GDRT_Unload () != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unload GDRT data structure"); + TL_Error_Print (); + return TLS_KO; + } + + /* Compression du heap sous-jacent */ + + if (SM_Heap_IsOpen (( (DST_RootDesc *)(LOG_Base->GDRT->Root->User))->Heap_Name, &Heap) == SMS_OK) + SM_Heap_Compress (Heap, &Size); + + /* Déverrouillage de la table de routage GDRT */ + + if (DS_DataStruct_Unlock (LOG_Base->GDRT->Root) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_LIBLOG_Unload : unable to unlock the GDRT data structure"); + TL_Error_Print (); + return TLS_KO; + } + } + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Affectation de toutes les tables de routage d'une section KUNF à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Name : nom de la section KUNF */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Channel_RTab_Add (LOGT_Channel * My_Channel, const char * Kunf_Name) +{ + KITEM * Item; + + if (!My_Channel) + { + sprintf (TL_Error_Msg, "Error TL_Channel_RTab_Add : the channel is null"); + TL_Error_Print (); + return TLS_KO; + } + + kunfig_open (NULL, KUNFIG_OPEN_SIMPLEACCESS|KUNFIG_OPEN_OVERRIDINGENV); + + /* Recherche de la section KUNF passée en paramètre */ + + Item = kunfig_directfindentry (Kunf_Name); + + if (!Item) + { + sprintf (TL_Error_Msg, "Error TL_Channel_RTab_Add : unable to find section \"%s\"", Kunf_Name); + TL_Error_Print (); + + kunfig_close (); + + return TLS_KO; + } + + /* On descend dans l'arborescence de la section pour récupérer la liste des tables de routage */ + + Item = kunfig_down (Item, KUNFIG_LOCAL); + + while (Item) + { + char * Table_Name = kunfig_getname (Item); + char Name [256]; + + sprintf (Name, "%s:%s", Kunf_Name, Table_Name); + + if (TL_RTab_Add (My_Channel, Name) != TLS_OK) + { + sprintf (TL_Error_Msg, "Error TL_Channel_RTab_Add : unable to add rooting table %s to the channel", Table_Name); + TL_Error_Print (); + + kunfig_close (); + + return TLS_KO; + } + + Item = kunfig_next (Item, KUNFIG_LOCAL); + } + + kunfig_close (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Affectation de tous les triggers d'une section KUNF à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Name : nom de la section KUNF */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Channel_Trigger_Add (LOGT_Channel * My_Channel, const char * Kunf_Name) +{ + KITEM * Item; + + if (!My_Channel) + { + sprintf (TL_Error_Msg, "Error TL_Channel_Trigger_Add : the channel is null"); + TL_Error_Print (); + return TLS_KO; + } + + kunfig_open (NULL, KUNFIG_OPEN_SIMPLEACCESS|KUNFIG_OPEN_OVERRIDINGENV); + + /* Recherche de la section KUNF passée en paramètre */ + + Item = kunfig_directfindentry (Kunf_Name); + + if (!Item) + { + sprintf (TL_Error_Msg, "Error TL_Channel_Trigger_Add : unable to find section \"%s\"", Kunf_Name); + TL_Error_Print (); + + kunfig_close (); + + return TLS_KO; + } + + /* On descend dans l'arborescence de la section pour récupérer la liste des triggers */ + + Item = kunfig_down (Item, KUNFIG_LOCAL); + + while (Item) + { + char * Trigger_Name = kunfig_getname (Item); + char Name [256]; + + sprintf (Name, "%s:%s", Kunf_Name, Trigger_Name); + + if (TL_Trigger_Add (My_Channel, Name) != TLS_OK) + { + sprintf (TL_Error_Msg, "Error TL_Channel_Trigger_Add : unable to add trigger %s to the channel", Trigger_Name); + TL_Error_Print (); + + kunfig_close (); + + return TLS_KO; + } + + Item = kunfig_next (Item, KUNFIG_LOCAL); + } + + kunfig_close (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ +/* Fonctions privées */ +/*------------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* Chargement du cache des modules */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_KMOD_Load ( void ) +{ + int Id_Module; + char Cd_Module [81]; + + int Nb_Modules = 0; + + /* Récupération des modules */ + + EXEC SQL DECLARE cursor_module CURSOR FOR SELECT ID_MODULE, CD_MODULE FROM TB_MODULE WHERE DAT_FIN_EFFET IS NOT NULL; + + EXEC SQL OPEN cursor_module; + + if (sqlca.sqlcode != SQL_OK) + { + sprintf (TL_Error_Msg, "Error TL_KMOD_Load : unable to open cursor to retrieve modules from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_module; + return TLS_KO; + } + + EXEC SQL FETCH cursor_module INTO :Id_Module, :Cd_Module; + + while (sqlca.sqlcode == SQL_OK || sqlca.sqlcode == SQL_FETCHED_COLUMN_NULL) + { + void * Value; + + if (DS_Value_Alloc (LOG_Base->KMOD, &Value, trim (Cd_Module), Id_Module) != NDS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KMOD_Load : unable to create a module for the KMOD data structure"); + TL_Error_Print (); + return TLS_KO; + } + + if (DS_Value_Add (LOG_Base->KMOD, Value) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KMOD_Load : unable to add a module to the KMOD data structure"); + TL_Error_Print (); + EXEC SQL CLOSE cursor_module; + return TLS_KO; + } + + Nb_Modules++; + + EXEC SQL FETCH cursor_module INTO :Id_Module, :Cd_Module; + } + + if (sqlca.sqlcode != SQL_NO_DATA_FOUND) + { + sprintf (TL_Error_Msg, "Error TL_KMOD_Load : unable to fetch cursor to retrieve modules from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_module; + return TLS_KO; + } + + EXEC SQL CLOSE cursor_module; + + sprintf (TL_Info_Msg, "TL_KMOD_Load : %d module(s) loaded in the KMOD data structure", Nb_Modules); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Déchargement du cache des modules */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_KMOD_Unload ( void ) +{ + if (DS_DataStruct_Traverse (LOG_Base->KMOD, NDD_CMD_DELETE_VALUE, NULL) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KMOD_Unload : unable to delete all values from the KMOD data structure"); + TL_Error_Print (); + return TLS_KO; + } + + sprintf (TL_Info_Msg, "The KMOD data structure has been successfully unloaded"); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Chargement du cache des formats d'événement */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_KFORMAT_Load ( void ) +{ + char Data [81]; + unsigned int Event_Type; + LOGT_Event_Format * Format; + NDT_Node * Node; + char * Format_Data; + int Nb_Event_Format = 0; + int Nb_Event_Data = 0; + + /* Récupération des formats d'événement */ + + EXEC SQL DECLARE cursor_format CURSOR FOR + SELECT TB_TYPE_EVEN.CD_TYPE_EVEN, TB_DONNEE.CD_DONNEE + FROM TB_TYPE_EVEN, TA_DONNEE_FORMAT, TB_DONNEE + WHERE TB_TYPE_EVEN.ID_FORMAT = TA_DONNEE_FORMAT.ID_FORMAT + AND TA_DONNEE_FORMAT.DAT_EFFET_FORMAT <= SYSDATE + AND TA_DONNEE_FORMAT.DAT_EFFET <= SYSDATE + AND TB_DONNEE.CD_DONNEE = TA_DONNEE_FORMAT.CD_DONNEE + AND TB_DONNEE.DAT_EFFET = TA_DONNEE_FORMAT.DAT_EFFET_DONNEE; + + EXEC SQL OPEN cursor_format; + + if (sqlca.sqlcode != SQL_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to open cursor to retrieve event formats from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + EXEC SQL FETCH cursor_format INTO :Event_Type, :Data; + + while (sqlca.sqlcode == SQL_OK || sqlca.sqlcode == SQL_FETCHED_COLUMN_NULL) + { + LOGT_Event_Format Tmp_Event_Format; + + Tmp_Event_Format.Event_Type = Event_Type; + + if (ND_Node_Find (LOG_Base->KFORMAT, &Node, (void *)(&Tmp_Event_Format), NULL) != NDS_OK) + { + /* Création du format de l'événement */ + + if (DS_Value_Alloc (LOG_Base->KFORMAT, (void **)&Format, Event_Type) != NDS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to create a value for the KFORMAT data structure"); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + if (DS_Value_Add (LOG_Base->KFORMAT, (void *)Format) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to add an event format to the KFORMAT data structure"); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + Nb_Event_Format++; + } + else + Format = (LOGT_Event_Format *)(Node->Value); + + /* Création de la donnée du format */ + + if (DS_Value_Alloc (Format->Data_List, (void **)&Format_Data, trim (Data)) != NDS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to create a data for the event format data list"); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + if (DS_Value_Add (Format->Data_List, (void *)Format_Data) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to add a data to the event format data list"); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + Nb_Event_Data++; + + EXEC SQL FETCH cursor_format INTO :Event_Type, :Data; + } + + if (sqlca.sqlcode != SQL_NO_DATA_FOUND) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Load : unable to fetch cursor to retrieve formats from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_format; + return TLS_KO; + } + + EXEC SQL CLOSE cursor_format; + + sprintf (TL_Info_Msg, "TL_KFORMAT_Load : %d format(s) and %d data(s) loaded in the KFORMAT data structure", Nb_Event_Format, Nb_Event_Data); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Déchargement du cache des formats d'événement */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_KFORMAT_Unload ( void ) +{ + if (DS_DataStruct_Traverse (LOG_Base->KFORMAT, NDD_CMD_DELETE_VALUE, NULL) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_KFORMAT_Unload : unable to delete all values from the KFORMAT data structure"); + TL_Error_Print (); + return TLS_KO; + } + + sprintf (TL_Info_Msg, "The KFORMAT data structure has been successfully unloaded"); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Chargement de la table de routage par défaut (GDRT) */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_GDRT_Load ( void ) +{ + int cd_type_even; + int cd_retour; + char cd_gravite [2]; + int rooting; + char nom_type_even [81]; + int Nb_Event = 0; + int Nb_Tree = 0; + + /* Sélection des types d'événement correspondant à la règle */ + + EXEC SQL DECLARE cursor_evt CURSOR FOR + SELECT CD_TYPE_EVEN, NOM_TYPE_EVEN, TB_TYPE_EVEN.CD_GRAVITE, CD_RETOUR, NIV_SORTIE FROM TB_TYPE_EVEN, TB_GRAVITE WHERE TB_TYPE_EVEN.CD_GRAVITE = TB_GRAVITE.CD_GRAVITE; + + EXEC SQL OPEN cursor_evt; + + if (sqlca.sqlcode != SQL_OK) + { + sprintf (TL_Error_Msg, "Error TL_GDRT_Load : unable to open cursor to retrieve event types from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_evt; + return TLS_KO; + } + + EXEC SQL FETCH cursor_evt INTO :cd_type_even, :nom_type_even, :cd_gravite, :cd_retour, :rooting; + + while (sqlca.sqlcode == SQL_OK || sqlca.sqlcode == SQL_FETCHED_COLUMN_NULL) + { + if (ND_Manager_Exec (LOG_Base->GDRT->Root->Manager, NDD_CMD_MAKE_VALUE, trim (nom_type_even), cd_type_even, (LOGT_Gravite)cd_gravite [0], (LOGT_RC)cd_retour, (LOGT_Rooting)rooting, &Nb_Tree) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_GDRT_Load : unable to add event \"%s\" to the GDRT data structure", trim (nom_type_even)); + TL_Error_Print (); + EXEC SQL CLOSE cursor_evt; + return TLS_KO; + } + + Nb_Event++; + + EXEC SQL FETCH cursor_evt INTO :cd_type_even, :nom_type_even, :cd_gravite, :cd_retour, :rooting; + } + + if (sqlca.sqlcode != SQL_NO_DATA_FOUND) + { + sprintf (TL_Error_Msg, "Error TL_GDRT_Load : unable to fetch cursor to retrieve event types from the database (%s)", Oracle_Message_Get ()); + TL_Error_Print (); + EXEC SQL CLOSE cursor_evt; + return TLS_KO; + } + + EXEC SQL CLOSE cursor_evt; + + sprintf (TL_Info_Msg, "TL_GDRT_Load : %d event(s) loaded (%d tree(s) created) in the GDRT data structure", Nb_Event, Nb_Tree); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Déchargement de la table de routage GDRT */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_GDRT_Unload ( void ) +{ + if (DS_DataStruct_Traverse (LOG_Base->GDRT->Root, NDD_CMD_DELETE_VALUE, NULL) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_GDRT_Unload : unable to delete all values from the GDRT data structure"); + TL_Error_Print (); + return TLS_KO; + } + + sprintf (TL_Info_Msg, "The GDRT data structure has been successfully unloaded"); + TL_Info_Print (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Connexion à la base de suivi */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Database_Connect ( void ) +{ + EXEC SQL CONNECT :oracx; + + if (sqlca.sqlcode != SQL_OK) + { + sprintf (TL_Error_Msg, "Error TL_Database_Connect %s", Oracle_Message_Get ()); + TL_Error_Print (); + return TLS_KO; + } + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une table de routage utilisateur à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Name : nom de la section kunf de la table de routage */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_RTab_Add (LOGT_Channel * My_Channel, char * Kunf_Name) +{ + KITEM * Item; + LOGT_RuleClass RuleClass; + LOGT_Rule * Rule; + LOGT_Rooting Rooting; + LOGT_RTab * RTab; + char * ptr; + char RTab_Name [100]; + char sRule [256]; + + /* Recherche de la section relative à la table de routage */ + + Item = kunfig_directfindentry (Kunf_Name); + + if (!Item) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : unable to find section \"%s\"", Kunf_Name); + TL_Error_Print (); + return TLS_KO; + } + + /* Création de la table de routage utilisateur */ + + if ((ptr = strrchr (Kunf_Name, ':')) ) ptr ++; + else ptr = Kunf_Name; + + sprintf (RTab_Name, "%s_%d_%ld_%d", ptr, My_Channel->ModuleId, My_Channel->Pid, My_Channel->Id); + + if (LOG_RTab_Alloc (&RTab, RTab_Name) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : unable to allocate memory for rooting table %s", RTab_Name); + TL_Error_Print (); + + return TLS_KO; + } + + /* On descend dans l'arborescence de la table de routage pour récupérer les règles associées */ + + Item = kunfig_down (Item, KUNFIG_LOCAL); + + while (Item) + { + char Name [256]; + char * Value; + char * Rule_Name = kunfig_getname (Item); + + /* Récupération de la classe de la règle */ + + sprintf (Name, "%s:%s:class", Kunf_Name, Rule_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : class is missing in section \"%s\"", Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + if (!strcmp (Value, "ALL")) + RuleClass = LOGD_SELECT_ALL; + else if (!strcmp (Value, "GRV")) + RuleClass = LOGD_SELECT_GRV; + else if (!strcmp (Value, "RC")) + RuleClass = LOGD_SELECT_RC; + else if (!strcmp (Value, "TYPE")) + RuleClass = LOGD_SELECT_TYPE; + else + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : unknown class \"%s\" in section \"%s\"", Value, Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + /* Récupération de la règle */ + + if (RuleClass != LOGD_SELECT_ALL) + { + sprintf (Name, "%s:%s:rule", Kunf_Name, Rule_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : rule is missing in section \"%s\"", Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + } + + /* Vérifications d'usage sur la règle */ + + if (RuleClass == LOGD_SELECT_GRV) + { + LOGT_Gravite Gravite; + + if (!strcmp (Value, "INFO")) + { + Gravite = LOGD_GRV_INFO; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "TRACE")) + { + Gravite = LOGD_GRV_TRACE; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "FONCT")) + { + Gravite = LOGD_GRV_FONCT; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "DETAIL")) + { + Gravite = LOGD_GRV_DETAIL; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "STAT")) + { + Gravite = LOGD_GRV_STAT; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "ERR")) + { + Gravite = LOGD_GRV_ERR; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "REJDON")) + { + Gravite = LOGD_GRV_REJDON; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "REJENR")) + { + Gravite = LOGD_GRV_REJENR; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "WARNING")) + { + Gravite = LOGD_GRV_WARNING; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "RECYCLE")) + { + Gravite = LOGD_GRV_RECYCLE; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "EXIT")) + { + Gravite = LOGD_GRV_EXIT; + Rule = (LOGT_Rule *)(&Gravite); + } + else if (!strcmp (Value, "ABEND")) + { + Gravite = LOGD_GRV_ABEND; + Rule = (LOGT_Rule *)(&Gravite); + } + else + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : bad rule \"%s\" in section \"%s\"", Value, Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + } + else if (RuleClass == LOGD_SELECT_RC) + { + LOGT_RC RC; + + if (!strcmp (Value, "OK")) + { + RC = LOGD_RC_OK; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "ANOERR")) + { + RC = LOGD_RC_ANOERR; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "REJDON")) + { + RC = LOGD_RC_REJDON; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "REJENR")) + { + RC = LOGD_RC_REJENR; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "WARNING")) + { + RC = LOGD_RC_WARNING; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "RECYCLE")) + { + RC = LOGD_RC_RECYCLE; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "EXIT")) + { + RC = LOGD_RC_EXIT; + Rule = (LOGT_Rule *)(&RC); + } + else if (!strcmp (Value, "ABEND")) + { + RC = LOGD_RC_ABEND; + Rule = (LOGT_Rule *)(&RC); + } + else + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : bad rule \"%s\" in section \"%s\"", Value, Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + } + else if (RuleClass == LOGD_SELECT_TYPE) + { + /* La section kunf ne peut pas comporter le caractère ':' qui a donc été remplacé par "{2pts}" */ + + strcpy (sRule, Value); + + while ((ptr = strstr (sRule, "{2pts}")) ) + { + char Tmp [256]; + + strcpy (Tmp, ptr + 6); + + *ptr = ':'; + ptr++; + *ptr = (char)0; + strcat (sRule, Tmp); + } + + Rule = (LOGT_Rule *)sRule; + } + + /* Récupération du routage de la règle */ + + sprintf (Name, "%s:%s:rooting", Kunf_Name, Rule_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : rooting is missing in section \"%s\"", Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + Rooting = 0; + + if (strstr (Value, "DATABASE")) Rooting += LOGD_ROOTING_DATABASE; + + if (strstr (Value, "NULL")) Rooting += LOGD_ROOTING_NULL; + + if (strstr (Value, "STDERR")) Rooting += LOGD_ROOTING_STDERR; + + if (strstr (Value, "PREVIOUS")) Rooting += LOGD_ROOTING_PREVIOUS; + + if (strstr (Value, "DEFAULT")) Rooting += LOGD_ROOTING_DEFAULT; + + if (Rooting == 0) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : bad rooting \"%s\" in section \"%s\"", Value, Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + /* Mise à jour de la table de routage */ + + if (LOG_RTab_Setup (RTab, RuleClass, Rule, Rooting) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : unable to apply rule %s to the rooting table", Rule_Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + Item = kunfig_next (Item, KUNFIG_LOCAL); + } + + /* Ajout de la table de routage au channel */ + + if (LOG_RTab_Add (My_Channel, RTab) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_RTab_Add : unable to add rooting table %s to the channel", RTab_Name); + TL_Error_Print (); + + LOG_RTab_Free (RTab); + + return TLS_KO; + } + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un trigger à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Name : nom de la section kunf du trigger */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Trigger_Add (LOGT_Channel * My_Channel, char * Kunf_Name) +{ + LOGT_Trigger * Trigger; + LOGT_RTab * RTab; + char Type_Evt [256]; + LOGT_Flags Mode; + LOGT_Flags Type; + LOGT_RTab Tmp_RTab; + NDT_Node * Node; + char Name [256]; + char * Value; + + /* Récupération du type d'événement déclencheur du trigger (expression régulière) */ + + sprintf (Name, "%s:event", Kunf_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : missing trigger event type in section \"%s\"", Kunf_Name); + TL_Error_Print (); + + return TLS_KO; + } + else + { + char * ptr; + + /* La section kunf ne peut pas comporter le caractère ':' qui a donc été remplacé par "{2pts}" */ + + strcpy (Type_Evt, Value); + + while ((ptr = strstr (Type_Evt, "{2pts}")) ) + { + char Tmp [256]; + + strcpy (Tmp, ptr + 6); + + *ptr = ':'; + ptr++; + *ptr = (char)0; + strcat (Type_Evt, Tmp); + } + } + + /* Récupération du type du trigger */ + + sprintf (Name, "%s:type", Kunf_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : missing trigger type in section \"%s\"", Kunf_Name); + TL_Error_Print (); + + return TLS_KO; + } + + /* Vérifications d'usage sur le type */ + + if (!strcmp (Value, "ADD")) + Type = LOGD_ADD; + else if (!strcmp (Value, "REMOVE")) + Type = LOGD_REMOVE; + else + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : bad trigger type \"%s\" in section \"%s\"", Value, Kunf_Name); + TL_Error_Print (); + + return TLS_KO; + } + + /* Récupération du mode de fonctionnement du trigger */ + + sprintf (Name, "%s:mode", Kunf_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : missing trigger mode in section \"%s\"", Kunf_Name); + TL_Error_Print (); + + return TLS_KO; + } + + /* Vérifications d'usage sur le mode */ + + if (!strcmp (Value, "ONE_SHOT")) + Mode = LOGD_ONE_SHOT; + else if (!strcmp (Value, "PERMANENT")) + Mode = LOGD_PERMANENT; + else + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : bad trigger mode \"%s\" in section \"%s\"", Value, Kunf_Name); + TL_Error_Print (); + + return TLS_KO; + } + + /* Récupération de la table de routage concernée */ + + sprintf (Name, "%s:rooting_table", Kunf_Name); + Value = kunfig_directfindvalue (KUNFIG_LOCAL, Name); + + if (!Value) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : missing trigger rooting table in section \"%s\"", Kunf_Name); + TL_Error_Print (); + } + + sprintf (Name, "%s_%d_%ld_%d", Value, My_Channel->ModuleId, My_Channel->Pid, My_Channel->Id); + Tmp_RTab.Name = Name; + + /* Recherche de la table de routage dans la liste de la base */ + + if (DS_Node_Find (LOG_Base->URT_List, &Node, (void *)(&Tmp_RTab), NULL) != DSS_OK) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : rooting table \"%s\" is undefined", Value); + TL_Error_Print (); + + return TLS_KO; + } + + RTab = (LOGT_RTab *)(Node->Value); + + /* Création du trigger */ + + if (LOG_Trigger_Add (&Trigger, My_Channel, RTab, Type_Evt, Type | Mode) != LOGS_OK) + { + sprintf (TL_Error_Msg, "Error TL_Trigger_Add : unable to create trigger %s", Kunf_Name); + TL_Error_Print (); + return TLS_KO; + } + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Routine d'affichage d'un message d'erreur */ +/*------------------------------------------------------------------------------*/ +void TL_Error_Print ( void ) +{ + if (TL_stderr) fprintf (TL_stderr, "%s\n", TL_Error_Msg); +} + +/*------------------------------------------------------------------------------*/ +/* Routine d'affichage d'un message d'information */ +/*------------------------------------------------------------------------------*/ +void TL_Info_Print ( void ) +{ + fprintf (stdout, "%s\n", TL_Info_Msg); +} + +/*------------------------------------------------------------------------------*/ +/* Récupération des paramétres */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Param_Get ( void ) +{ + char * Login, * Pwd, * Sid, * Kunf_Name, * Env; + char Name [256]; + + if (kunfig_open (NULL, KUNFIG_OPEN_SIMPLEACCESS|KUNFIG_OPEN_OVERRIDINGENV) != KUNFIG_ERROR_NONE) + { + sprintf (TL_Error_Msg, "Error TL_Param_Get : unable to open kunfig file"); + TL_Error_Print (); + return TLS_KO; + } + + if ((Env = getenv ("BDM_PROFILE")) ) + { + Kunf_Name = (char * )malloc ( strlen ("ADMIN:INSTALL_SUIVI") + strlen (Env) + 2); + sprintf (Kunf_Name, "ADMIN:INSTALL_SUIVI:%s", Env); + } + else + Kunf_Name = strdup ("ADMIN:INSTALL_SUIVI"); + + /* Récupération des paramètres de connexion à la base de suivi */ + + sprintf (Name, "%s:login", Kunf_Name); + if ((Login = kunfig_directfindvalue (KUNFIG_INHERIT, Name)) == NULL) + { + sprintf (TL_Error_Msg, "Error TL_Param_Get : unable to find %s in KUNF", Name); + TL_Error_Print (); + free (Kunf_Name); + return TLS_KO; + } + + sprintf (Name, "%s:password", Kunf_Name); + if ((Pwd = kunfig_directfindvalue (KUNFIG_INHERIT, Name)) == NULL) + { + sprintf (TL_Error_Msg, "Error TL_Param_Get : unable to find %s in KUNF", Name); + TL_Error_Print (); + free (Kunf_Name); + return TLS_KO; + } + + if (oracx) free (oracx); + + sprintf (Name, "%s:instance", Kunf_Name); + if ((Sid = kunfig_directfindvalue (KUNFIG_INHERIT, Name)) ) + { + oracx = (char * )malloc (strlen (Login) + strlen (Pwd) + strlen (Sid) + 3); + sprintf (oracx, "%s/%s@%s", Login, Pwd, Sid); + } + else + { + oracx = (char * )malloc (strlen (Login) + strlen (Pwd) + 2); + sprintf (oracx, "%s/%s", Login, Pwd); + } + + free (Kunf_Name); + + kunfig_close (); + + return TLS_OK; +} + +/*------------------------------------------------------------------------------*/ +/* Suppression des espaces en début et fin de chaîne des caractères */ +/*------------------------------------------------------------------------------*/ +char * trim (char * str) +{ + char * ptr1, * ptr2; + + ptr1 = ptr2 = str; + + while (*ptr1 == ' ') ptr1++; + + if (ptr1 != str) + { + while (*ptr1 != '\0') + { + *ptr2 = *ptr1; + ptr2++; + ptr1++; + } + + *ptr2 = *ptr1; + } + else + { + while (*ptr1 != '\0') ptr1++; + ptr2 = ptr1; + } + + if (ptr2 > str) + { + ptr2--; + while (*ptr2 == ' ') ptr2--; + ptr2++; + *ptr2 = '\0'; + } + + return (str); +} + +/*------------------------------------------------------------------------------*/ +/* Récupération du message Oracle */ +/*------------------------------------------------------------------------------*/ +char * Oracle_Message_Get ( void ) +{ + size_t buf_len, oracle_text_len; + static char oracle_text [200]; + + buf_len = sizeof (oracle_text); + sqlglm (oracle_text, &buf_len, &oracle_text_len); + + trim (oracle_text); + + return oracle_text; +} diff --git a/lib/log.h b/lib/log.h new file mode 100644 index 0000000..902b269 --- /dev/null +++ b/lib/log.h @@ -0,0 +1,516 @@ +#ifndef _LIBLOG +#define _LIBLOG + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +/*********** Anciennes librairies ************** +#include +#include +************************************************/ + +/* Codes retour des fonctions de l'API */ + +typedef int LOGT_Status; + +#define LOGS_OK DSS_OK /* La fonction s'est correctement exécutée et a produit un résultat */ +#define LOGS_KO DSS_KO /* La fonction s'est correctement exécutée mais n'a pas produit de résultat */ + +#define LOGS_ERRMEM MSGS_ERRMEM /* Problème d'allocation mémoire */ +#define LOGS_ERRAPI MSGS_ERRAPI /* Utilisation incorrecte des API */ +#define LOGS_ERRSHM MSGS_ERRSHM /* Problème relatif aux segments de mémoire partagée */ +#define LOGS_ERRSEM MSGS_ERRSEM /* Problème relatif à l'utilisation des sémaphores */ +#define LOGS_ERRSIG MSGS_ERRSIG /* Opération sur sémpahore interrompue par un signal système */ +#define LOGS_ERRDLL MSGS_ERRDLL /* Problème de chargement dynamique de librairie */ + +#define LOG_ERROR(s) (s < 0) /* Tous les codes retour négatifs correspondent à des erreurs */ + +/* Notion de routage (possibilité de les combiner par addition binaire) */ + +typedef int LOGT_Rooting; + +#define LOGD_ROOTING_DATABASE 0x01 /* Routage vers la base de suivi */ +#define LOGD_ROOTING_STDERR 0x02 /* Routage vers la sortie standard d'erreur */ +#define LOGD_ROOTING_DEFAULT 0x04 /* Routage de la table de routage par défaut */ +#define LOGD_ROOTING_PREVIOUS 0x08 /* Routage de la table de routage précédente */ +#define LOGD_ROOTING_NULL 0x10 /* Routage vers /dev/null */ + +#define LOGD_ROOTING_DATABASE_MSK(a) (LOGD_ROOTING_DATABASE & a) +#define LOGD_ROOTING_STDERR_MSK(a) (LOGD_ROOTING_STDERR & a) + +/* Notion de gravité (classe d'événement) */ + +typedef int LOGT_Gravite; + +#define LOGD_GRV_INFO 'I' +#define LOGD_GRV_TRACE 'T' +#define LOGD_GRV_FONCT 'F' +#define LOGD_GRV_DETAIL 'L' +#define LOGD_GRV_STAT 'S' +#define LOGD_GRV_ERR 'E' +#define LOGD_GRV_REJDON 'D' +#define LOGD_GRV_REJENR 'R' +#define LOGD_GRV_WARNING 'W' +#define LOGD_GRV_RECYCLE 'Y' +#define LOGD_GRV_EXIT 'X' +#define LOGD_GRV_ABEND 'A' + +/* Notion de code retour (pour le pilotage) */ + +typedef int LOGT_RC; + +#define LOGD_RC_OK 0 /* Continuation */ +#define LOGD_RC_ANOERR 4 /* Anomalie */ +#define LOGD_RC_REJDON 6 /* Rejet de la donnée */ +#define LOGD_RC_REJENR 7 /* Rejet de l'enregistrement */ +#define LOGD_RC_WARNING 8 /* Evénement inconnu */ +#define LOGD_RC_RECYCLE 10 /* Recyclage de l'enregistrement */ +#define LOGD_RC_EXIT 14 /* Sortie du traitement */ +#define LOGD_RC_ABEND 16 /* Interruption du traitement */ + +#define LOGD_RC_SIZE 17 /* Taille des tableaux de codes retour (voir fonction LOG_Event_Cpt_Get) */ + +/* Type de table de routage */ + +typedef int LOGT_RTType; + +#define LOGD_GMRT 0 /* Global Master Rooting Table */ +#define LOGD_LMRT 1 /* Local Master Rooting Table */ +#define LOGD_URT 2 /* User Rooting Table */ +#define LOGD_LDRT 3 /* Local Default Rooting Table */ +#define LOGD_GDRT 4 /* Global Default Rooting Table */ + +/* Notion de table de routage */ + +typedef struct { + char * Name; /* Nom de la table de routage */ + LOGT_RTType Type; /* Type de la table de routage */ + NDT_Root * Root; /* Pointeur sur la structure contenant les événements */ + int Nb_Channel; /* Nombre de canaux auquels est rattachée la table */ + pid_t Pid; /* Processus propriétaire de la table de routage (utile au garbage collector) */ +} LOGT_RTab; + + +#define LOGD_RTAB_DEFAULT 0 /* Référence à la table de routage par défaut */ +#define LOGD_RTAB_PREVIOUS 1 /* Référence à la table de routage précédente */ + +/* Notion de classe de règle de sélection des événements */ + +typedef int LOGT_RuleClass; + +#define LOGD_SELECT_ALL 1 /* Règle appliquée à tous les événements */ +#define LOGD_SELECT_GRV 2 /* Règle appliquée aux événements d'une certaine gravité */ +#define LOGD_SELECT_RC 3 /* Règle appliquée aux événements associés à un certain code retour */ +#define LOGD_SELECT_TYPE 4 /* Règle appliquée aux événements d'un certain type */ + +/* Notion de règle de sélection des événements */ + +typedef void LOGT_Rule; /* Contient le code gravité, code retour ou type d'événement selon la classe de la règle */ + +/* Différents indicateurs */ + +typedef int LOGT_Flags; + +/* Modes d'ouverture et de fermeture */ + +#define LOGD_CREATE SMD_CREATE /* Création */ +#define LOGD_OPEN SMD_OPEN /* Ouverture simple */ +#define LOGD_DESTROY SMD_DESTROY /* Destruction */ +#define LOGD_CLOSE SMD_CLOSE /* Fermeture simple */ + +/* Flags de debug sur l'ouverture de la librairie */ + +#define LOGD_DEBUG_NONE SMD_DEBUG_NONE /* pour n'afficher aucun message généré par les diverses librairies */ +#define LOGD_DEBUG SMD_DEBUG /* pour afficher les messages générés par la librairie */ +#define LOGD_DEBUG_ALL SMD_DEBUG_ALL /* pour afficher les messages générés par toutes les librairies sous-jacentes */ + +#define LOGD_DEBUG_MSK (MSGD_DEBUG & MSGD_DEBUG_ALL) + +/* Mode de fonctionnement d'un trigger */ + +#define LOGD_ADD 0x01 /* Trigger d'ajout de table de routage */ +#define LOGD_REMOVE 0x02 /* Trigger de suppression de table de routage */ +#define LOGD_ONE_SHOT 0x04 /* Trigger actif une seul fois */ +#define LOGD_PERMANENT 0x08 /* Trigger actif en permanence */ + +#define LOGD_ADD_MSK(a) (LOGD_ADD & a) +#define LOGD_REMOVE_MSK(a) (LOGD_REMOVE & a) +#define LOGD_ONE_SHOT_MSK(a) (LOGD_ONE_SHOT & a) +#define LOGD_PERMANENT_MSK(a) (LOGD_PERMANENT & a) + +/* Notion de channel */ + +typedef struct { + pid_t Pid; /* Processus propriétaire du channel */ + int Id; /* Identifiant du channel */ + int ModuleId; /* Identifiant du module envoyeur */ + int Master_ModuleId; /* Identifiant du module primaire */ + NDT_Root * RTab_List; /* Liste de tables de routage */ + NDT_Root * SubModule_List; /* Liste des sous-modules */ + NDT_Root * Trigger_List; /* Liste des triggers posés sur le channel */ + NDT_Root * Event_Cpt_List; /* Liste de compteurs d'événements */ +} LOGT_Channel; + +/* Notion de trigger (ajout ou suppression dynamique de tables de routage) */ + +typedef struct LOGT_Trigger +{ + char * Event_Name; /* Evénement déclencheur du trigger */ + LOGT_RTab * RTab; /* Table de routage utilisateur concernée */ + LOGT_Flags Mode; /* Mode de fonctionnement du trigger */ + LOGT_Channel * Channel; /* Channel auquel est rattaché le trigger */ +} LOGT_Trigger; + +/* Base système de la librairie LIBLOG */ + +typedef struct { + NDT_Root * KMOD; /* Cache des modules */ + NDT_Root * KFORMAT; /* Cache des formats d'événement */ + LOGT_RTab * GDRT; /* Table GDRT */ + LOGT_RTab * GMRT; /* Table GMRT */ + NDT_Root * LMRT_List; /* Liste des LMRT */ + NDT_Root * LDRT_List; /* Liste des LDRT */ + NDT_Root * URT_List; /* Liste des URT */ + NDT_Root * Channel_List; /* Liste des channels */ +} LOGT_Base; + +LOGT_Base * LOG_Base = NULL; + +/* Informations sur un type d'événement */ + +typedef struct { + unsigned int Event_Type; /* Identifiant du type d'événement */ + char * Event_Name; /* Nom du type d'événément */ + LOGT_Rooting Rooting; /* Routage associé */ + LOGT_Gravite Gravite; /* Code gravité associé */ + LOGT_RC RC; /* Code retour associé */ + NDT_Root * Data_List; /* Liste des données du format de l'événement */ +} LOGT_Info; + +/* Format d'un type d'événement */ + +typedef struct { + unsigned int Event_Type; /* Type d'événement */ + NDT_Root * Data_List; /* Liste des données du format */ +} LOGT_Event_Format; + +/* Message explicite des erreurs générées par la librairie LINLOG */ + +char LOG_Error_Msg [256]; + +/* Identifiant du port de messages pour l'envoi des événements */ + +#define LOGD_EVENT_PORT_NAME "EVENT_PORT" + +/* Type des messages qui contiennent les événements */ + +#define LOGD_EVENT_MSG_TYPE 100 + +/* + Formatage des événements par les clients de la LIBLOG : + + EVEN1[.EVEN2[.EVEN3]]@[MODULE1[.MODULE2[.MODULE3]]]:[MODE1[.MODE2[.MODE3]]]:[GEO1[.GEO2[.GEO3]]] + + */ + +#define EVEN1 0x00000101 +#define EVEN2 0x00000102 +#define EVEN3 0x00000103 +#define MODULE1 0x00000201 +#define MODULE2 0x00000202 +#define MODULE3 0x00000203 +#define MODE1 0x00000301 +#define MODE2 0x00000302 +#define MODE3 0x00000303 +#define GEO1 0x00000401 +#define GEO2 0x00000402 +#define GEO3 0x00000403 + +#define DEFAULT -1L +#define CHAR 0L +#define STRING 1L +#define SHORT 2L +#define INT 3L +#define LONG 4L +#define FLOAT 5L +#define DOUBLE 6L + +#define END_NAME -1 +#define END_DATA "END_DATA" + +/* Format d'un message contenant un événement */ + +#define EVENT_FORMAT_VERSION_SIZE 10 /* sur 10 caractères max */ +#define EVENT_FORMAT_VERSION "V1.0" + +/* Zone de données du message : + + - Version de format de message : 10 octets | + - Numéro de processus envoyeur : 4 octets | Entête + - Identifiant du module envoyeur : 4 octets | + - Identifiant du module primaire : 4 octets | + + - Identifiant du type d'événement : 4 octets + + - Taille du nom de l'événement : 1 octet | + - Nom de l'événement | + - Taille du code support : 1 octet | + - Code support | + - Taille du nom de la macro-donnée : 1 octet | Evénement | + - Nom de la macro-donnée | | + - Taille de la valeur de la macro-donnée : 1 octet | | N fois + - Valeur de la macro-donnée | | +*/ + +typedef struct { + char Version [EVENT_FORMAT_VERSION_SIZE]; + unsigned int Sending_Pid; + unsigned int ModuleId; + unsigned int Master_ModuleId; +} LOGT_Event_Msg_Header; + +typedef struct { + LOGT_Event_Msg_Header Header; + unsigned int Event_Type; + size_t Data_Size; + char Event_Data; +} LOGT_Event_Msg_Data; + +/* Définition des alias de l'API */ + +#ifndef LOG_MODE +#define LOG_MODE 0 +#endif + +#if LOG_MODE == 1 + + /* API sans vérification des arguments */ + +# define LOG_Library_Open LOG_Library_Open_I +# define LOG_Library_Close LOG_Library_Close_I +# define LOG_Library_Stderr_Set LOG_Library_Stderr_Set_I +# define LOG_Channel_Open LOG_Channel_Open_I +# define LOG_Channel_Enter LOG_Channel_Enter_I +# define LOG_Channel_Leave LOG_Channel_Leave_I +# define LOG_Channel_Close LOG_Channel_Close_I +# define LOG_RTab_Alloc LOG_RTab_Alloc_I +# define LOG_RTab_Setup LOG_RTab_Setup_I +# define LOG_RTab_Add LOG_RTab_Add_I +# define LOG_RTab_Remove LOG_RTab_Remove_I +# define LOG_RTab_Free LOG_RTab_Free_I +# define LOG_Trigger_Add LOG_Trigger_Add_I +# define LOG_Trigger_Remove LOG_Trigger_Remove_I +# define LOG_Event_Send LOG_Event_Send_I +# define LOG_Event_External_Send LOG_Event_External_Send_I +# define LOG_Event_Info_Get LOG_Event_Info_Get_I +# define LOG_Event_Cpt_Get LOG_Event_Cpt_Get_I + +#else + + /* API avec vérification des arguments */ + +# define LOG_Library_Open LOG_Library_Open_C +# define LOG_Library_Close LOG_Library_Close_C +# define LOG_Library_Stderr_Set LOG_Library_Stderr_Set_C +# define LOG_Channel_Open LOG_Channel_Open_C +# define LOG_Channel_Enter LOG_Channel_Enter_C +# define LOG_Channel_Leave LOG_Channel_Leave_C +# define LOG_Channel_Close LOG_Channel_Close_C +# define LOG_RTab_Alloc LOG_RTab_Alloc_C +# define LOG_RTab_Setup LOG_RTab_Setup_C +# define LOG_RTab_Add LOG_RTab_Add_C +# define LOG_RTab_Remove LOG_RTab_Remove_C +# define LOG_RTab_Free LOG_RTab_Free_C +# define LOG_Trigger_Add LOG_Trigger_Add_C +# define LOG_Trigger_Remove LOG_Trigger_Remove_C +# define LOG_Event_Send LOG_Event_Send_C +# define LOG_Event_External_Send LOG_Event_External_Send_C +# define LOG_Event_Info_Get LOG_Event_Info_Get_C +# define LOG_Event_Cpt_Get LOG_Event_Cpt_Get_C + +#endif + +/*------------------------------------------------------------------------------*/ +/* Ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Instance : numéro de l'instance à ouvrir */ +/* (I) Context : contexte d'utilisation de la librairie */ +/* (I) Open_Mode : mode d'ouverture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Open_I ( int Instance, const char * Context, LOGT_Flags Open_Mode ); +LOGT_Status LOG_Library_Open_C ( int Instance, const char * Context, LOGT_Flags Open_Mode ); + +/*------------------------------------------------------------------------------*/ +/* Fermeture de l'instance de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Close_Mode : mode de fermeture de la librairie */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Close_I ( LOGT_Flags Close_Mode ); +LOGT_Status LOG_Library_Close_C ( LOGT_Flags Close_Mode ); + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Library_Stderr_Set_I ( FILE * Out ); +LOGT_Status LOG_Library_Stderr_Set_C ( FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Création d'un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (O) Channel : adresse du pointeur sur le canal créé */ +/* (I) Pid : numéro du processus propriétaire du canal */ +/* (I) Channel_Id : identifiant du canal au sein du processus */ +/* (I) Module_Name : nom du module propriétaire du canal */ +/* (I) Master_Module_Name : nom du module primaire */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Open_I (LOGT_Channel ** Channel, int Pid, int Channel_Id, const char * Module_Name, const char * Master_Module_Name); +LOGT_Status LOG_Channel_Open_C (LOGT_Channel ** Channel, int Pid, int Channel_Id, const char * Module_Name, const char * Master_Module_Name); + +/*------------------------------------------------------------------------------*/ +/* Entrée dans un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Enter_I ( LOGT_Channel * Channel, const char * SubModule_Name ); +LOGT_Status LOG_Channel_Enter_C ( LOGT_Channel * Channel, const char * SubModule_Name ); + +/*------------------------------------------------------------------------------*/ +/* Sortie d'un sous-module pour un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal */ +/* (I) SubModule_Name : nom du sous-module */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Leave_I ( LOGT_Channel * Channel, const char * SubModule_Name ); +LOGT_Status LOG_Channel_Leave_C ( LOGT_Channel * Channel, const char * SubModule_Name ); + +/*------------------------------------------------------------------------------*/ +/* Fermeture d'un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal à fermer */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Channel_Close_I ( LOGT_Channel * Channel); +LOGT_Status LOG_Channel_Close_C ( LOGT_Channel * Channel); + +/*------------------------------------------------------------------------------*/ +/* Création d'une table de routage utilisateur */ +/*------------------------------------------------------------------------------*/ +/* (O) RTab : adresse du pointeur sur la table de routage */ +/* (I) Name : nom de la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Alloc_I ( LOGT_RTab ** RTab, char * Name ); +LOGT_Status LOG_RTab_Alloc_C ( LOGT_RTab ** RTab, char * Name ); + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une règle à une table de routage */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage */ +/* (I) RuleClass : classe de la nouvelle règle */ +/* (I) Rule : pointeur sur la nouvelle règle */ +/* (I) Value : valeur de la nouvelle règle */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Setup_I ( LOGT_RTab * RTab, LOGT_RuleClass RuleClass, LOGT_Rule * Rule, LOGT_Rooting Value ); +LOGT_Status LOG_RTab_Setup_C ( LOGT_RTab * RTab, LOGT_RuleClass RuleClass, LOGT_Rule * Rule, LOGT_Rooting Value ); + +/*------------------------------------------------------------------------------*/ +/* Ajout d'une table de routage à un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal de communication */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Add_I ( LOGT_Channel * Channel, LOGT_RTab * RTab ); +LOGT_Status LOG_RTab_Add_C ( LOGT_Channel * Channel, LOGT_RTab * RTab ); + +/*------------------------------------------------------------------------------*/ +/* Suppression d'une table de routage d'un canal de communication */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le canal de communication */ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Remove_I ( LOGT_Channel * Channel, LOGT_RTab * RTab ); +LOGT_Status LOG_RTab_Remove_C ( LOGT_Channel * Channel, LOGT_RTab * RTab ); + +/*------------------------------------------------------------------------------*/ +/* Destruction d'une table de routage */ +/*------------------------------------------------------------------------------*/ +/* (I) RTab : pointeur sur la table de routage */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_RTab_Free_I ( LOGT_RTab * RTab ); +LOGT_Status LOG_RTab_Free_C ( LOGT_RTab * RTab ); + +/*------------------------------------------------------------------------------*/ +/* Ajout d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (O) Trigger : adresse du pointeur sur le trigger mis en place */ +/* (I) Channel : pointeur sur le canal de communication */ +/* (I) RTab : pointeur sur la table de routage à appliquer */ +/* (I) Type_Evt : type d'événement déclencheur ( expression régulière ) */ +/* (I) Mode : mode de fonctionnement du trigger */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Add_I ( LOGT_Trigger ** Trigger, LOGT_Channel * Channel, LOGT_RTab * RTab, char * Type_Evt, LOGT_Flags Mode ); +LOGT_Status LOG_Trigger_Add_C ( LOGT_Trigger ** Trigger, LOGT_Channel * Channel, LOGT_RTab * RTab, char * Type_Evt, LOGT_Flags Mode ); + +/*------------------------------------------------------------------------------*/ +/* Suppression d'un trigger */ +/*------------------------------------------------------------------------------*/ +/* (I) Trigger : pointeur sur le trigger mis en place */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Trigger_Remove_I ( LOGT_Trigger * Trigger ); +LOGT_Status LOG_Trigger_Remove_C ( LOGT_Trigger * Trigger ); + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un canal de communication */ +/* (O) RC : pointeur sur le code retour associé à l'événement */ +/* (I) Cd_Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Send_I ( LOGT_Channel * Channel, LOGT_RC * RC, char * Cd_Support, va_list Data ); +LOGT_Status LOG_Event_Send_C ( LOGT_Channel * Channel, LOGT_RC * RC, char * Cd_Support, va_list Data ); + +/*------------------------------------------------------------------------------*/ +/* Envoi d'un événement ( PL/SQL ou shell ) */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : identifiant du channel */ +/* (I) Cd_Support : code du support source */ +/* (I) Data : données de l'événement */ +/*------------------------------------------------------------------------------*/ +/* (O) Retourne le code retour associé au type d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_RC LOG_Event_External_Send_I ( LOGT_Channel * Channel, char * Cd_Support, char * Data ); +LOGT_RC LOG_Event_External_Send_C ( LOGT_Channel * Channel, char * Cd_Support, char * Data ); + +/*------------------------------------------------------------------------------*/ +/* Retourne les informations du type par lequel un événement est résolu */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un canal de communication */ +/* (O) Info : pointeur sur les informations à récupérer */ +/* (I) Event_Name : nom de l'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Info_Get_I ( LOGT_Channel * Channel, LOGT_Info ** Info, char * Event_Name ); +LOGT_Status LOG_Event_Info_Get_C ( LOGT_Channel * Channel, LOGT_Info ** Info, char * Event_Name ); + +/*------------------------------------------------------------------------------*/ +/* Retourne le nombre d'événements envoyés par code retour */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur un canal de communication */ +/* (O) Cpt : pointeur sur un tableau de compteurs d'événement */ +/* (I) RegExpr : expression régulière sur le nom d'événement */ +/*------------------------------------------------------------------------------*/ +LOGT_Status LOG_Event_Cpt_Get_I ( LOGT_Channel * Channel, int * Cpt [LOGD_RC_SIZE], char * RegExpr ); +LOGT_Status LOG_Event_Cpt_Get_C ( LOGT_Channel * Channel, int * Cpt [LOGD_RC_SIZE], char * RegExpr ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/tool.h b/lib/tool.h new file mode 100644 index 0000000..c4250c6 --- /dev/null +++ b/lib/tool.h @@ -0,0 +1,68 @@ +#ifndef _LIBTOOL +#define _LIBTOOL + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Codes retour des fonctions de l'API */ + +typedef int TLT_Status; + +#define TLS_OK LOGS_OK +#define TLS_KO LOGS_KO + +typedef int TLT_Cache; + +#define TLD_KMOD 0001 +#define TLD_KFORMAT 0010 +#define TLD_GDRT 0100 + +char TL_Error_Msg[256]; + +/*------------------------------------------------------------------------------*/ +/* Définition de la sortie standard des messages d'erreur de la librairie */ +/*------------------------------------------------------------------------------*/ +/* (I) Out : flux de sortie des messages d'erreur */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Library_Stderr_Set ( FILE * Out ); + +/*------------------------------------------------------------------------------*/ +/* Chargement des caches de la librairie LIBLOG */ +/*------------------------------------------------------------------------------*/ +/* (I) ToLoad : liste des caches de données à charger */ +/* (combinaison de TLD_KMOD, TLD_KFORMAT et TLD_GDRT) */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_LIBLOG_Load (TLT_Cache ToLoad); + +/*------------------------------------------------------------------------------*/ +/* Déchargement des caches de la librairie LIBLOG */ +/*------------------------------------------------------------------------------*/ +/* (I) ToUnload : liste des caches de données à décharger */ +/* (combinaison de TLD_KMOD, TLD_KFORMAT et TLD_GDRT) */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_LIBLOG_Unload (TLT_Cache ToUnload); + +/*------------------------------------------------------------------------------*/ +/* Affectation de toutes les tables de routage d'une section KUNF à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Nm : nom de la section KUNF */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Channel_RTab_Add (LOGT_Channel * My_Channel, const char * Kunf_Nm); + +/*------------------------------------------------------------------------------*/ +/* Affectation de tous les triggers d'une section KUNF à un channel */ +/*------------------------------------------------------------------------------*/ +/* (I) Channel : pointeur sur le channel */ +/* (I) Kunf_Nm : nom de la section KUNF */ +/*------------------------------------------------------------------------------*/ +TLT_Status TL_Channel_Trigger_Add (LOGT_Channel * My_Channel, const char * Kunf_Nm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/util/logadmin.c b/util/logadmin.c new file mode 100644 index 0000000..72db8c8 --- /dev/null +++ b/util/logadmin.c @@ -0,0 +1,426 @@ +#include +#include +#include +#include +#include +#include +#include + +VER_INFO_EXPORT (logadmin, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") + +#define USAGE "Usage : %s [ --help | --version [-v] | --create | --destroy | --load [1|2|3] ] | --unload [1|2|3] ]\n" + +typedef struct { + double sec; + struct timeval start; + struct timeval stop; +} 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;} +cpt t_exec; + +#define QUIT 0 +#define BASE_INIT 1 +#define BASE_OPEN 2 +#define BASE_INFO 3 +#define BASE_CLOSE 4 +#define BASE_END 5 +#define BASE_LOAD 6 +#define BASE_UNLOAD 7 +#define SHOW_CHANNEL_LIST 8 +#define SHOW_RTAB_LIST 9 +#define CHANNEL_DUMP 10 +#define RTAB_DUMP 11 +#define TEST_EVENT 12 + +char menu [1000]; +char tmp [100]; + +void init_menu (void); +int print_menu (void); +char * Get_Rooting (LOGT_Rooting); +char * Get_RC (LOGT_RC); + +int main (int argc, char ** argv) +{ + int choice, i; + char Name [100]; + LOGT_Channel * My_Channel; + char Answer[10]; + NDT_Node * Node; + NDT_Root * Root; + LOGT_RTab RTab; + int Mode; + LOGT_Info * Info; + + TL_Library_Stderr_Set (stderr); + + /* Lancement de commande d'administration ? */ + + if (argc >= 2) + { + if (!strcmp (argv [1], "--help")) + { + fprintf (stderr, USAGE, argv [0]); + return -1; + } + else if (!strcmp (argv [1], "--version")) + { + if (argc >= 3 && !strcmp (argv [2], "-v")) + return VER_Object_Print (stdout, VERD_VERBOSE); + else + return VER_Object_Print (stdout, VERD_MINIMAL); + } + else if (!strcmp (argv [1], "--create")) + { + if (SM_Library_Open (0, NULL, SMD_OPEN | SMD_DEBUG_ALL) != SMS_OK) + { + fprintf (stderr, "=> Impossible d'ouvrir l'instance de la LIBSHMEM\n"); + return -1; + } + + if (LOG_Library_Open (0, NULL, LOGD_CREATE | SMD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "=> Création de la LIBLOG impossible\n"); + return -1; + } + + return 0; + } + else if (!strcmp (argv [1], "--load")) + { + Mode = 0; + + if (argc > 2) + { + if (strchr (argv [2], '1')) Mode += TLD_KMOD; + if (strchr (argv [2], '2')) Mode += TLD_KFORMAT; + if (strchr (argv [2], '3')) Mode += TLD_GDRT; + } + + if (LOG_Library_Open (0, NULL, LOGD_OPEN | SMD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "=> Ouverture de la LIBLOG impossible\n"); + return -1; + } + + if (TL_LIBLOG_Load (Mode) != LOGS_OK) + { + fprintf (stderr, "=> Chargement de la LIBLOG impossible\n"); + return -1; + } + return 0; + } + else if (!strcmp (argv [1], "--unload")) + { + Mode = 0; + + if (argc > 2) + { + if (strchr (argv [2], '1')) Mode += TLD_KMOD; + if (strchr (argv [2], '2')) Mode += TLD_KFORMAT; + if (strchr (argv [2], '3')) Mode += TLD_GDRT; + } + + if (LOG_Library_Open (0, NULL, LOGD_OPEN | SMD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "=> Ouverture de la LIBLOG impossible\n"); + return -1; + } + + if (TL_LIBLOG_Unload (Mode) != LOGS_OK) + { + fprintf (stderr, "=> Déchargement de la LIBLOG impossible\n"); + return -1; + } + return 0; + } + else if (!strcmp (argv [1], "--destroy")) + { + if (LOG_Library_Open (0, NULL, LOGD_OPEN | SMD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "=> Ouverture de la LIBLOG à détruire impossible\n"); + return -1; + } + + if (LOG_Library_Close (LOGD_DESTROY) != LOGS_OK) + { + fprintf (stderr, "=> Destruction de la LIBLOG impossible\n"); + return -1; + } + return 0; + } + else + { + fprintf (stderr, USAGE, argv [0]); + return -1; + } + } + + /* Lancement du menu intercatif */ + + init_menu (); + + choice = print_menu (); + + while (choice != QUIT) + { + strcpy (Answer, "yes"); + + switch (choice) + { + case BASE_INIT: + fprintf (stdout, "\nReturn code = %s\n", \ + LOG_Library_Open (0, NULL, LOGD_CREATE | SMD_DEBUG_ALL) == LOGS_OK ? "OK" : "NOK" ); + break; + + case BASE_OPEN: + fprintf (stdout, "\nReturn code = %s\n", \ + LOG_Library_Open (0, NULL, LOGD_OPEN | SMD_DEBUG_ALL) == LOGS_OK ? "OK" : "NOK" ); + break; + + case BASE_END: + fprintf (stdout, "\nReturn code = %s\n", \ + LOG_Library_Close (LOGD_DESTROY) == LOGS_OK ? "OK" : "NOK" ); + break; + + case BASE_CLOSE: + fprintf (stdout, "\nReturn code = %s\n", \ + LOG_Library_Close (LOGD_CLOSE) == LOGS_OK ? "OK" : "NOK" ); + break; + + case BASE_INFO: + DS_DataStruct_Info_Print (LOG_Base->KMOD, stdout); + DS_DataStruct_Info_Print (LOG_Base->KFORMAT, stdout); + DS_DataStruct_Info_Print (LOG_Base->GDRT->Root, stdout); + DS_DataStruct_Info_Print (LOG_Base->LMRT_List, stdout); + DS_DataStruct_Info_Print (LOG_Base->LDRT_List, stdout); + DS_DataStruct_Info_Print (LOG_Base->URT_List, stdout); + DS_DataStruct_Info_Print (LOG_Base->Channel_List, stdout); + break; + + case BASE_LOAD: + fprintf (stdout, "\nCache to load ? (KMOD=1, KFORMAT=2, GDRT=3) "); + gets (Name); + Mode = 0; + if (strchr (Name, '1')) Mode |= TLD_KMOD; + if (strchr (Name, '2')) Mode += TLD_KFORMAT; + if (strchr (Name, '3')) Mode += TLD_GDRT; + fprintf (stdout, "\nReturn code = %s\n", TL_LIBLOG_Load (Mode) == LOGS_OK ? "OK" : "NOK" ); + + break; + + case BASE_UNLOAD: + fprintf (stdout, "\nCache to unload ? (KMOD=1, KFORMAT=2, GDRT=3) "); + gets (Name); + Mode = 0; + if (strchr (Name, '1')) Mode += TLD_KMOD; + if (strchr (Name, '2')) Mode += TLD_KFORMAT; + if (strchr (Name, '3')) Mode += TLD_GDRT; + fprintf (stdout, "\nReturn code = %s\n", TL_LIBLOG_Unload (Mode) == LOGS_OK ? "OK" : "NOK" ); + + break; + + case SHOW_RTAB_LIST: + DS_DataStruct_Print (LOG_Base->LMRT_List, stdout); + DS_DataStruct_Print (LOG_Base->LDRT_List, stdout); + DS_DataStruct_Print (LOG_Base->URT_List, stdout); + break; + + case SHOW_CHANNEL_LIST: + DS_DataStruct_Print (LOG_Base->Channel_List, stdout); + break; + + case CHANNEL_DUMP: + fprintf (stdout, "\nChannel address ? "); + gets (Name); + i = atoi (Name); + + if (DS_Node_Find (LOG_Base->Channel_List, &Node, (void *)i, NULL) != DSS_OK) + fprintf (stdout, "Unable to find channel at address %d\n", i); + else + { + My_Channel = (LOGT_Channel *)(Node->Value); + + ND_Manager_Exec (LOG_Base->Channel_List->Manager, NDD_CMD_PRINT_VALUE, &My_Channel, stdout); + + if (fprintf (stdout, "\n\nShow rooting tables ? (y/n) ") && gets (tmp) && *tmp == 'y') + DS_DataStruct_Print (My_Channel->RTab_List, stdout); + + if (fprintf (stdout, "\nShow submodules ? (y/n) ") && gets (tmp) && *tmp == 'y') + DS_DataStruct_Print (My_Channel->SubModule_List, stdout); + + if (fprintf (stdout, "\nShow triggers ? (y/n) ") && gets (tmp) && *tmp == 'y') + DS_DataStruct_Print (My_Channel->Trigger_List, stdout); + + if (fprintf (stdout, "\nShow event counters ? (y/n) ") && gets (tmp) && *tmp == 'y') + DS_DataStruct_Print (My_Channel->Event_Cpt_List, stdout); + } + break; + + case RTAB_DUMP: + fprintf (stdout, "\nTable Name ? "); + gets (Name); + RTab.Name = Name; + if ((DS_Node_Find (LOG_Base->LMRT_List, &Node, &RTab, NULL) == DSS_OK && (Root = LOG_Base->LMRT_List)) || + (DS_Node_Find (LOG_Base->LDRT_List, &Node, &RTab, NULL) == DSS_OK && (Root = LOG_Base->LDRT_List)) || + (DS_Node_Find (LOG_Base->URT_List, &Node, &RTab, NULL) == DSS_OK && (Root = LOG_Base->URT_List))) + { + ND_Manager_Exec (Root->Manager, NDD_CMD_PRINT_VALUE, (void **)&(Node->Value), stdout); + + if (fprintf (stdout, "\n\nShow events ? (y/n) ") && gets (tmp) && *tmp == 'y') + DS_DataStruct_Print (((LOGT_RTab *)(Node->Value))->Root, stdout); + } + else + fprintf (stdout, "\nUnable to find rooting table \"%s\"\n", Name); + + break; + + case TEST_EVENT: + fprintf (stdout, "\nEvent name ? "); + gets (Name); + Info = (LOGT_Info *)malloc(sizeof(LOGT_Info)); + t_start (t_exec); + if (LOG_Event_Info_Get(NULL, &Info, Name) != LOGS_OK) + { + fprintf (stdout, "\nEvénement \"%s\" non résolu\n", Name); + t_stop (t_exec); + } + else + { + t_stop (t_exec); + fprintf (stdout, "\nEvénement \"%s\" résolu en %.4f sec :\n", Name, t_exec.sec); + fprintf (stdout, "\t- Type : %s (%d)\n", Info->Event_Name, Info->Event_Type); + fprintf (stdout, "\t- Routage : %s\n", Get_Rooting(Info->Rooting)); + fprintf (stdout, "\t- Gravité : %c\n", (char)Info->Gravite); + fprintf (stdout, "\t- Code retour : %s\n", Get_RC(Info->RC)); + fprintf (stdout, "\t- Format :"); + if (Info->Data_List) + { + ND_Node_First_Get(Info->Data_List, &Node); + i = 0; + while (Node) + { + if (i > 0) fprintf (stdout, ","); + fprintf (stdout, " %s", (char *)(Node->Value)); + ND_Node_Next_Get (Node, &Node); + i++; + } + } + fprintf (stdout, "\n\n"); + } + free(Info); + break; + + case QUIT: + fprintf (stdout, "\nExiting program ...\n"); + break; + + default: + fprintf (stdout, "\nUndefined choice %d\n", choice); + } + choice = print_menu (); + } + return 0; +} + +void init_menu (void) +{ + sprintf (menu, "Menu :\n"); + sprintf (tmp, " - %2d) %-25s", QUIT, "Quit"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", BASE_INIT, "Init library"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s", BASE_OPEN, "Open library"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", BASE_INFO, "Info library"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s", BASE_CLOSE, "Close library"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", BASE_END, "End library"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s", BASE_LOAD, "Load library cache"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", BASE_UNLOAD, "Unload library cache"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s", SHOW_CHANNEL_LIST, "Show channels"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", SHOW_RTAB_LIST, "Show rooting tables"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s", CHANNEL_DUMP, "Dump a channel"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", RTAB_DUMP, "Dump a rooting table"); strcat (menu, tmp); + sprintf (tmp, " - %2d) %-25s\n", TEST_EVENT, "Test an event"); strcat (menu, tmp); +} + +int print_menu (void) +{ + fprintf (stdout, "---------------------------------------------------------------------------\n%s", menu); + + tmp[0] = '\0'; + while (tmp[0] == '\0') + { + printf ("\nChoice ? "); + gets (tmp); + } + + return atoi (tmp); +} + +char *Get_Rooting(LOGT_Rooting Rooting) +{ + static char lib[20]; + + switch ((int)Rooting) + { + case LOGD_ROOTING_NULL: + strcpy(lib, "NULL"); + break; + case LOGD_ROOTING_STDERR: + strcpy(lib, "STDERR"); + break; + case LOGD_ROOTING_DATABASE: + strcpy(lib, "BASE"); + break; + case LOGD_ROOTING_DEFAULT: + strcpy(lib, "DEFAULT"); + break; + case LOGD_ROOTING_PREVIOUS: + strcpy(lib, "PREVIOUS"); + break; + default: + strcpy(lib, "unknown"); + break; + } + + return lib; +} + +char *Get_RC(LOGT_RC RC) +{ + static char lib[20]; + + switch ((int)RC) + { + case LOGD_RC_OK: + strcpy(lib, "OK"); + break; + case LOGD_RC_ANOERR: + strcpy(lib, "ANOERR"); + break; + case LOGD_RC_REJDON: + strcpy(lib, "REJDON"); + break; + case LOGD_RC_REJENR: + strcpy(lib, "REJENR"); + break; + case LOGD_RC_WARNING: + strcpy(lib, "WARNING"); + break; + case LOGD_RC_RECYCLE: + strcpy(lib, "RECYCLE"); + break; + case LOGD_RC_EXIT: + strcpy(lib, "EXIT"); + break; + case LOGD_RC_ABEND: + strcpy(lib, "ABEND"); + break; + default: + strcpy(lib, "unknown"); + break; + } + + return lib; +} + diff --git a/util/logagent.c b/util/logagent.c new file mode 100644 index 0000000..2705ba9 --- /dev/null +++ b/util/logagent.c @@ -0,0 +1,504 @@ +#include +#include +#include +#include +#include +#define MSG_MODE 1 +#include +#include +#include + +VER_INFO_EXPORT (logagent, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") + +void Parse_Arg (int , char **); +void Event_Msg_Process ( MSGT_Message * ); +void System_Msg_Process ( MSGT_Message * ); +void Info_Trace ( void ); + +unsigned int End_Agent, Nb_Event, Nb_System_Msg; +MSGT_Port * Private_Port, * Event_Port; +MSGT_PortList * Private_PortList; + +unsigned int Num_Agent, Status, Debug; +char Debug_Trace [512]; + +/*--------------------------------------------------------------------------------------------------*/ +/* Fonction principale */ +/*--------------------------------------------------------------------------------------------------*/ +int main ( int argc, char ** argv ) +{ + MSGT_Message * Msg; + char Private_Port_Name [256]; + + /* Récupération des arguments de la ligne de commande */ + + Parse_Arg (argc, argv); + + /* Démarrage de l'agent */ + + Status = ACTIVE; + + /* Ouverture de la librairie LIBMSG */ + + if (MSG_Library_Open (NULL, NULL, MSGD_OPEN) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible d'ouvrir la librairie LIBMSG"); + Info_Trace (); + return KO; + } + + /* Ouverture du port de message dans lequel sont envoyés les événements */ + + if (MSG_Port_Open (LOGD_EVENT_PORT_NAME, &Event_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible d'ouvrir le port de messages des événements"); + Info_Trace (); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + /* Ouverture (cas du restart) ou création du port privé de l'agent */ + + sprintf (Private_Port_Name, "Agent_%d_port", Num_Agent); + + if (MSG_Port_Open (Private_Port_Name, &Private_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de d'ouvrir ou de créer mon port de messages privé"); + Info_Trace (); + MSG_Port_Close (Event_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + /* Création d'une liste de ports (port public + port privé) que l'agent va écouter */ + + if (MSG_PortList_Open (&Private_PortList) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de créer ma liste de ports"); + Info_Trace (); + MSG_Port_Close (Event_Port, MSGD_CLOSE); + MSG_Port_Close (Private_Port, MSGD_DESTROY); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + if (MSG_PortList_Port_Add (Private_PortList, Private_Port) != MSGS_OK || MSG_PortList_Port_Add (Private_PortList, Event_Port) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible d'ajouter les ports privé et public à ma liste de ports"); + Info_Trace (); + MSG_PortList_Close (Private_PortList); + MSG_Port_Close (Event_Port, MSGD_CLOSE); + MSG_Port_Close (Private_Port, MSGD_DESTROY); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + sprintf (Debug_Trace, "démarrage en mode trace %s", Debug == TRUE ? "activé" : "désactivé"); + Info_Trace (); + + /* Boucle principale */ + + Nb_System_Msg = 0; + Nb_Event = 0; + End_Agent = FALSE; + + while (End_Agent == FALSE) + { + unsigned int Expected_Type; + + if (Status == ACTIVE) + { + /* Quand l'agent est actif, il traite tous les types de messages */ + + Expected_Type = MSGD_NO_TYPE; + } + else + { + /* Quand l'agent est stoppé, il ne traite que les messages système */ + + Expected_Type = MSGD_SYSTEM_GENERIC; + } + + /* Ecoute des ports de messages de la liste */ + + if (MSG_PortList_Listen (Private_PortList, Expected_Type, &Msg, MSGD_WAIT) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de réceptionner un message depuis l'un des ports écoutés"); + Info_Trace (); + MSG_PortList_Close (Private_PortList); + MSG_Port_Close (Private_Port, MSGD_DESTROY); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + /* Traitement du message */ + + switch (Msg->Type) + { + case LOGD_EVENT_MSG_TYPE: + + /* Il s'agit d'un événement */ + + Event_Msg_Process (Msg); + Nb_Event ++; + + break; + + default: + + /* Il s'agit d'un message système */ + + System_Msg_Process (Msg); + Nb_System_Msg ++; + + break; + } + } + + /* Suppression de la liste de ports de l'agent */ + + if (MSG_PortList_Close (Private_PortList) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de supprimer ma liste de ports"); + Info_Trace (); + MSG_Port_Close (Private_Port, MSGD_DESTROY); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + /* Suppression du port privé de l'agent */ + + if (MSG_Port_Close (Private_Port, MSGD_DESTROY) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de supprimer mon port de messages privé"); + Info_Trace (); + MSG_Library_Close (MSGD_CLOSE); + return KO; + } + + /* Fermeture de la librairie */ + + if (MSG_Library_Close (MSGD_CLOSE) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de fermer la librairie LIBMSG"); + Info_Trace (); + return KO; + } + + strcpy (Debug_Trace, "terminé"); + Info_Trace (); + + return OK; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Récupération de la ligne de commande */ +/*--------------------------------------------------------------------------------------------------*/ +void Parse_Arg (int argc, char ** argv) +{ + int i; + + Debug = FALSE; + + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) + { + fprintf (stderr, "Usage : %s [ [--help|-h] | --version [-v] | -id [--debug] ]\n", argv [0]); + exit (1); + } + + if (!strcmp (argv[i], "-id")) + { + i++; + if (i == argc) + { + fprintf (stderr, "Argument manquant après \"%s\"\n", argv[i - 1]); + exit (0); + } + + Num_Agent = atoi (argv[i]); + continue; + } + + if (!strcmp (argv[i], "--version")) + { + if (i+1 < argc && !strcmp (argv[i+1], "-v")) + { + VER_Object_Print (stdout, VERD_VERBOSE); + exit (0); + } + else + { + VER_Object_Print (stdout, VERD_MINIMAL); + exit (0); + } + } + + if (!strcmp (argv[i], "--debug")) + { + Debug = TRUE; + continue; + } + + fprintf (stderr, "Option invalide \"%s\"\n", argv[i]); + exit (0); + } + + if (Num_Agent == 0) + { + fprintf (stderr, "Option \"-id\" manquante ou bien valeur incorrecte (doit être > 0)\n"); + exit (0); + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Traitement d'un message contenant un événement */ +/*--------------------------------------------------------------------------------------------------*/ +void Event_Msg_Process (MSGT_Message * Msg) +{ + LOGT_Event_Msg_Data * Msg_Data; + unsigned int Length, Event_Type; + char Event_Name [256]; + char Cd_Support [256]; + char Data_Name [256]; + char Data_Value [256]; + unsigned int i; + char * Event_Data_Ptr; + + /* Récupération des données de l'entête de l'événement */ + + Msg_Data = (LOGT_Event_Msg_Data *)(Msg->Data); + + /* Vérification de la version du format */ + + if (strcmp (Msg_Data->Header.Version, EVENT_FORMAT_VERSION)) + { + sprintf (Debug_Trace, "version du format de message \"%s\" incorrect (\"%s\" attendu)", Msg_Data->Header.Version, EVENT_FORMAT_VERSION); + Info_Trace (); + + /* Suppression du message */ + + MSG_Message_Free (Msg); + + return; + } + + sprintf (Debug_Trace, "réception d'un événement de la part du processus %d (module %d/%d)", + Msg_Data->Header.Sending_Pid, + Msg_Data->Header.ModuleId, + Msg_Data->Header.Master_ModuleId); + + /* Récupération de l'identifiant du type d'événement */ + + Event_Type = Msg_Data->Event_Type; + + /* Récupération du nom de l'événement */ + + Event_Data_Ptr = &(Msg_Data->Event_Data); + + i = 0; + Length = (unsigned int)(Event_Data_Ptr [i]); + strncpy (Event_Name, Event_Data_Ptr + i + 1, Length); + Event_Name [Length] = (char)0; + + i += 1 + Length; + + if (Debug == TRUE) fprintf (stderr, "%s\nEvénement \"%s\" (type=%d):", Debug_Trace, Event_Name, Event_Type); + + Length = (unsigned int)(Event_Data_Ptr [i]); + strncpy (Cd_Support, Event_Data_Ptr + i + 1, Length); + Cd_Support [Length] = (char)0; + + if (Debug == TRUE) fprintf (stderr, "%s\n\t- support=\"%s\"\n", Debug_Trace, Cd_Support); + + i += 1 + Length; + + /* Récupération des macro-données */ + + while (i < Msg_Data->Data_Size) + { + /* Récupération du nom de la macro-donnée */ + + Length = (unsigned int)(Event_Data_Ptr [i]); + strncpy (Data_Name, Event_Data_Ptr + i + 1, Length); + Data_Name [Length] = (char)0; + + i += 1 + Length; + + if (i < Msg->Size) + { + /* Récupération de la valeur de la macro-donnée */ + + Length = (unsigned int)(Event_Data_Ptr [i]); + strncpy (Data_Value, Event_Data_Ptr + i + 1, Length); + Data_Value [Length] = (char)0; + + i += 1 + Length; + } + else + { + strcpy (Debug_Trace, "mauvais format d'événement"); + Info_Trace (); + } + + if (Debug == TRUE) fprintf (stderr, "\t- %s=%s\n", Data_Name, Data_Value); + } + + /* Traitement de l'événement + + ... + ... + ... + + */ + + + /* Renvoi du message à l'envoyeur */ + + if (MSG_Message_Reply (Msg) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de renvoyer le message de l'événement à son envoyeur"); + Info_Trace (); + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Traitement d'un message système par un agent */ +/*--------------------------------------------------------------------------------------------------*/ +void System_Msg_Process (MSGT_Message * Msg) +{ + /* Pour accuser réception du message système, on commence par remplir les données liées à l'agent */ + + ((Agent_Stat *)(Msg->Data))->Num_Agent = Num_Agent; + ((Agent_Stat *)(Msg->Data))->Pid = getpid (); + + switch (Msg->Type) + { + case MSGD_SYSTEM_STOP_REQUEST: + + if (Status == ACTIVE) + { + /* On indique que la requête a bien été prise en compte */ + + ((Agent_Stat *)(Msg->Data))->Answer = TRUE; + + /* Pause de l'agent jusqu'à réception d'un message MSGD_SYSTEM_CONTINUE_REQUEST */ + + Status = STOPPED; + + strcpy (Debug_Trace, "pause"); + Info_Trace (); + } + else + { + /* On indique que la requête n'a pas été prise en compte */ + + ((Agent_Stat *)(Msg->Data))->Answer = FALSE; + } + + break; + + case MSGD_SYSTEM_CONTINUE_REQUEST: + + if (Status == STOPPED) + { + /* On indique que la requête a bien été prise en compte */ + + ((Agent_Stat *)(Msg->Data))->Answer = TRUE; + + /* Reprise de l'agent */ + + Status = ACTIVE; + + strcpy (Debug_Trace, "reprise"); + Info_Trace (); + } + else + { + /* On indique que la requête n'a pas été prise en compte */ + + ((Agent_Stat *)(Msg->Data))->Answer = FALSE; + } + + break; + + case MSGD_SYSTEM_SHUTDOWN_REQUEST: + + /* Fin de la boucle principale de l'agent */ + + End_Agent = TRUE; + + strcpy (Debug_Trace, "terminaison en cours..."); + Info_Trace (); + + break; + + case MSGD_SYSTEM_STATUS_REQUEST: + + /* On informe le superviseur sur l'état dans lequel on se trouve */ + + ((Agent_Stat *)(Msg->Data))->Status = Status; + ((Agent_Stat *)(Msg->Data))->Debug = Debug; + + break; + + case MSGD_SYSTEM_INFO_REQUEST: + + /* On informe le superviseur sur le nombre de messages (système et événement) traités */ + + ((Agent_Stat *)(Msg->Data))->Cpt_Event = Nb_Event; + ((Agent_Stat *)(Msg->Data))->Cpt_System = Nb_System_Msg; + + break; + + case MSGD_SYSTEM_TRACEON_REQUEST: + + Debug = TRUE; + strcpy (Debug_Trace, "activation du mode trace"); + Info_Trace (); + + break; + + case MSGD_SYSTEM_TRACEOFF_REQUEST: + + strcpy (Debug_Trace, "désactivation du mode trace"); + Info_Trace (); + Debug = FALSE; + + break; + + default : + + /* On indique que la requête n'a pas été prise en compte */ + + ((Agent_Stat *)(Msg->Data))->Answer = FALSE; + + break; + } + + /* On accuse réception du message */ + + MSG_Message_Reply (Msg); +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Affichage sur la sortie standard d'erreur d'un message généré par un agent */ +/*--------------------------------------------------------------------------------------------------*/ +void Info_Trace ( void ) +{ + time_t dts; + struct tm * dt; + char Current_Date [25]; + + if (Debug == TRUE) + { + /* Récupère la date courante */ + + time (&dts); + dt = localtime (&dts); + sprintf (Current_Date, "%02d/%02d/%04d %02d:%02d:%02d", dt->tm_mday, dt->tm_mon + 1, dt->tm_year + 1900, dt->tm_hour, dt->tm_min, dt->tm_sec); + + fprintf (stderr, "[%s] Agent n°%d : %s\n", Current_Date, Num_Agent, Debug_Trace); + } +} diff --git a/util/logagent.h b/util/logagent.h new file mode 100644 index 0000000..bbe6dfa --- /dev/null +++ b/util/logagent.h @@ -0,0 +1,24 @@ + +#define ANSWER_SIZE 1000 /* Taille minimale des messages système adressés au superviseur */ +#define DEFAULT_TIMEOUT 5 /* Nombre de secondes avant lesquelles les agents devront répondre aux requêtes du superviseur */ +#define NB_MAX_AGENT 50 /* Nombre maximal d'agents pouvant être suivis par le superviseur */ + +/* Etats possibles d'un agent */ + +#define STOPPED 0 +#define ACTIVE 1 + +#define OK 1 +#define KO -1 + +/* Structure contenant les informations qu'un agent renvoie au superviseur */ + +typedef struct { + unsigned int Num_Agent; /* Numéro de l 'agent */ + pid_t Pid; /* Identifiant du processus de l'agent */ + unsigned int Status; /* Etat dans lequel se trouve l'agent */ + unsigned int Debug; /* Mode debug dans lequel se trouve l'agent */ + unsigned int Cpt_Event; /* Nombre d'événements traités */ + unsigned int Cpt_System; /* Nombre de messages système traités */ + unsigned int Answer; /* Réponse de l'agent à la requête */ +} Agent_Stat; diff --git a/util/logbench.c b/util/logbench.c new file mode 100644 index 0000000..798d5b4 --- /dev/null +++ b/util/logbench.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#define LOG_MODE 1 +#include +#include + +typedef struct { + double sec; + long count; + struct timeval start; + struct timeval stop; +} cpt; + +#define t_init(x) {x.sec = 0; x.count = 0;} +#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; x.count++;} + +int main (int argc, char ** argv) +{ + LOGT_Channel * My_Channel; + char Line [1000], * Event_Data; + FILE * fid; + unsigned int Nb_Send, Line_Number, i; + cpt Compteur; + + if (argc != 2) + { + fprintf (stderr, "Usage : %s \n", argv [0]); + return -1; + } + + /* Ouverture du fichier de test */ + + fid = fopen (argv [1], "r"); + if (!fid) + { + fprintf (stderr, "Unable to open file \"%s\" for reading\n", argv [1]); + return -1; + } + + /* Ouverture de la librairie */ + + if (LOG_Library_Open (0, NULL, LOGD_OPEN | LOGD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "\n=> Impossible d'ouvrir la librairie LIBLOG\n"); + return -1; + } + + /* Ouverture d'un channel */ + + if (LOG_Channel_Open (&My_Channel, 0, 1, "IPR_CAVpopulate2.pc", "IPR_CAV") != LOGS_OK) + { + fprintf (stderr, "\n=> Impossible d'ouvrir un channel\n"); + return -1; + } + + /* Ajout des tables de routage utilisateur */ + + if (TL_Channel_RTab_Add (My_Channel, "UTILS:ROOTING:ROOTING_TABLE") != TLS_OK) + { + fprintf (stderr, "\n=> Impossible d'ajouter les tables de routage au channel\n"); + LOG_Channel_Close (My_Channel); + return -1; + } + + /* Ajout des triggers */ + + if (TL_Channel_Trigger_Add (My_Channel, "UTILS:ROOTING:TRIGGER") != TLS_OK) + { + fprintf (stderr, "\n=> Impossible d'ajouter les triggers au channel\n"); + LOG_Channel_Close (My_Channel); + return -1; + } + + /* Initialisation du compteur */ + + t_init (Compteur); + + /* Envoi des événements paramétrés dans le fichier */ + + Line_Number = 1; + + while (!feof (fid) && fgets (Line, 1000, fid)) + { + /* Récupération des informations dans la ligne du fichier */ + + Event_Data = strchr (Line, '#'); + + if (Event_Data == NULL) + { + fprintf (stderr, "Warning ligne n°%d : format incorrect (caractère '#' manquant)\n", Line_Number); + } + else + { + *Event_Data = (char)0; + + Nb_Send = atoi (Line); + + if (Nb_Send <= 0) + { + fprintf (stderr, "Warning ligne n°%d : valeur (%d) incorrecte avant le caracatère '#'\n", Line_Number, Nb_Send); + Nb_Send = 1; + } + + Event_Data++; + + for (i = 0; i < Nb_Send; i++) + { + t_start (Compteur); + + /* Envoi de l'événement proprement dit */ + + if (LOG_Event_External_Send (My_Channel, argv [1], Event_Data) == LOGD_RC_WARNING) + fprintf (stderr, "Warning ligne n°%d : code retour WARNING sur envoi de l'événement\n", Line_Number); + + t_stop (Compteur); + } + } + + Line_Number++; + } + + fclose (fid); + + /* Affichage du résultat du benchmark */ + + fprintf (stdout, "%ld événements envoyés en %.2f sec (%.2f évt/sec)\n", Compteur.count, Compteur.sec, Compteur.count / Compteur.sec); + + /* Fermeture du channel */ + + if (LOG_Channel_Close (My_Channel) != LOGS_OK) + { + fprintf (stderr, "\n=> Impossible de fermer le channel\n"); + return -1; + } + + /* Fermeture de la librairie */ + + if (LOG_Library_Close (LOGD_CLOSE) != LOGS_OK) + { + fprintf (stderr, "\n=> Impossible de fermer la librairie LIBLOG\n"); + return -1; + } + + return 1; +} + diff --git a/util/logresolve.c b/util/logresolve.c new file mode 100644 index 0000000..dd2ca6f --- /dev/null +++ b/util/logresolve.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include +#define ND_MODE 1 +#include +#define LOG_MODE 1 +#include + +VER_INFO_EXPORT (logresolve, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") + +typedef struct { + double sec; + struct timeval start; + struct timeval stop; +} 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;} +cpt t_exec; + +char * Get_Rooting (LOGT_Rooting); +char * Get_RC (LOGT_RC); + +#define USAGE "Usage : %s [ --help | --version [-v] | --event ]\n" + +int main (int argc, char **argv) +{ + LOGT_Info * Info; + char * Event; + int i; + + if (argc >= 2) + { + if (!strcmp (argv [1], "--help")) + { + fprintf (stderr, USAGE, argv [0]); + return 1; + } + else if (!strcmp (argv [1], "--version")) + { + if (argc >= 3 && !strcmp (argv [2], "-v")) + return VER_Object_Print (stdout, VERD_VERBOSE); + else + return VER_Object_Print (stdout, VERD_MINIMAL); + } + else if (!strcmp (argv [1], "--event")) + { + if (argc != 3) + { + fprintf (stderr, USAGE, argv [0]); + return 0; + } + + Event = argv [2]; + } + else + { + fprintf (stderr, USAGE, argv [0]); + return 0; + } + } + else + { + fprintf (stderr, USAGE, argv [0]); + return 0; + } + + /* Récupération des informations sur un événement */ + + Info = (LOGT_Info *) malloc (sizeof (LOGT_Info)); + + if (LOG_Library_Open (0, NULL, LOGD_OPEN | LOGD_DEBUG_ALL) != LOGS_OK) + { + fprintf (stderr, "=> Ouverture de la librairie LIBLOG impossible\n"); + return 0; + } + + t_start (t_exec); + + if (LOG_Event_Info_Get (NULL, &Info, Event) != LOGS_OK) + { + t_stop (t_exec); + fprintf (stderr, "=> Impossible de résoudre l'événement \"%s\"\n", Event); + } + else + { + NDT_Node * Node; + + t_stop (t_exec); + fprintf (stdout, "\nEvénement \"%s\" résolu en %.4f sec :\n", Event, t_exec.sec); + fprintf (stdout, "\t- Type : %s (Id=%d)\n", Info->Event_Name, Info->Event_Type); + fprintf (stdout, "\t- Routage : %s\n", Get_Rooting (Info->Rooting)); + fprintf (stdout, "\t- Gravité : %c\n", (char)Info->Gravite); + fprintf (stdout, "\t- Code retour : %s\n", Get_RC (Info->RC)); + fprintf (stdout, "\t- Format :"); + if (Info->Data_List) + { + ND_Node_First_Get (Info->Data_List, &Node); + i = 0; + while (Node) + { + if (i > 0) fprintf (stdout, ","); + fprintf (stdout, " %s", (char *)(Node->Value)); + ND_Node_Next_Get (Node, &Node); + i++; + } + } + fprintf (stdout, "\n\n"); + } + + LOG_Library_Close (LOGD_CLOSE); + + free (Info); + + return 0; +} + +char * Get_Rooting (LOGT_Rooting Rooting) +{ + static char lib [20]; + + switch ((int)Rooting) + { + case LOGD_ROOTING_NULL: + strcpy (lib, "NULL"); + break; + case LOGD_ROOTING_STDERR: + strcpy (lib, "STDERR"); + break; + case LOGD_ROOTING_DATABASE: + strcpy (lib, "BASE"); + break; + case LOGD_ROOTING_DEFAULT: + strcpy (lib, "DEFAULT"); + break; + case LOGD_ROOTING_PREVIOUS: + strcpy (lib, "PREVIOUS"); + break; + default: + strcpy (lib, "unknown"); + break; + } + + return lib; +} + +char * Get_RC (LOGT_RC RC) +{ + static char lib [20]; + + switch ((int)RC) + { + case LOGD_RC_OK: + strcpy (lib, "OK"); + break; + case LOGD_RC_ANOERR: + strcpy (lib, "ANOERR"); + break; + case LOGD_RC_REJDON: + strcpy (lib, "REJDON"); + break; + case LOGD_RC_REJENR: + strcpy (lib, "REJENR"); + break; + case LOGD_RC_WARNING: + strcpy (lib, "WARNING"); + break; + case LOGD_RC_RECYCLE: + strcpy (lib, "RECYCLE"); + break; + case LOGD_RC_EXIT: + strcpy (lib, "EXIT"); + break; + case LOGD_RC_ABEND: + strcpy (lib, "ABEND"); + break; + default: + strcpy (lib, "unknown"); + break; + } + + return lib; +} diff --git a/util/logsupervisor.c b/util/logsupervisor.c new file mode 100644 index 0000000..d0e798f --- /dev/null +++ b/util/logsupervisor.c @@ -0,0 +1,1246 @@ +#include +#include +#include +#include +#include +#include +#include +#ifdef LINUX +#include +#include +#else +#include +#include +#endif +#include +#include +#define ND_MODE 1 +#include +#define MSG_MODE 1 +#include +#include + +extern int sigignore(int sig); + +VER_INFO_EXPORT (logsupervisor, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") + +/*--------------------------------------------------------------------------------------------------*/ + +#define Date_IsSet(tvp) ((tvp).tv_sec || (tvp).tv_usec) +#define Date_Compare(tvp, uvp) ((tvp).tv_sec < (uvp).tv_sec || ((tvp).tv_sec == (uvp).tv_sec && (tvp).tv_usec < (uvp).tv_usec)) + +/* Tableau permettant de référéncer les agents suivis par le superviseur */ + +typedef struct { + pid_t Pid; /* Identifiant du processus */ + short int Restarted; /* Indique si l'agent est déjà tombé puis a été redémarré */ + short int GivenUp; /* Indique si l'agent a été abandonné (car tombé plusieur fois) */ +} Agent_Ref; + +Agent_Ref * Tab_Agent; + +/* Requêtes à traiter par le superviseur (classées par type de message système) */ + +typedef struct { + struct timeval Request_Date; /* Date de début de la requête */ + unsigned int Nb_Reply; /* Nombre de réponses recues de la part des agents */ + Agent_Stat Reply_Stat [NB_MAX_AGENT]; /* Statistiques des agents ayant répondu */ + NDT_Root * Msg_List; /* Liste chaînée des messages en attente sur cette requête */ +} Waiting_Request; + +Waiting_Request Tab_Request [MSGD_NB_SYSTEM_MESSAGE]; + +char Debug_Trace [256]; +unsigned int Timeout; + +/*--------------------------------------------------------------------------------------------------*/ + +#define AGENT_PATH "logagent" + +#define SUPERVISOR_START 1 +#define SUPERVISOR_PING 2 +#define SUPERVISOR_STATUS_GET 3 +#define SUPERVISOR_INFO_GET 4 +#define SUPERVISOR_STOP_AGENT 5 +#define SUPERVISOR_CONTINUE_AGENT 6 +#define SUPERVISOR_TRACEON 7 +#define SUPERVISOR_TRACEOFF 8 +#define SUPERVISOR_SHUTDOWN 9 + +void Parse_Arg ( int, char ** ); +void Supervisor_Start ( void ); +void Supervisor_Request (unsigned int, size_t, int); +void Supervisor_Ping ( void ); +void Supervisor_Status_Get ( void ); +void Supervisor_Info_Get ( void ); +void Supervisor_Agent_Stop ( void ); +void Supervisor_Agent_Continue ( void ); +void Supervisor_Shutdown ( void ); + +void System_Msg_Process ( MSGT_Message * ); +int Agent_Msg_Send ( unsigned int, unsigned int, int ); +int Agent_Start ( unsigned int ); +void Agent_Restart ( int signum ); +char * Agent_Status_Get ( unsigned int Agent_Status, unsigned int Agent_Debug ); +void Request_Answer ( unsigned int Idx ); +void Timeout_Handle ( int signum ); +void Info_Trace ( void ); +char * Status_Get ( void ); +NDT_Status Request_List_Manager ( va_list ); + +unsigned int Nb_Agent, Nb_GivenUp, End_Supervisor, Status, Debug, Action; +MSGT_Port * Supervisor_Port, * System_Port; + +/*--------------------------------------------------------------------------------------------------*/ + +int main ( int argc , char ** argv ) +{ + /* Récupération des arguments de la ligne de commande */ + + Parse_Arg (argc, argv); + + /* Lancement de l'action sur le superviseur */ + + switch (Action) + { + case SUPERVISOR_START: + Supervisor_Start (); + break; + + case SUPERVISOR_PING: + Supervisor_Request (MSGD_SYSTEM_PING_REQUEST, sizeof (MSGT_PingData), MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_STATUS_GET: + Supervisor_Request (MSGD_SYSTEM_STATUS_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_INFO_GET: + Supervisor_Request (MSGD_SYSTEM_INFO_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_STOP_AGENT: + Supervisor_Request (MSGD_SYSTEM_STOP_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_CONTINUE_AGENT: + Supervisor_Request (MSGD_SYSTEM_CONTINUE_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_TRACEON: + Supervisor_Request (MSGD_SYSTEM_TRACEON_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_TRACEOFF: + Supervisor_Request (MSGD_SYSTEM_TRACEOFF_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + case SUPERVISOR_SHUTDOWN: + Supervisor_Request (MSGD_SYSTEM_SHUTDOWN_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY); + break; + + default: + break; + } + + return OK; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Récupération de la ligne de commande */ +/*--------------------------------------------------------------------------------------------------*/ +void Parse_Arg (int argc, char ** argv) +{ + int i; + + Debug = FALSE; + Nb_Agent = 0; + Timeout = 0; + + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) + { + char Usage [1000]; + + sprintf (Usage, + "Usage : %s \nOptions :\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n", + argv [0], + "--help | -h", "-> Affiche l'aide courante", + "--version [-v]", "-> Affiche le numéro de version", + "--start [--debug] [--timeout ]", "-> Démarre le superviseur et agents", + "--ping", "-> Ping le superviseur", + "--status", "-> Affiche le status de tous les agents et du superviseur", + "--info", "-> Affiche des informations statistiques de tous les agents", + "--stop", "-> Stoppe tous les agents", + "--continue", "-> Continue tous les agents stoppés", + "--traceon", "-> Active le mode trace du superviseur et des agents", + "--traceoff", "-> Désactive le mode trace du superviseur et des agents", + "--shutdown", "-> Tue tous les agents et le superviseur"); + fprintf (stderr, Usage); + exit (1); + } + + if (!strcmp (argv[i], "--version")) + { + if (i+1 < argc && !strcmp (argv[i+1], "-v")) + { + VER_Object_Print (stdout, VERD_VERBOSE); + exit (0); + } + else + { + VER_Object_Print (stdout, VERD_MINIMAL); + exit (0); + } + } + + if (!strcmp (argv[i], "--start")) + { + Action = SUPERVISOR_START; + i++; + if (i == argc) + { + fprintf (stderr, "Missing argument after %s\n", argv[i - 1]); + exit (0); + } + + if ((Nb_Agent = atoi (argv[i])) <= 0) + { + fprintf (stderr, "Bad value (%s) after %s\n", argv[i], argv[i - 1]); + exit (0); + } + + continue; + } + + if (!strcmp (argv[i], "--ping")) + { + Action = SUPERVISOR_PING; + continue; + } + + if (!strcmp (argv[i], "--status")) + { + Action = SUPERVISOR_STATUS_GET; + continue; + } + + if (!strcmp (argv[i], "--info")) + { + Action = SUPERVISOR_INFO_GET; + continue; + } + + if (!strcmp (argv[i], "--stop")) + { + Action = SUPERVISOR_STOP_AGENT; + continue; + } + + if (!strcmp (argv[i], "--continue")) + { + Action = SUPERVISOR_CONTINUE_AGENT; + continue; + } + + if (!strcmp (argv[i], "--traceon")) + { + Action = SUPERVISOR_TRACEON; + continue; + } + + if (!strcmp (argv[i], "--traceoff")) + { + Action = SUPERVISOR_TRACEOFF; + continue; + } + + if (!strcmp (argv[i], "--shutdown")) + { + Action = SUPERVISOR_SHUTDOWN; + continue; + } + + if (!strcmp (argv[i], "--debug")) + { + Debug = TRUE; + continue; + } + + if (!strcmp (argv[i], "--timeout")) + { + i++; + if (i == argc) + { + fprintf (stderr, "Missing argument after %s\n", argv[i - 1]); + exit (0); + } + + if ((Timeout = atoi (argv[i])) <= 0) + { + fprintf (stderr, "Bad value (%s) after %s\n", argv[i], argv[i - 1]); + exit (0); + } + + continue; + } + + fprintf (stderr, "Option invalide \"%s\"\n", argv[i]); + exit (0); + } + + if (Timeout == 0) Timeout = DEFAULT_TIMEOUT; +} + +/*--------------------------------------------------------------------------------------------------*/ +/*--------------------------------------- SUPERVISEUR ----------------------------------------------*/ +/*--------------------------------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------------------------------*/ +/* Envoie une requête au superviseur */ +/*--------------------------------------------------------------------------------------------------*/ +void Supervisor_Request (unsigned int Type, size_t Size, int Priority) +{ + MSGT_Message * Msg; + + Debug = TRUE; + + /* Ouverture de la librairie LIBLOG */ + + if (MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK) + { + fprintf (stderr, "=> Impossible d'ouvrir la librairie LIBMSG\n"); + return; + } + + /* Ouverture du port de messages du superviseur */ + + if (MSG_Port_Open (MSGD_SUPERVISOR_PORT_NAME, &Supervisor_Port, MSGD_OPEN) != MSGS_OK) + { + fprintf (stderr, "=> Impossible d'ouvrir le port de messages du superviseur\n"); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Création / ouverture du port système dont on se sert pour les accusés réception */ + + if (MSG_Port_Open (MSGD_SYSTEM_PORT_NAME, &System_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) + { + fprintf (stderr, "=> Impossible d'ouvrir ou de créer le port de messages système\n"); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Création du message */ + + if (MSG_Message_Alloc (&Msg, Size) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de créer un message\n"); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Port_Close (System_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + memset (Msg->Data, 0, Msg->Size); + + if (MSG_Message_Config (Msg, MSGD_CONFIG_TYPE, Type) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de configurer le type du message\n"); + MSG_Message_Free (Msg); + MSG_Port_Close (System_Port, MSGD_CLOSE); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + if (MSG_Message_Config (Msg, MSGD_CONFIG_PRIORITY, Priority) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de configurer la priorité du message\n"); + MSG_Message_Free (Msg); + MSG_Port_Close (System_Port, MSGD_CLOSE); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Envoi du message avec demande d'accusé réception dans le port système */ + + if (MSG_Message_Send (MSGD_SYSTEM_PORT_NAME, Supervisor_Port, Msg) != MSGS_OK) + { + fprintf (stderr, "=> Impossible d'envoyer le message\n"); + MSG_Port_Close (System_Port, MSGD_CLOSE); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Fermeture du port de messages du superviseur */ + + if (MSG_Port_Close (Supervisor_Port, MSGD_CLOSE) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de fermer le port de messages du superviseur\n"); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Ecoute du port de messages système */ + + if (MSG_Message_Receive (System_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de réceptionner un message dans le port système\n"); + MSG_Message_Free (Msg); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + if (Msg->Type == MSGD_SYSTEM_PING_REPLY) + { + double send_delay, rcv_delay, ping_delay; + struct timeval t1, t2, t3, t4; + + t1 = ((MSGT_PingData *)(Msg->Data))->Snd1; + t2 = ((MSGT_PingData *)(Msg->Data))->Rcv1; + t3 = ((MSGT_PingData *)(Msg->Data))->Snd2; + t4 = ((MSGT_PingData *)(Msg->Data))->Rcv2; + + send_delay = (double)(t2.tv_sec) - (double)(t1.tv_sec) + ((double)(t2.tv_usec) - (double)(t1.tv_usec)) / 1000000; + rcv_delay = (double)(t4.tv_sec) - (double)(t3.tv_sec) + ((double)(t4.tv_usec) - (double)(t3.tv_usec)) / 1000000; + ping_delay = (double)(t4.tv_sec) - (double)(t1.tv_sec) + ((double)(t4.tv_usec) - (double)(t1.tv_usec)) / 1000000; + + fprintf (stdout, "Ping = %.4f sec (Aller = %.4f sec / Retour = %.4f sec)\n", ping_delay, send_delay, rcv_delay); + } + else + { + /* Autres messages système */ + + fprintf (stdout, (char *)(Msg->Data)); + } + + /* Désallocation du message */ + + if (MSG_Message_Free (Msg) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de supprimer le message\n"); + MSG_Port_Close (System_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Fermeture du port de messages système */ + + if (MSG_Port_Close (System_Port, MSGD_CLOSE) != MSGS_OK) + { + fprintf (stderr, "=> Impossible de fermer le port de messages système\n"); + MSG_Library_Close (MSGD_CLOSE); + return ; + } + + MSG_Library_Close (MSGD_CLOSE); +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Procédure de démarrage du superviseur */ +/*--------------------------------------------------------------------------------------------------*/ +void Supervisor_Start ( void ) +{ + MSGT_Message * Msg; + unsigned int i; + + Nb_GivenUp = 0; + End_Supervisor = FALSE; + Status = ACTIVE; + + /* Allocation d'un tableau pour référencer les agents */ + + Tab_Agent = (Agent_Ref *)malloc (Nb_Agent * sizeof (Agent_Ref)); + + if (!Tab_Agent) + { + strcpy (Debug_Trace, "impossible d'allouer de la mémoire pour référencer les agents"); + Info_Trace (); + return; + } + + /* Initialisation du tableau des requêtes soumises au superviseur */ + + for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++) + { + memset (&(Tab_Request [i]), 0, sizeof (Waiting_Request)); + ND_DataStruct_Open (&(Tab_Request [i].Msg_List), NDD_DS_LIST | NDD_MN_FIFO, NULL, NULL, NULL, TRUE); + strcpy (Tab_Request [i].Msg_List->Manager, "Request_List_Manager"); + } + + /* Ouverture de la librairie LIBMSG */ + + if (MSG_Library_Open (0, NULL, MSGD_OPEN) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible d'ouvrir la librairie LIBMSG"); + Info_Trace (); + return; + } + + /* Ouverture / création du port de messages du superviseur */ + + if (MSG_Port_Open (MSGD_SUPERVISOR_PORT_NAME, &Supervisor_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible d'ouvrir mon port de messages privé"); + Info_Trace (); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* On trappe le signal SIGCHLD pour détecter les agents qui tombent */ + + signal (SIGCHLD, Agent_Restart); + + /* Lancement des agents */ + + for (i = 1; i <= Nb_Agent; i++) Agent_Start (i); + + /* Boucle principale du superviseur */ + + while (End_Supervisor == FALSE) + { + /* Ecoute du port de messages du superviseur */ + + int rc = MSG_Message_Receive (Supervisor_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT); + + switch (rc) + { + case MSGS_OK: + + /* Traitement des messages envoyés au superviseur */ + + System_Msg_Process (Msg); + + break; + + case MSGS_ERRSIG: + + /* On continue à boucler sur l'écoute */ + + break; + + default: + strcpy (Debug_Trace, "impossible de réceptionner un message dans mon port du messages privé"); + Info_Trace (); + MSG_Message_Free (Msg); + MSG_Port_Close (Supervisor_Port, MSGD_CLOSE); + MSG_Library_Close (MSGD_CLOSE); + return; + } + } + + /* Fermeture du port de messages du superviseur */ + + if (MSG_Port_Close (Supervisor_Port, MSGD_CLOSE) != MSGS_OK) + { + strcpy (Debug_Trace, "impossible de fermer mon port de messages privé"); + Info_Trace (); + MSG_Library_Close (MSGD_CLOSE); + return; + } + + /* Fermeture de la librairie LIBMSG */ + + MSG_Library_Close (MSGD_CLOSE); + + /* Désallocation des ressources locales */ + + for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++) + { + if (Tab_Request [i].Msg_List) ND_DataStruct_Close (Tab_Request [i].Msg_List); + } + + strcpy (Debug_Trace, "terminé"); + Info_Trace (); +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Traitement d'un message système par le superviseur */ +/*--------------------------------------------------------------------------------------------------*/ +void System_Msg_Process (MSGT_Message * Msg) +{ + unsigned int Idx; + unsigned int i; + + /* S'agit-il d'un message de type REQUEST ou REPLY ? */ + + if (MSGD_IS_SYSTEM_REQUEST (Msg->Type)) + { + Idx = (Msg->Type - 1) / 2; + + /* Le message est-il de taille suffisante pour que l'on y réponde ? */ + + if (Msg->Size < ANSWER_SIZE) + { + /* On le supprime : tant pis pour l'envoyeur ! */ + + MSG_Message_Free (Msg); + + sprintf (Debug_Trace, "la requête envoyée par \"%s\" ne sera pas prise en compte car le message est de taille insuffisante (%d octets minimum)", Msg->From, ANSWER_SIZE); + Info_Trace (); + + return; + } + + /* + Mise du message en attente : on y répondra lorque tous les + agents y auront répondu ou bien lorsque le timeout aura expiré. + */ + + ND_Value_Add (Tab_Request [Idx].Msg_List, Msg); + + /* On regarde si une requête du même type était déjà en cours */ + + if (Tab_Request [Idx].Msg_List->Node_Number == 1) + { + /* S'il s'agit d'une requête SHUTDOWN_REQUEST, il faut désormais ignorer les signaux de type SIGCHLD */ + + if (Msg->Type == MSGD_SYSTEM_SHUTDOWN_REQUEST) + sigignore (SIGCHLD); + + /* On prend en compte les requêtes TRACEON_REQUEST et TRACEOFF_REQUEST */ + + if (Msg->Type == MSGD_SYSTEM_TRACEON_REQUEST) + { + Debug = TRUE; + sprintf (Debug_Trace, "activation du mode trace"); + Info_Trace (); + } + + if (Msg->Type == MSGD_SYSTEM_TRACEOFF_REQUEST) + { + sprintf (Debug_Trace, "désactivation du mode trace"); + Info_Trace (); + Debug = FALSE; + } + + /* On mémorise la date de la requête */ + + gettimeofday (&(Tab_Request [Idx].Request_Date), NULL); + + if (Nb_Agent - Nb_GivenUp == 0) + { + /* S'il n'y a plus d'agent valide, on répond tout de suite à la requête */ + + Request_Answer (Idx); + } + else + { + /* Sinon, on initie une alarme ... */ + + signal (SIGALRM, Timeout_Handle); + alarm (Timeout); + + /* ... et on transmet la requête à tous les agents qui devront y répondre avant le timeout */ + + for (i = 1; i <= Nb_Agent; i++) + { + if (Tab_Agent [i -1].GivenUp == FALSE) + { + if (Agent_Msg_Send (i, Msg->Type, MSGD_SYSTEM_HIGH_PRIORITY) != OK) + { + sprintf (Debug_Trace, "impossible de transmettre la requête à l'agent n°%d", i); + Info_Trace (); + } + } + } + } + } + } + else if (MSGD_IS_SYSTEM_REPLY (Msg->Type)) /* Il s'agit d'une réponse d'un agent */ + { + Idx = (Msg->Type / 2) - 1; + + /* Une requête de ce type a-t'elle déjà été lancée ? */ + + if (Tab_Request [Idx].Msg_List->Node_Number > 0) + { + int Num_Agent; + Agent_Stat * Stat; + + Tab_Request [Idx].Nb_Reply++; + + /* Mise à jour de statistiques : on recopie celles renvoyés par l'agent dans notre tableau */ + + Stat = (Agent_Stat *)(Msg->Data); + + Num_Agent = Stat->Num_Agent; + + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Num_Agent = Stat->Num_Agent; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Pid = Stat->Pid; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Cpt_Event = Stat->Cpt_Event; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Cpt_System = Stat->Cpt_System; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Status = Stat->Status; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Debug = Stat->Debug; + Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Answer = Stat->Answer; + + /* Tous les agents ont-ils répondu à la requête ? */ + + if (Tab_Request [Idx].Nb_Reply == Nb_Agent - Nb_GivenUp) + { + /* On répond à la requête */ + + Request_Answer (Idx); + } + else + { + /* Tous les agents n'ont pas encore répondu : on attend encore */ + } + } + else + { + /* L'agent a répondu trop tard : tant pis pour lui, on ne tient pas compte de cette réponse */ + } + + /* On supprime le message */ + + MSG_Message_Free (Msg); + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Réponse à une requête (procédure exécutée au timeout ou bien lorsque tous les agents ont répondu)*/ +/*--------------------------------------------------------------------------------------------------*/ +void Request_Answer ( unsigned int Idx ) +{ + char Answer [ANSWER_SIZE]; + unsigned int i, j; + unsigned int Type = 2 * Idx + 1; + NDT_Node * Node, * Next_Node; + NDT_Root * Msg_List; + char str [256]; + + Answer [0] = (char)0; + + /* Réponse concernant le superviseur lui-même */ + + switch (Type) + { + case MSGD_SYSTEM_TRACEON_REQUEST: + + sprintf (str, "Superviseur : mode trace activé\n"); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_TRACEOFF_REQUEST: + + sprintf (str, "Superviseur : mode trace désactivé\n"); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_STATUS_REQUEST: + + sprintf (str, "Superviseur : %s\n", Status_Get ()); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_INFO_REQUEST: + + /* Informations concernant les agents suivis */ + + sprintf (str, "Superviseur :\n\t- %d agent(s) suivi(s)\n\t- %d agent(s) abandonné(s)\n", Nb_Agent - Nb_GivenUp, Nb_GivenUp); + strcat (Answer, str); + + /* On compte le nombre de requêtes en attente */ + + j = 0; + for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++) + if (i != Idx && Tab_Request [i].Msg_List->Node_Number > 0) j++; + + sprintf (str, "\t- %d requête(s) en attente de réponse de la part des agents\n", j); + strcat (Answer, str); + + /* On consolide les statistiques des agents concernant le nombre d'événements traités */ + + j = 0; + for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++) + j += Tab_Request [Idx].Reply_Stat [i].Cpt_Event; + + sprintf (str, "\t- %d événement(s) traité(s) par l'ensemble des agents ayant répondu\n\n", j); + strcat (Answer, str); + + break; + + case MSGD_SYSTEM_SHUTDOWN_REQUEST: + + End_Supervisor = TRUE; + + strcpy (Debug_Trace, "terminaison en cours..."); + Info_Trace (); + + break; + + default: + + break; + } + + /* Réponse concernant les agents auxquels la requête a été transmise */ + + sprintf (str, "%d/%d agent(s) ont répondu à la requête%s\n", Tab_Request [Idx].Nb_Reply, Nb_Agent - Nb_GivenUp, Tab_Request [Idx].Nb_Reply > 0 ? " :" : "."); + strcat (Answer, str); + + for (i = 0; i < Nb_Agent; i++) + { + if (Tab_Agent [i].GivenUp == TRUE) continue; + + sprintf (str, "\t- Agent n°%d (process %ld) : ", i + 1, Tab_Agent [i].Pid); + strcat (Answer, str); + + if (Tab_Request [Idx].Reply_Stat [i].Num_Agent == 0) + strcat (Answer, "pas de réponse\n"); + else + { + switch (Type) + { + case MSGD_SYSTEM_STOP_REQUEST: + sprintf (str, "%s\n", Tab_Request [Idx].Reply_Stat [i].Answer == TRUE ? "stoppé" : "déjà stoppé"); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_CONTINUE_REQUEST: + sprintf (str, "%s\n", Tab_Request [Idx].Reply_Stat [i].Answer == TRUE ? "repris" : "déjà actif"); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_SHUTDOWN_REQUEST: + strcat (Answer, "arrêté\n"); + break; + + case MSGD_SYSTEM_STATUS_REQUEST: + sprintf (str, "%s\n", Agent_Status_Get (Tab_Request [Idx].Reply_Stat [i].Status, Tab_Request [Idx].Reply_Stat [i].Debug)); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_INFO_REQUEST: + sprintf (str, "%d événement(s) traité(s) / %d message(s) système(s) reçu(s)\n", Tab_Request [Idx].Reply_Stat [i].Cpt_Event, Tab_Request [Idx].Reply_Stat [i].Cpt_System); + strcat (Answer, str); + break; + + case MSGD_SYSTEM_TRACEON_REQUEST: + strcat (Answer, "mode trace activé\n"); + break; + + case MSGD_SYSTEM_TRACEOFF_REQUEST: + strcat (Answer, "mode trace désactivé\n"); + break; + + default: + break; + } + } + } + + if (Type == MSGD_SYSTEM_SHUTDOWN_REQUEST) strcat (Answer, "Superviseur terminé.\n"); + + /* On répond à tous les messages en attente sur cette requête */ + + Msg_List = Tab_Request [Idx].Msg_List; + + ND_Node_First_Get (Msg_List, &Node); + + while (Node) + { + MSGT_Message * Msg = (MSGT_Message *)(Node->Value); + char * Msg_Data = Msg->Data; + + ND_Node_Next_Get (Node, &Next_Node); + + ND_Node_Remove (Node); + + /* On remplit le champ de données du message */ + + if (strlen (Answer) >= Msg->Size) + { + sprintf (Debug_Trace, "attention, le message (%d octets) n'est pas assez long pour contenir toute la réponse (%d caractères)\n", Msg->Size, strlen (Answer)); + Info_Trace (); + strncpy (Msg_Data, Answer, Msg->Size - 1); + Msg_Data [Msg->Size - 1] = (char)0; + } + else strcpy (Msg_Data, Answer); + + /* On renvoie le message à son envoyeur */ + + MSG_Message_Reply (Msg); + + /* Message suivant */ + + Node = Next_Node; + } + + /* On réinitialise les données concernant la requête */ + + memset (&(Tab_Request [Idx]), 0, sizeof (Waiting_Request)); + Tab_Request [Idx].Msg_List = Msg_List; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Procédure appelée lorsqu'un timeout expire */ +/*--------------------------------------------------------------------------------------------------*/ +void Timeout_Handle ( int signum ) +{ + unsigned int i, Older; + int Found = FALSE; + + /* On recherche la requête la plus ancienne */ + + for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++) + { + if (Date_IsSet (Tab_Request [i].Request_Date) && (Found == FALSE || Date_Compare (Tab_Request [i].Request_Date, Tab_Request [Older].Request_Date))) + { + Found = TRUE; + Older = i; + } + } + + /* On répond à la requête */ + + if (Found == TRUE) + { + strcpy (Debug_Trace, "timeout expiré => réponse à la requête la plus ancienne"); + Info_Trace (); + Request_Answer (Older); + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Redémarrage automatique d'un agent tombé */ +/*--------------------------------------------------------------------------------------------------*/ +void Agent_Restart ( int signum ) +{ + unsigned int Found, i; + pid_t Child_Pid; +#ifdef LINUX + int Child_Info; +#else + siginfo_t Child_Info; +#endif + unsigned int Restart; + + /* On réinitialise le trap du signal SIGCHLD */ + + signal (SIGCHLD, Agent_Restart); + + /* On récupère les informations concernant le processus fils qui est tombé */ + +#ifdef LINUX + Child_Pid = waitpid (-1, &Child_Info, WNOHANG); + + if (Child_Pid == -1) + { + sprintf (Debug_Trace, "impossible de récupérer les informations concernant un processus fils tombé"); + Info_Trace (); + return; + } +#else + if (waitid (P_ALL, 0, &Child_Info, WEXITED) == -1) + { + sprintf (Debug_Trace, "impossible de récupérer les informations concernant un processus fils tombé"); + Info_Trace (); + return; + } + + Child_Pid = Child_Info.si_pid; +#endif + + /* On recherche l'agent correspondant au process fils tombé */ + + Found = FALSE; + i = 0; + while (i < Nb_Agent && Found == FALSE) + { + if (Tab_Agent [i].GivenUp == FALSE) + { + if (Tab_Agent [i].Pid == Child_Pid) Found = TRUE; + else i++; + + } + else i++; + } + + if (Found == FALSE) + { + sprintf (Debug_Trace, "impossible de trouver l'agent correspondant au processus fils %ld tombé", Child_Pid); + Info_Trace (); + return; + } + + /* Analyse de la raison pour laquelle le fils est tombé */ + +#ifdef LINUX + if (WIFEXITED(Child_Info)) +#else + if (Child_Info.si_code == CLD_EXITED) +#endif + { + /* L'agent s'est terminé tout seul (comme un grand !!!) : on ne le relance pas */ + + Restart = FALSE; + +#ifdef LINUX + sprintf (Debug_Trace, "détection agent n°%d terminé avec code retour %d", i + 1, WEXITSTATUS(Child_Info)); +#else + sprintf (Debug_Trace, "détection agent n°%d terminé avec code retour %d", i + 1, Child_Info.si_status); +#endif + Info_Trace (); + } +#ifdef LINUX + else if (WIFSIGNALED(Child_Info) && WTERMSIG(Child_Info) == SIGKILL) +#else + else if (Child_Info.si_code == CLD_KILLED) +#endif + { + /* L'agent a à priori été tué volontairement : on ne le relance donc pas */ + + Restart = FALSE; + + sprintf (Debug_Trace, "détection agent n°%d tué", i + 1); + Info_Trace (); + + } +#ifdef LINUX + else if WIFSIGNALED(Child_Info) +#else + else if (Child_Info.si_code == CLD_DUMPED) +#endif + { + /* L'agent s'est terminé anormallement : on essaie de relancer l'agent */ + + Restart = TRUE; + +#ifdef LINUX + sprintf (Debug_Trace, "détection agent n°%d tombé suite à signal %d", i + 1, WTERMSIG(Child_Info)); +#else + sprintf (Debug_Trace, "détection agent n°%d tombé suite à signal %d", i + 1, Child_Info.si_status); +#endif + Info_Trace (); + } + else Restart = TRUE; + + if (Restart == TRUE) + { + /* Une tentative de relance a-t'elle déjà été lancée ? */ + + if (Tab_Agent [i].Restarted == TRUE) + { + sprintf (Debug_Trace, "abandon de l'agent n°%d", i + 1); + Info_Trace (); + Tab_Agent [i].GivenUp = TRUE; + Nb_GivenUp ++; + } + else + { + /* On redémarre l'agent */ + + sprintf (Debug_Trace, "relance de l'agent n°%d", i + 1); + Info_Trace (); + + Agent_Start (i + 1); + + Tab_Agent [i].Restarted = TRUE; + } + } + else + { + sprintf (Debug_Trace, "abandon de l'agent n°%d", i + 1); + Info_Trace (); + Tab_Agent [i].GivenUp = TRUE; + Nb_GivenUp ++; + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Envoi d'un message à un agent */ +/*--------------------------------------------------------------------------------------------------*/ +int Agent_Msg_Send ( unsigned int Num_Agent, unsigned int Type, int Priority ) +{ + MSGT_Message * Msg; + char Agent_Port_Name [256]; + MSGT_Port * Agent_Port; + + /* Ouverture du port de messages privé d'un agent dont on connait le numéro */ + + sprintf (Agent_Port_Name, "Agent_%d_port", Num_Agent); + + if (MSG_Port_Open (Agent_Port_Name, &Agent_Port, MSGD_OPEN) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible d'ouvrir le port de messages \"%s\"", Agent_Port_Name); + Info_Trace (); + return KO; + } + + /* Création du message (de la taille d'un message système standard du superviseur aux agents) */ + + if (MSG_Message_Alloc (&Msg, sizeof (Agent_Stat)) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible de créer un message destiné à l'agent n°%d", Num_Agent); + Info_Trace (); + MSG_Port_Close (Agent_Port, MSGD_CLOSE); + return KO; + } + + /* Initialisation des données du message */ + + memset (Msg->Data, 0, Msg->Size); + + /* Configuration du type de message */ + + if (MSG_Message_Config (Msg, MSGD_CONFIG_TYPE, Type) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible de configurer le type du message destiné à l'agent n°%d", Num_Agent); + Info_Trace (); + MSG_Message_Free (Msg); + MSG_Port_Close (Agent_Port, MSGD_CLOSE); + return KO; + } + + /* Configuration de la priorité du message */ + + if (MSG_Message_Config (Msg, MSGD_CONFIG_PRIORITY, Priority) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible de configurer la priorité du message destiné à l'agent n°%d", Num_Agent); + Info_Trace (); + MSG_Message_Free (Msg); + MSG_Port_Close (Agent_Port, MSGD_CLOSE); + return KO; + } + + /* Envoi du message avec demande d'accusé réception dans le port du superviseur */ + + if (MSG_Message_Send (MSGD_SUPERVISOR_PORT_NAME, Agent_Port, Msg) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible d'envoyer le message destiné à l'agent n°%d", Num_Agent); + Info_Trace (); + MSG_Message_Free (Msg); + MSG_Port_Close (Agent_Port, MSGD_CLOSE); + return KO; + } + + /* Fermeture du port de messages d'envoi */ + + if (MSG_Port_Close (Agent_Port, MSGD_CLOSE) != MSGS_OK) + { + sprintf (Debug_Trace, "impossible de fermer le port de messages de l'agent n°%d", Num_Agent); + Info_Trace (); + MSG_Message_Free (Msg); + MSG_Port_Close (Agent_Port, MSGD_CLOSE); + return KO; + } + + return OK; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Démarrage d'un agent */ +/*--------------------------------------------------------------------------------------------------*/ +int Agent_Start ( unsigned int Num_Agent ) +{ + pid_t Agent_Pid; + + if (Num_Agent > NB_MAX_AGENT) + { + strcpy (Debug_Trace, "Limite maximale du nombre d'agents atteinte"); + Info_Trace (); + return KO; + } + + /* On crée un process fils */ + +#ifdef LINUX + Agent_Pid = fork (); +#else + /* Sous Solaris, il faut utiliser la fonction fork1() pour supporter le multi-thread */ + + Agent_Pid = fork1 (); +#endif + + if (Agent_Pid != 0) + { + /* Code pour le processus père (superviseur) : on référence le processus fils comme nouvel agent */ + + Tab_Agent [Num_Agent - 1].Pid = Agent_Pid; + Tab_Agent [Num_Agent - 1].Restarted = FALSE; + Tab_Agent [Num_Agent - 1].GivenUp = FALSE; + sprintf (Debug_Trace, "lancement de l'agent n°%d", Num_Agent); + Info_Trace (); + } + else + { + char sNum_Agent [10]; + + sprintf (sNum_Agent, "%d", Num_Agent); + + /* Code pour le processus fils (agent) */ + + if (Debug == TRUE) + execlp (AGENT_PATH, AGENT_PATH, "-id", sNum_Agent, "--debug", NULL, NULL); + else + execlp (AGENT_PATH, AGENT_PATH, "-id", sNum_Agent, NULL, NULL); + + sprintf (Debug_Trace, "erreur lors du lancement de l'agent n°%d (execl: errno %d)", Num_Agent, errno); + Info_Trace (); + + exit (KO); + } + + return OK; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Affichage sur la sortie standard d'erreur d'un message généré par le superviseur */ +/*--------------------------------------------------------------------------------------------------*/ +void Info_Trace ( void ) +{ + time_t dts; + struct tm * dt; + char Current_Date [25]; + + if (Debug) + { + /* Récupère la date courante */ + + time (&dts); + dt = localtime (&dts); + sprintf (Current_Date, "%02d/%02d/%04d %02d:%02d:%02d", dt->tm_mday, dt->tm_mon + 1, dt->tm_year + 1900, dt->tm_hour, dt->tm_min, dt->tm_sec); + + fprintf (stderr, "[%s] Superviseur : %s\n", Current_Date, Debug_Trace); + } +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Affiche le statut du superviseur */ +/*--------------------------------------------------------------------------------------------------*/ +char * Status_Get ( void ) +{ + static char Status_Str [256]; + + sprintf (Status_Str, "Timeout = %d sec / Trace = %s", Timeout, Debug == TRUE ? "On" : "Off"); + + return Status_Str; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Affiche le statut d'un agent */ +/*--------------------------------------------------------------------------------------------------*/ +char * Agent_Status_Get ( unsigned int Agent_Status, unsigned int Agent_Debug ) +{ + static char Status_Str [256]; + + sprintf (Status_Str, "Statut = %s / Trace = %s", Agent_Status == ACTIVE ? "actif" : "stoppé", Agent_Debug == TRUE ? "On" : "Off"); + + return Status_Str; +} + +/*--------------------------------------------------------------------------------------------------*/ +/* Manager d'une liste de messages en attente sur une requête */ +/*--------------------------------------------------------------------------------------------------*/ +NDT_Status Request_List_Manager (va_list Args) +{ + return NDS_OK; +}