3182 lines
108 KiB
C
3182 lines
108 KiB
C
/* Utilisation des API sans vérification des arguments */
|
|
|
|
#define ND_MODE 1
|
|
#define SM_MODE 1
|
|
#define DS_MODE 1
|
|
|
|
#include <libmsg.h>
|
|
|
|
VER_INFO_EXPORT(libmsg,"$Revision: 1.1 $", "$Name: $",__FILE__,"$Author: smas $")
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS PUBLIQUES */
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS OPTIMISEES (MSG_MODE = 1) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Teste si la librairie a été ouverte */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_IsOpen_I ( void )
|
|
{
|
|
if (!MSG_Base) return MSGS_NO;
|
|
|
|
return MSGS_YES;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Permet d'indiquer à la librairie qu'un signal a été reçu. */
|
|
/* */
|
|
/* NB : cette fonction sera appelée par l'utilisateur pour éviter que le */
|
|
/* processus se bloque sur une attente de message malgré la réception de signal */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Signal_I ( void )
|
|
{
|
|
MSG_Signal_Received = TRUE;
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ouverture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Instance : numéro de l'instance de la librairie */
|
|
/* (I) Context : contexte d'utilisation de la librairie */
|
|
/* (I) Open_Mode : mode d'ouverture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Open_I ( int Instance, const char * Context, MSGT_Flags Open_Mode )
|
|
{
|
|
MSGT_Status rc;
|
|
int Locked;
|
|
int DS_Debug_Mode = DSD_DEBUG_NONE;
|
|
|
|
/* Définition du mode debug */
|
|
|
|
if (Open_Mode & MSGD_DEBUG)
|
|
{
|
|
MSG_stderr = stderr;
|
|
DS_Debug_Mode = DSD_DEBUG;
|
|
}
|
|
else if (Open_Mode & MSGD_DEBUG_ALL)
|
|
{
|
|
MSG_stderr = stderr;
|
|
DS_Debug_Mode = DSD_DEBUG_ALL;
|
|
}
|
|
|
|
/* Ouverture de la librairie LIBDATASTR */
|
|
|
|
rc = DS_Library_Open (Instance, Context, DS_Debug_Mode);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to open the LIBDATASTR library");
|
|
MSG_Error_Print();
|
|
return rc;
|
|
}
|
|
|
|
/* Accès aux ressources partagées de la librairie */
|
|
|
|
if (Open_Mode & MSGD_CREATE)
|
|
{
|
|
/* On vérifie que le processus courant n'a pas déjà ouvert la librairie */
|
|
|
|
if (MSG_Open_Counter > 0)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : the current process has already opened the LIBMSG library");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/* Création de la base LIBMSG */
|
|
|
|
rc = SM_Heap_Open (MSG_Name_Prefix (MSG_BASE_HEAP_NAME), &MSG_Base_Heap, MSG_BASE_HEAP_SEGMENT_SIZE, SMD_CREATE | SMD_WRITE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to create the heap for the LIBMSG base");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
return rc;
|
|
}
|
|
|
|
rc = SM_Chunk_Alloc (MSG_Base_Heap, sizeof (MSGT_Base), (void **)&MSG_Base);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to allocate memory for the LIBMSG base structure");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
MSG_Base = NULL;
|
|
return rc;
|
|
}
|
|
|
|
/* Création de la liste des ports de messages (en fait c'est un arbre) */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (MSG_PORT_LIST_NAME), &(MSG_Base->Port_List), NDD_DS_TREE | NDD_MN_AUTO_EQU, MSG_FILE_MANAGER, MSG_PORT_LIST_SEGMENT_SIZE, DSD_CREATE, TRUE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to create the base message port list");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
MSG_Base = NULL;
|
|
return rc;
|
|
}
|
|
else strcpy (MSG_Base->Port_List->Manager, "MSG_Base_Port_List_Manager");
|
|
|
|
/* Création du heap dans lequel seront alloués les messages */
|
|
|
|
rc = SM_Heap_Open (MSG_Name_Prefix (MSG_MESSAGE_HEAP_NAME), &MSG_Message_Heap, MSG_MESSAGE_HEAP_SEGMENT_SIZE, SMD_CREATE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to create the message heap");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
MSG_Base = NULL;
|
|
return rc;
|
|
}
|
|
|
|
/* Verrouillage de la base LIBMSG en lecture */
|
|
|
|
rc = SM_Heap_Lock (MSG_Base_Heap, SMD_READ, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to lock the LIBMSG base for reading");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
MSG_Base = NULL;
|
|
return rc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SMT_DSH * DSH;
|
|
NDT_Root * Root;
|
|
|
|
/* On n'accède aux ressources que lors de la première ouverture */
|
|
|
|
if (MSG_Open_Counter == 0)
|
|
{
|
|
/* Ouverture de la base LIBMSG en lecture */
|
|
|
|
rc = SM_Heap_Open (MSG_Name_Prefix (MSG_BASE_HEAP_NAME), &MSG_Base_Heap, 0, SMD_OPEN | SMD_READ, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to open the heap for the LIBMSG base");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
return rc;
|
|
}
|
|
|
|
DSH = MSG_Base_Heap->MHH->DSR->Head->Value;
|
|
|
|
/* La structure de la base se trouve dans le premier chunk du premier segment du heap */
|
|
|
|
MSG_Base = (MSGT_Base *)((size_t)(DSH->Start) + sizeof (NDT_Node) + sizeof (SMT_Chunk));
|
|
|
|
/* Ouverture de la liste des ports de messages */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (MSG_PORT_LIST_NAME), &Root, NULL, NULL, 0, SMD_OPEN, TRUE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to open the base port list");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Ouverture du heap dans lequel seront alloués les messages */
|
|
|
|
rc = SM_Heap_Open (MSG_Name_Prefix (MSG_MESSAGE_HEAP_NAME), &MSG_Message_Heap, 0, SMD_OPEN, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Open : unable to open the message heap");
|
|
MSG_Error_Print ();
|
|
DS_Library_Close ();
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Mise à jour du compteur d'ouverture */
|
|
|
|
MSG_Open_Counter++;
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Close_Mode : mode de fermeture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Close_I ( MSGT_Flags Close_Mode )
|
|
{
|
|
MSGT_Status rc;
|
|
|
|
if (Close_Mode == MSGD_DESTROY)
|
|
{
|
|
/* Destruction de la liste des ports de messages */
|
|
|
|
rc = DS_DataStruct_Close (MSG_Base->Port_List, DSD_DESTROY);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to destroy the base port list");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Destruction du heap contenant les messages */
|
|
|
|
rc = SM_Heap_End (MSG_Name_Prefix (MSG_MESSAGE_HEAP_NAME));
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to destroy the message heap");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Destruction du heap contenant la structure de base */
|
|
|
|
rc = SM_Heap_End (MSG_Name_Prefix (MSG_BASE_HEAP_NAME));
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to destroy the heap of the base structure");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
MSG_Base = NULL;
|
|
|
|
/* Réinitialisation du compteur d'ouverture */
|
|
|
|
MSG_Open_Counter = 0;
|
|
}
|
|
else
|
|
{
|
|
/* On ne libère les ressources que lors de la dernière fermeture */
|
|
|
|
if (MSG_Open_Counter == 1)
|
|
{
|
|
/* Fermeture de la liste des ports de messages */
|
|
|
|
rc = DS_DataStruct_Close (MSG_Base->Port_List, DSD_CLOSE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to close the base port list");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Fermeture du heap contenant les messages */
|
|
|
|
rc = SM_Heap_Close (MSG_Message_Heap);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to close the message heap");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Fermeture du heap contenant la structure de base */
|
|
|
|
rc = SM_Heap_Close (MSG_Base_Heap);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : unable to close the heap of the base structure");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
MSG_Base = NULL;
|
|
|
|
/* Mise à jour du compteur d'ouverture */
|
|
|
|
MSG_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 */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Stderr_Set_I ( FILE * Out )
|
|
{
|
|
MSG_stderr = Out;
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Affichage des ressources de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Out : Flux de sortie de l'affichage */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Dump_I ( FILE * Out )
|
|
{
|
|
MSGT_Status rc;
|
|
size_t Total_Size = 0;
|
|
unsigned int Nb_Message;
|
|
int Locked;
|
|
|
|
/* Verrouillage du heap des messages en lecture */
|
|
|
|
rc = SM_Heap_Lock (MSG_Message_Heap, SMD_READ, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Dump : unable to lock the message heap for reading");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Récupération de la taille totale des messages */
|
|
|
|
ND_DataStruct_Traverse (MSG_Message_Heap->MHH->ACR, NDD_CMD_SUM_VALUES, &Total_Size);
|
|
|
|
Nb_Message = MSG_Message_Heap->MHH->ACR->Node_Number;
|
|
Total_Size -= Nb_Message * sizeof (NDT_Node);
|
|
|
|
/* Déverrouillage du heap des messages */
|
|
|
|
rc = SM_Heap_Unlock (MSG_Message_Heap);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Dump : unable to unlock the message heap");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Affichage des informations sur la base de la LIBMSG */
|
|
|
|
fprintf (Out, "LIBMSG :\n\t- %ld message port(s)\n\t- %d message(s) : %d byte(s)\n", MSG_Base->Port_List->Node_Number, Nb_Message, Total_Size);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Test de l'existence d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Name : nom du port de messages */
|
|
/* (O) Port : adresse d'un pointeur sur le port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Exist_I ( const char * Name, MSGT_Port ** Port )
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Node * Node;
|
|
MSGT_Port Tmp_Port;
|
|
|
|
*Port = NULL;
|
|
|
|
strcpy (Tmp_Port.Name, Name);
|
|
|
|
rc = DS_Node_Find (MSG_Base->Port_List, &Node, (void *)&Tmp_Port, NULL);
|
|
if (DS_ERROR(rc)) return rc;
|
|
|
|
if (rc == DSS_KO) return MSGS_NO;
|
|
|
|
*Port = (MSGT_Port *)(Node->Value);
|
|
|
|
return MSGS_YES;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création/ouverture d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Name : nom du port de messages */
|
|
/* (O) Port : adresse d'un pointeur sur le port de messages */
|
|
/* (I) Open_Mode : mode d'ouverture du port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Open_I ( const char * Name, MSGT_Port ** Port, MSGT_Flags Open_Mode )
|
|
{
|
|
MSGT_Status rc;
|
|
union semun Sem_Ctl;
|
|
|
|
*Port = NULL;
|
|
|
|
/* Recherche du nom du port dans la liste des ports référencés par la base */
|
|
|
|
rc = MSG_Port_Exist_I (Name, Port);
|
|
if (MSG_ERROR(rc)) return rc;
|
|
if (rc == MSGS_YES)
|
|
{
|
|
NDT_Root * Root;
|
|
|
|
if (!MSGD_MSK_OPEN (Open_Mode))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the message port \"%s\" already exists and (Open_Mode & MSGD_OPEN) is false", Name);
|
|
MSG_Error_Print ();
|
|
|
|
*Port = NULL;
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/* On ouvre le heap du port qui contient la queue de messages et la liste de sémaphores */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (Name), &Root, NULL, NULL, 0, DSD_OPEN, TRUE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to open the main data structure of port \"%s\"", Name);
|
|
MSG_Error_Print ();
|
|
|
|
*Port = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
if (!MSGD_MSK_CREATE (Open_Mode))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the message port \"%s\" does not exist and (Open_Mode & MSGD_CREATE) is false", Name);
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/* Création du port dans la liste des ports référencés par la base */
|
|
|
|
rc = DS_Value_Alloc (MSG_Base->Port_List, (void **)Port, Name);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to create message port \"%s\"", Name);
|
|
MSG_Error_Print ();
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Création du sémaphore permettant le verrouillage du port */
|
|
|
|
(*Port)->LockSemID = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL);
|
|
if ((*Port)->LockSemID == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case ENOMEM:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the amount of memory is not sufficient to create a new semaphore");
|
|
break;
|
|
|
|
case ENOSPC:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the number of semaphores exceeds the system-imposed limit");
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unknown error (%d) while creating a semaphore", errno);
|
|
break;
|
|
}
|
|
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Initialisation du sémaphore à 1 (aucun verrou) */
|
|
|
|
Sem_Ctl.val = 1;
|
|
if (semctl ((*Port)->LockSemID, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to initialize the value of the listen semaphore %d", (*Port)->LockSemID);
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Création du sémaphore permettant l'écoute du port */
|
|
|
|
(*Port)->ListenSemID = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL);
|
|
if ((*Port)->ListenSemID == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case ENOMEM:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the amount of memory is not sufficient to create a new semaphore");
|
|
break;
|
|
|
|
case ENOSPC:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the number of semaphores exceeds the system-imposed limit");
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unknown error (%d) while creating a semaphore", errno);
|
|
break;
|
|
}
|
|
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Initialisation du sémaphore à 0 */
|
|
|
|
Sem_Ctl.val = 0;
|
|
if (semctl ((*Port)->ListenSemID, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to initialize the value of the listen semaphore %d", (*Port)->ListenSemID);
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Création de la queue de messages du port */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (Name), &((*Port)->MsgQueue), NDD_DS_LIST | NDD_MN_ORDERED, MSG_FILE_MANAGER, MSG_PORT_SEGMENT_SIZE, DSD_CREATE, TRUE);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to create a message queue for port \"%s\"", Name);
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
else strcpy ((*Port)->MsgQueue->Manager, "MSG_MessageQueue_Manager");
|
|
|
|
/* Création de la liste des sémaphores des listes de ports qui sont à l'écoute du port (dans le même heap que pour la queue de messages) */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (Name), &((*Port)->SemList), NDD_DS_LIST | NDD_MN_FIFO, MSG_FILE_MANAGER, 0, DSD_NEW, TRUE);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to create the list of semaphore for port \"%s\"", Name);
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
else strcpy ((*Port)->SemList->Manager, "MSG_Semaphore_List_Manager");
|
|
|
|
/* Ajout du port à la liste des ports référencés par la base */
|
|
|
|
rc = DS_Value_Add (MSG_Base->Port_List, (void *)(*Port));
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : unable to add message port \"%s\" to the base list", Name);
|
|
MSG_Error_Print ();
|
|
|
|
/* Suppression du port précédement créé */
|
|
|
|
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
|
|
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Configuration d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Tag : type de configuration */
|
|
/* (I) ... : données de configuration */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Config_I ( MSGT_Port * Port, MSGT_Config Tag, ... )
|
|
{
|
|
MSGT_Status rc;
|
|
va_list Args;
|
|
|
|
if (Tag == MSGD_CONFIG_SIZE)
|
|
{
|
|
size_t Size;
|
|
|
|
va_start (Args, Tag);
|
|
Size = va_arg (Args, size_t);
|
|
|
|
if (Size != MSGD_UNLIMITED)
|
|
{
|
|
/* On vérifie que la taille limite n'est pas déjà dépassée */
|
|
|
|
if ((size_t)(Port->MsgQueue->Node_Number) > Size)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : the limit has already been exceeded");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
}
|
|
|
|
MSG_Port_Lock (Port, MSGD_WRITE);
|
|
|
|
Port->Size = Size;
|
|
va_end (Args);
|
|
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_MSGQUEUE)
|
|
{
|
|
NDT_DataStruct_Type Type;
|
|
|
|
va_start (Args, Tag);
|
|
Type = va_arg (Args, NDT_DataStruct_Type);
|
|
|
|
MSG_Port_Lock (Port, MSGD_WRITE);
|
|
|
|
rc = DS_DataStruct_Convert (Port->MsgQueue, Type);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : unable to configure the message queue of port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
}
|
|
|
|
va_end (Args);
|
|
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : unknown config type %d", Tag);
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Close_Mode : mode de fermeture du port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Close_I ( MSGT_Port * Port, MSGT_Flags Close_Mode )
|
|
{
|
|
MSGT_Status rc;
|
|
|
|
if (Close_Mode == MSGD_CLOSE)
|
|
{
|
|
rc = DS_DataStruct_Close (Port->MsgQueue, DSD_CLOSE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
/* Pour la fermeture du port, on se contente de fermer sa data structure principale */
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Close : unable to close the message queue of port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
else if (Close_Mode == MSGD_DESTROY)
|
|
{
|
|
/* On ne prend pas la peine de vérifier si le port est référencé par une liste de ports (tant pis pour elle) */
|
|
|
|
/* Suppression du port de la liste des ports référencés par la base */
|
|
|
|
rc = DS_Value_Remove (MSG_Base->Port_List, Port, (void **)&Port);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Close : unable to remove port \"%s\" from the base list", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
rc = DS_Value_Free (MSG_Base->Port_List, Port);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Close : unable to free port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Verrouillage d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Mode : type de verrouillage */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Lock_I ( MSGT_Port * Port, MSGT_Flags Mode )
|
|
{
|
|
if (MSGD_MSK_READ(Mode)) return MSG_ShareLock_Set (Port->LockSemID);
|
|
|
|
if (MSGD_MSK_WRITE(Mode)) return MSG_ExclusiveLock_Set (Port->LockSemID);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Déverrouillage d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Mode : type de verrou à enlever */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Unlock_I ( MSGT_Port * Port, MSGT_Flags Mode )
|
|
{
|
|
if (MSGD_MSK_READ(Mode)) return MSG_ShareLock_Release (Port->LockSemID);
|
|
|
|
if (MSGD_MSK_WRITE(Mode)) return MSG_ExclusiveLock_Release (Port->LockSemID);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création/ouverture d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) PortList : adresse d'un pointeur sur la liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Open_I ( MSGT_PortList ** PortList )
|
|
{
|
|
MSGT_Status rc;
|
|
union semun Sem_Ctl;
|
|
|
|
/* Allocation de la structure */
|
|
|
|
*PortList = (MSGT_PortList *) malloc (sizeof(MSGT_PortList));
|
|
if (!*PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : unable to allocate memory for the message port list");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRMEM;
|
|
}
|
|
|
|
/* Création en local d'une liste de ports */
|
|
|
|
rc = ND_DataStruct_Open (&((*PortList)->Root), NDD_DS_LIST | NDD_MN_FIFO, NULL, NULL, NULL, TRUE);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : unable to open the node structure");
|
|
MSG_Error_Print ();
|
|
free (*PortList);
|
|
|
|
return rc;
|
|
}
|
|
else strcpy((*PortList)->Root->Manager, "MSG_PortList_Manager");
|
|
|
|
/* Création du sémaphore pour l'écoute sur la liste de ports */
|
|
|
|
(*PortList)->ListenSemID = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL);
|
|
if ((*PortList)->ListenSemID == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case ENOMEM:
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : the amount of memory is not sufficient to create a new semaphore");
|
|
break;
|
|
|
|
case ENOSPC:
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : the number of semaphores exceeds the system-imposed limit");
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : unknown error (%d) while creating a semaphore", errno);
|
|
break;
|
|
}
|
|
|
|
MSG_Error_Print ();
|
|
|
|
ND_DataStruct_Close((*PortList)->Root);
|
|
free (*PortList);
|
|
|
|
return MSGS_ERRSEM;
|
|
}
|
|
|
|
/* Initialisation du sémaphore à 0 */
|
|
|
|
Sem_Ctl.val = 0;
|
|
if (semctl ((*PortList)->ListenSemID, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : unable to initialize the value of the listen semaphore %d", (*PortList)->ListenSemID);
|
|
MSG_Error_Print ();
|
|
|
|
semctl ((*PortList)->ListenSemID, 0, IPC_RMID, Sem_Ctl);
|
|
ND_DataStruct_Close((*PortList)->Root);
|
|
free (*PortList);
|
|
|
|
return MSGS_ERRSEM;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ajout d'un port de messages à une liste de ports */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/* (I) Port : pointeur sur un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Port_Add_I ( MSGT_PortList * PortList, MSGT_Port * Port )
|
|
{
|
|
MSGT_Status rc;
|
|
union semun Sem_Ctl, Tmp_Ctl;
|
|
|
|
/* Ajout du port à la liste */
|
|
|
|
rc = ND_Value_Add (PortList->Root, (void *)Port);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Add : unable to add a value to the port list node structure");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Mise à jour du sémaphore de la liste : pour cela, on verrouille temporairement le port écouté */
|
|
|
|
MSG_Port_Lock (Port, MSGD_READ);
|
|
|
|
Sem_Ctl.val = semctl (PortList->ListenSemID, 0, GETVAL, Tmp_Ctl) + Port->MsgQueue->Node_Number;
|
|
if (semctl (PortList->ListenSemID, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : unable to update the value of semaphore %d", PortList->ListenSemID);
|
|
MSG_Error_Print ();
|
|
|
|
ND_Value_Remove (PortList->Root, Port, (void **)&Port);
|
|
ND_Value_Free (PortList->Root, Port);
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
|
|
return MSGS_ERRSEM;
|
|
}
|
|
|
|
/* On référence la présente liste au niveau du port que l'on écoute */
|
|
|
|
rc = ND_Value_Add (Port->SemList, (void *)PortList->ListenSemID);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Add : unable to reference the current list to the port");
|
|
MSG_Error_Print ();
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
return rc;
|
|
}
|
|
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retrait d'un port de messages d'une liste de ports */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/* (I) Port : pointeur sur un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Port_Remove_I ( MSGT_PortList * PortList, MSGT_Port * Port )
|
|
{
|
|
MSGT_Status rc;
|
|
union semun Sem_Ctl, Tmp_Ctl;
|
|
|
|
/* Retrait du port de la liste : pour cela, on verrouille temporairement le port */
|
|
|
|
MSG_Port_Lock (Port, MSGD_READ);
|
|
|
|
rc = ND_Value_Remove (PortList->Root, Port, (void **)&Port);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : unable to remove a port from the port list");
|
|
MSG_Error_Print ();
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
return rc;
|
|
}
|
|
|
|
rc = ND_Value_Free (PortList->Root, Port);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : unable to free a port of the port list");
|
|
MSG_Error_Print ();
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
return rc;
|
|
}
|
|
|
|
/* On met à jour le sémaphore de la liste de ports */
|
|
|
|
Sem_Ctl.val = semctl (PortList->ListenSemID, 0, GETVAL, Tmp_Ctl) - Port->MsgQueue->Node_Number;
|
|
if (Sem_Ctl.val < 0) Sem_Ctl.val = 0;
|
|
if (semctl (PortList->ListenSemID, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : unable to update the value of the semaphore %d", PortList->ListenSemID);
|
|
MSG_Error_Print ();
|
|
rc = MSGS_ERRSEM;
|
|
}
|
|
|
|
/* On retire la référence que le port avait sur la présente liste de ports */
|
|
|
|
rc = ND_Value_Remove (Port->SemList, (void *)PortList->ListenSemID, (void **)&(PortList->ListenSemID));
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : unable to remove the current port list from the port");
|
|
MSG_Error_Print ();
|
|
}
|
|
|
|
rc = ND_Value_Free (Port->SemList, (void *)PortList->ListenSemID);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : unable to free the current port list");
|
|
MSG_Error_Print ();
|
|
}
|
|
|
|
MSG_Port_Unlock (Port, MSGD_READ);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Suppression d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Close_I ( MSGT_PortList * PortList )
|
|
{
|
|
MSGT_Status rc;
|
|
union semun Sem_Ctl;
|
|
NDT_Node * Node;
|
|
|
|
/* On détache tous les ports de la liste */
|
|
|
|
ND_Node_First_Get (PortList->Root, &Node);
|
|
while (Node)
|
|
{
|
|
NDT_Node * Next_Node;
|
|
MSGT_Port * Port = (MSGT_Port *)(Node->Value);
|
|
|
|
ND_Node_Next_Get (Node, &Next_Node);
|
|
|
|
rc = MSG_PortList_Port_Remove (PortList, Port);
|
|
if (MSG_ERROR(rc)) return rc;
|
|
|
|
Node = Next_Node;
|
|
}
|
|
|
|
/* Destruction de la liste de ports */
|
|
|
|
ND_DataStruct_Close (PortList->Root);
|
|
|
|
/* Suppression du sémaphore de la liste de ports */
|
|
|
|
semctl (PortList->ListenSemID, 0, IPC_RMID, Sem_Ctl);
|
|
|
|
/* Désallocation de la structure */
|
|
|
|
free (PortList);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ecoute d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur une liste de ports de messages */
|
|
/* (I) Type : type du message à récupérer */
|
|
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
|
|
/* (I) Flags : paramètres de réception */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Listen_I ( MSGT_PortList * PortList, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags)
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Node * Node;
|
|
int End = FALSE;
|
|
int Found = FALSE;
|
|
int Empty = TRUE;
|
|
|
|
/*
|
|
L'écoute d'une liste de ports est basée sur le
|
|
même algorithme que pour l'écoute d'un seul port.
|
|
|
|
Pour cela, la liste de ports possède un sémaphore qui est
|
|
incrémentée lorsqu'un nouveau message arrive sur l'un des ports.
|
|
*/
|
|
|
|
MSG_Signal_Received = FALSE; /* pour indiquer qu'aucun signal n'a encore interrompu l'attente */
|
|
|
|
do /* Boucle principale */
|
|
{
|
|
/* On opère sur le sémaphore pour indiquer qu'on essaye de retirer un message */
|
|
|
|
rc = MSG_Semaphore_Operate (PortList->ListenSemID, MSG_SemOp_Receive, 1);
|
|
|
|
switch ((int)rc)
|
|
{
|
|
case MSGS_OK:
|
|
case MSGS_ERRNOWAIT:
|
|
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
return MSGS_ERRSIG;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen : unable to operate on the listen port list semaphore (ID=%d)", PortList->ListenSemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Recherche d'un message du type demandé dans l'un des ports de la liste */
|
|
|
|
ND_Node_First_Get (PortList->Root, &Node);
|
|
while (Node && Found == FALSE)
|
|
{
|
|
MSGT_Port * Port = (MSGT_Port *)(Node->Value);
|
|
|
|
/* On écoute chaque port de la liste sans attente */
|
|
|
|
rc = MSG_Message_Receive_I (Port, Type, Msg, MSGD_NO_WAIT);
|
|
|
|
switch ((int)rc)
|
|
{
|
|
case MSGS_OK:
|
|
Found = TRUE;
|
|
break;
|
|
|
|
case MSGS_NO_MSG:
|
|
ND_Node_Next_Get (Node, &Node);
|
|
break;
|
|
|
|
case MSGS_BAD_TYPE:
|
|
Empty = FALSE;
|
|
ND_Node_Next_Get (Node, &Node);
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
return MSGS_ERRSIG;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen : unable to remove a message from one of the list's port");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
/* Un message a-t'il été trouvé ? */
|
|
|
|
if (Found == TRUE)
|
|
{
|
|
/* Fin de la boucle de recherche */
|
|
|
|
End = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* En mode sans attente, on sort directement avec un code retour spécifique */
|
|
|
|
if (Flags == MSGD_NO_WAIT) return (Empty == TRUE ? MSGS_NO_MSG : MSGS_BAD_TYPE);
|
|
|
|
/* Sinon, on se met en attente sur le sémaphore */
|
|
|
|
if (MSG_Signal_Received == TRUE) return MSGS_ERRSIG;
|
|
|
|
rc = MSG_Semaphore_Operate (PortList->ListenSemID, MSG_SemOp_Listen, 2);
|
|
|
|
/* Réveil du process : un message nouveau est-il arrivé sur l'un des ports de la liste ? */
|
|
|
|
switch ((int)rc)
|
|
{
|
|
case MSGS_OK:
|
|
|
|
/* On boucle à nouveau sur la recherche de message */
|
|
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
return MSGS_ERRSIG;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen: unable to operate on the listen port list semaphore (ID=%d)", PortList->ListenSemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
}
|
|
} while (End ==FALSE);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Msg : adresse d'un pointeur sur le message */
|
|
/* (I) Size : taille en octets des données du message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Alloc_I ( MSGT_Message ** Msg, size_t Size )
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Node * Node;
|
|
int Locked;
|
|
|
|
*Msg = NULL;
|
|
|
|
/* On verrouille le heap des messages en écriture */
|
|
|
|
rc = SM_Heap_Lock (MSG_Message_Heap, SMD_WRITE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : unable to lock the message heap for writing");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Le noeud du message est alloué en même temps que le message */
|
|
|
|
rc = SM_Chunk_Alloc (MSG_Message_Heap, sizeof (NDT_Node) + sizeof (MSGT_Message) + Size, (void **)&Node);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : unable to allocate memory for a new message");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
Node->Value = (void *)((size_t)(Node) + sizeof (NDT_Node));
|
|
|
|
*Msg = (MSGT_Message *)(Node->Value);
|
|
|
|
(*Msg)->From [0] = (char)0;
|
|
(*Msg)->Via [0] = (char)0;
|
|
(*Msg)->To [0] = (char)0;
|
|
(*Msg)->Type = MSGD_DEFAULT_TYPE;
|
|
(*Msg)->Priority = MSGD_DEFAULT_PRIORITY;
|
|
(*Msg)->Data = (void *)((size_t)(*Msg) + sizeof (MSGT_Message));
|
|
(*Msg)->Size = Size;
|
|
(*Msg)->Swap = NULL;
|
|
|
|
/* On déverrouille le heap des messages */
|
|
|
|
rc = SM_Heap_Unlock (MSG_Message_Heap);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : unable to unlock the message heap for writing");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Configuration d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur un message */
|
|
/* (I) Tag : type de configuration */
|
|
/* (I) ... : données de configuration */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Config_I ( MSGT_Message * Msg, MSGT_Config Tag, ... )
|
|
{
|
|
va_list Args;
|
|
|
|
if (Tag == MSGD_CONFIG_PRIORITY)
|
|
{
|
|
int Priority;
|
|
|
|
va_start (Args, Tag);
|
|
Priority = va_arg (Args, int);
|
|
|
|
if (Priority < MSGD_SYSTEM_HIGH_PRIORITY || Priority > MSGD_SYSTEM_LOW_PRIORITY)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : incorrect value (%d) for a priority", Priority);
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
Msg->Priority = Priority;
|
|
|
|
va_end (Args);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_TYPE)
|
|
{
|
|
unsigned int Type;
|
|
|
|
va_start (Args, Tag);
|
|
Type = va_arg (Args, int);
|
|
|
|
if (Type == MSGD_NO_TYPE)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : incorrect value (%d) for a message type", Type);
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*
|
|
Petite sécurité pour le messages système PING :
|
|
|
|
La taille du message doit être suffisante pour contenir
|
|
4 dates (mises à jour automatiquement par la librairie) :
|
|
|
|
- date d'envoi du PING REQUEST
|
|
- date de réception du PING REQUEST
|
|
- date d'envoi du PING REPLY
|
|
- date de réception du PING REPLY
|
|
*/
|
|
|
|
if (Type == MSGD_SYSTEM_PING_REQUEST)
|
|
{
|
|
if (Msg->Size < sizeof (MSGT_PingData))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : the message size (%d byte(s)) must be greater than %d bytes for a PING message", Msg->Size, sizeof (MSGT_PingData));
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
}
|
|
|
|
Msg->Type = Type;
|
|
|
|
va_end (Args);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : unknown config type %d", Tag);
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Destruction d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Free_I ( MSGT_Message * Msg )
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Node * Node;
|
|
int Locked;
|
|
|
|
/* On verrouille le heap des messages en écriture */
|
|
|
|
rc = SM_Heap_Lock (MSG_Message_Heap, SMD_WRITE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Free : unable to lock the message heap for writing");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Le noeud du message est désalloué en même temps que le message */
|
|
|
|
Node = (NDT_Node *)((size_t)Msg - sizeof (NDT_Node));
|
|
|
|
rc = SM_Chunk_Free (MSG_Message_Heap, Node);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Free : unable to free memory which had been allocated for the message");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* On déverrouille le heap des messages */
|
|
|
|
rc = SM_Heap_Unlock (MSG_Message_Heap);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Free : unable to unlock the message heap for writing");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Envoi d'un message dans un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) From : nom du port de messages de l'envoyeur */
|
|
/* (I) To : pointeur sur le port de messages destinataire */
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Send_I ( const char * From, MSGT_Port * To, MSGT_Message * Msg )
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Node * Node;
|
|
char To_Name [25];
|
|
struct timeval * Current_Time;
|
|
|
|
/*
|
|
Pour l'envoi d'un PING (message système), on modifie le contenu
|
|
du message en y mettant la date courante d'envoi.
|
|
*/
|
|
|
|
if (Msg->Type == MSGD_SYSTEM_PING_REQUEST)
|
|
{
|
|
/* Petite sécurité : on vérifie que le port de l'envoyeur est renseigné ! */
|
|
|
|
if (From && !strlen (From))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to send a ping request message when the sender port is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
Current_Time = &(((MSGT_PingData *)(Msg->Data))->Snd1);
|
|
gettimeofday (Current_Time, NULL);
|
|
}
|
|
else if (Msg->Type == MSGD_SYSTEM_PING_REPLY)
|
|
{
|
|
Current_Time = &(((MSGT_PingData *)(Msg->Data))->Snd2);
|
|
gettimeofday (Current_Time, NULL);
|
|
}
|
|
|
|
/* Verrouillage du port de messages en écriture */
|
|
|
|
rc = MSG_Port_Lock (To, MSGD_WRITE);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to lock port \"%s\" for writing", To->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* On vérifie qu'il reste de la place dans le port de messages */
|
|
|
|
if (To->Size != MSGD_UNLIMITED && (unsigned int)(To->MsgQueue->Node_Number) == To->Size)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : port \"%s\" is full", To->Name);
|
|
MSG_Error_Print ();
|
|
|
|
MSG_Port_Unlock (To, MSGD_WRITE);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Mise à jour des champs du message */
|
|
|
|
strcpy (To_Name, To->Name);
|
|
|
|
if (From && strlen (From))
|
|
{
|
|
if (!strlen (Msg->From)) strcpy (Msg->From, From);
|
|
|
|
strcpy (Msg->Via, From);
|
|
}
|
|
|
|
strcpy (Msg->To, To_Name);
|
|
|
|
/* Ajout du message = ajout du noeud (le noeud est déjà créé dans la liste de messages gérée par la base) */
|
|
|
|
Node = (NDT_Node *)((size_t)(Msg) - sizeof (NDT_Node));
|
|
|
|
rc = DS_Node_Add (To->MsgQueue, Node);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to add the message node to the node structure");
|
|
MSG_Error_Print ();
|
|
|
|
MSG_Port_Unlock (To, MSGD_WRITE);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* On met à jour le sémaphore d'écoute du port de messages */
|
|
|
|
rc = MSG_Semaphore_Operate (To->ListenSemID, MSG_SemOp_Add, 1);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to operate on semaphore %d", To->ListenSemID);
|
|
MSG_Error_Print ();
|
|
|
|
DS_Node_Remove (Node);
|
|
MSG_Port_Unlock (To, MSGD_WRITE);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* On met à jour les sémaphores de toutes les liste de ports qui sont à l'écoute du port de messages */
|
|
|
|
ND_Node_First_Get (To->SemList, &Node);
|
|
|
|
while (Node)
|
|
{
|
|
int SemID = (int)(Node->Value);
|
|
|
|
rc = MSG_Semaphore_Operate (SemID, MSG_SemOp_Add, 1);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to operate on semaphore %d", SemID);
|
|
MSG_Error_Print ();
|
|
|
|
/* On continue quand même : peut-être un processus a-t'il oublié de nous avertir qu'il fermait sa liste de ports (quel idiot !) */
|
|
}
|
|
|
|
ND_Node_Next_Get (Node, &Node);
|
|
}
|
|
|
|
/* Déverrouillage du port de messages en écriture */
|
|
|
|
rc = MSG_Port_Unlock (To, MSGD_WRITE);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : unable to unlock port \"%s\" which had been locked for writing", To->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Réception d'un message dans un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Type : type du message à récupérer */
|
|
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
|
|
/* (I) Flags : paramètres de réception */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Receive_I ( MSGT_Port * Port, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags)
|
|
{
|
|
NDT_Node * Node;
|
|
MSGT_Status rc;
|
|
struct timeval * Current_Time;
|
|
int End = FALSE;
|
|
int Found = FALSE;
|
|
int Empty = TRUE;
|
|
|
|
/* L'écoute d'un port de messagee est basée sur l'algorithme suivant :
|
|
|
|
- le processus commence par consulter la queue de messages (après verrouillage exclusif)
|
|
- s'il ne trouve rien qui lui convienne, il se met en attente sur le sémaphore attaché au port.
|
|
|
|
NB : le sémaphore du port est incrémenté à chaque fois qu'un nouveau message est présent sur le port.
|
|
*/
|
|
|
|
MSG_Signal_Received = FALSE; /* pour indiquer qu'aucun signal n'a encore interrompu l'attente */
|
|
|
|
do /* Boucle principale */
|
|
{
|
|
/* Verrouillage du port de messages en écriture */
|
|
|
|
rc = MSG_Port_Lock (Port, MSGD_WRITE);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to lock port \"%s\" for writing", Port->Name);
|
|
MSG_Error_Print ();
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* On opère sur le sémaphore pour indiquer qu'on essaye de retirer un message */
|
|
|
|
rc = MSG_Semaphore_Operate (Port->ListenSemID, MSG_SemOp_Receive, 1);
|
|
|
|
switch ((int)rc)
|
|
{
|
|
case MSGS_OK:
|
|
break;
|
|
|
|
case MSGS_ERRNOWAIT:
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
return MSGS_ERRSIG;
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to operate on the listen port semaphore (ID=%d)", Port->ListenSemID);
|
|
MSG_Error_Print ();
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
return rc;
|
|
}
|
|
|
|
/* Recherche d'un message du type demandé */
|
|
|
|
if (Type == MSGD_NO_TYPE)
|
|
{
|
|
/* Si aucun type n'est demandé en particulier, on prend le premier de la liste */
|
|
|
|
rc = DS_Node_First_Get (Port->MsgQueue, &Node);
|
|
if (DS_ERROR(rc)) return rc;
|
|
if (rc == DSS_OK) Found = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DS_Node_First_Get (Port->MsgQueue, &Node);
|
|
while (Node && Found != TRUE)
|
|
{
|
|
unsigned int Msg_Type = ((MSGT_Message *)(Node->Value))->Type;
|
|
|
|
Empty = FALSE;
|
|
|
|
if (Type == MSGD_SYSTEM_GENERIC && MSGD_IS_SYSTEM (Msg_Type))
|
|
{
|
|
/* Recherche d'un message système quelconque */
|
|
|
|
Found = TRUE;
|
|
}
|
|
else if (Msg_Type == Type)
|
|
{
|
|
/* Recherche d'un message d'un type particulier */
|
|
|
|
Found = TRUE;
|
|
}
|
|
else DS_Node_Next_Get (Node, &Node);
|
|
}
|
|
}
|
|
|
|
/* Un message a-t'il été trouvé ? */
|
|
|
|
if (Found == TRUE)
|
|
{
|
|
*Msg = (MSGT_Message *)(Node->Value);
|
|
|
|
/* Retrait du message = retrait du noeud (le noeud est géré dans la liste de messages référencés par la base) */
|
|
|
|
rc = DS_Node_Remove (Node);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to remove the message node from the node structure");
|
|
MSG_Error_Print ();
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
return rc;
|
|
}
|
|
|
|
/* Fin de la boucle de recherche */
|
|
|
|
End = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* Déverrouillage du port de messages en écriture */
|
|
|
|
rc = MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to unlock port \"%s\" which had been locked for writing", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* En mode sans attente, on sort directement avec un code retour spécifique */
|
|
|
|
if (Flags == MSGD_NO_WAIT) return (Empty == TRUE ? MSGS_NO_MSG : MSGS_BAD_TYPE);
|
|
|
|
/* Sinon, on se met en attente sur le sémaphore */
|
|
|
|
if (MSG_Signal_Received == TRUE) return MSGS_ERRSIG;
|
|
|
|
rc = MSG_Semaphore_Operate (Port->ListenSemID, MSG_SemOp_Listen, 2);
|
|
|
|
/* Réveil du process : un message nouveau est-il arrivé ? */
|
|
|
|
switch ((int)rc)
|
|
{
|
|
case MSGS_OK:
|
|
|
|
/* On boucle sur la recherche de message */
|
|
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
return MSGS_ERRSIG;
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to operate on the listen port semaphore (ID=%d)", Port->ListenSemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
} while (End == FALSE);
|
|
|
|
/*
|
|
Puisqu'un message a effectivement été retiré, on met à jour les sémaphores
|
|
de toutes les listes de ports qui seraient à l'écoute de ce port de messages.
|
|
*/
|
|
|
|
ND_Node_First_Get (Port->SemList, &Node);
|
|
while (Node)
|
|
{
|
|
int SemID = (int)(Node->Value);
|
|
int semrc = MSG_Semaphore_Operate (SemID, MSG_SemOp_Receive, 1);
|
|
|
|
switch (semrc)
|
|
{
|
|
case MSGS_OK:
|
|
break;
|
|
|
|
case MSGS_ERRNOWAIT:
|
|
|
|
/* Cas de la liste de ports sur laquelle le processus s'est précisément réveillé */
|
|
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
return MSGS_ERRSIG;
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
/* Peut-être un processus a-t'il oublié de nous avertir qu'il fermait sa liste de ports (quelle négligence !) */
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to operate on one of the semaphore list (Id=%d)", SemID);
|
|
MSG_Error_Print ();
|
|
|
|
/* On continue quand même */
|
|
}
|
|
|
|
ND_Node_Next_Get (Node, &Node);
|
|
}
|
|
|
|
/* Déverrouillage du port de messages en écriture */
|
|
|
|
rc = MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to unlock port \"%s\" which had been locked for writing", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
Pour la réception d'un PING (REQUEST ou REPLY), on modifie le contenu
|
|
du message en y mettant la date courante de réception.
|
|
*/
|
|
|
|
if ((*Msg)->Type == MSGD_SYSTEM_PING_REQUEST)
|
|
{
|
|
Current_Time = &(((MSGT_PingData *)((*Msg)->Data))->Rcv1);
|
|
gettimeofday (Current_Time, NULL);
|
|
|
|
/*
|
|
Pour un ping request, on va jusqu'à renvoyer automatiquement
|
|
le message à son envoyeur, puis relancer l'écoute sur le port.
|
|
Ainsi, le ping devient parfaitement transparent pour l'utilisateur.
|
|
*/
|
|
|
|
rc = MSG_Message_Reply (*Msg);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : unable to reply the PING REQUEST message");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSG_Message_Receive (Port, Type, Msg, Flags);
|
|
}
|
|
else if ((*Msg)->Type == MSGD_SYSTEM_PING_REPLY)
|
|
{
|
|
Current_Time = &(((MSGT_PingData *)((*Msg)->Data))->Rcv2);
|
|
gettimeofday (Current_Time, NULL);
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retour à l'envoyeur d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Reply_I ( MSGT_Message * Msg )
|
|
{
|
|
MSGT_Status rc;
|
|
MSGT_Port * To;
|
|
|
|
/* On vérifie que le port de l'envoyeur est bien défini */
|
|
|
|
if (strlen (Msg->Via))
|
|
{
|
|
/* Ouverture du port de messages de l'envoyeur */
|
|
|
|
rc = MSG_Port_Open_I (Msg->Via, &To, MSGD_OPEN);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : unable to open port \"%s\"", Msg->Via);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Sinon, on répond dans le port de messages par défaut */
|
|
|
|
rc = MSG_Port_Exist (MSGD_DEFAULT_PORT_NAME, &To);
|
|
if (rc == MSGS_YES) strcpy (Msg->Via, MSGD_DEFAULT_PORT_NAME);
|
|
else
|
|
{
|
|
if (MSG_ERROR(rc)) return rc;
|
|
|
|
/* S'il n'est pas défini, on supprime le message */
|
|
|
|
rc = MSG_Message_Free_I (Msg);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : unable to free the message");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Pour les messages système de type REQUEST, on change le type en REPLY.
|
|
Pour les messages utilisateur, c'est à l'utilisateur de changer le type si nécessaire.
|
|
*/
|
|
|
|
switch (Msg->Type)
|
|
{
|
|
case MSGD_SYSTEM_PING_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_PING_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_STOP_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_STOP_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_CONTINUE_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_CONT_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_RESTART_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_RESTART_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_SHUTDOWN_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_SHUTDOWN_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_STATUS_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_STATUS_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_INFO_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_INFO_REPLY;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_TRACEON_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_TRACEON_REPLY ;
|
|
break;
|
|
|
|
case MSGD_SYSTEM_TRACEOFF_REQUEST:
|
|
Msg->Type = MSGD_SYSTEM_TRACEOFF_REPLY;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
/* Envoi du message dans le port de l'envoyeur */
|
|
|
|
rc = MSG_Message_Send_I (Msg->To, To, Msg);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : unable to send the message to port \"%s\"", To->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retour à l'initiateur d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Return_I ( MSGT_Message * Msg )
|
|
{
|
|
MSGT_Status rc;
|
|
MSGT_Port * To;
|
|
|
|
/* On vérifie que le port de l'initiateur est bien défini */
|
|
|
|
if (strlen (Msg->From))
|
|
{
|
|
/* Ouverture du port de messages de l'initiateur */
|
|
|
|
rc = MSG_Port_Open_I (Msg->From, &To, MSGD_OPEN);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Return : unable to open port \"%s\"", Msg->Via);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Sinon, on répond dans le port de messages par défaut */
|
|
|
|
rc = MSG_Port_Exist_I (MSGD_DEFAULT_PORT_NAME, &To);
|
|
if (rc == MSGS_YES) strcpy (Msg->From, MSGD_DEFAULT_PORT_NAME);
|
|
else
|
|
{
|
|
if (MSG_ERROR(rc)) return rc;
|
|
|
|
/* S'il n'est pas défini, on supprime le message */
|
|
|
|
rc = MSG_Message_Free_I (Msg);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Return : unable to free the message");
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
}
|
|
|
|
/* Ouverture du port de messages de l'initiateur */
|
|
|
|
rc = MSG_Port_Open_I (Msg->From, &To, MSGD_OPEN);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : unable to open port \"%s\"", Msg->From);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Envoi du message dans le port de l'initiateur */
|
|
|
|
rc = MSG_Message_Send_I (Msg->To, To, Msg);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Return : unable to send the message to port \"%s\"", To->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS SECURISEES (MSG_MODE = 0) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Permet d'indiquer à la librairie qu'un signal a été reçu. */
|
|
/* */
|
|
/* NB : cette fonction sera appelée par l'utilisateur pour éviter que le */
|
|
/* processus se bloque sur une attente de message malgré la réception de signal */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Signal_C ( void )
|
|
{
|
|
return MSG_Library_Signal_I ();
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Teste si la librairie a été ouverte */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_IsOpen_C ( void )
|
|
{
|
|
return MSG_Library_IsOpen_I ();
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ouverture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Instance : numéro de l'instance de la librairie */
|
|
/* (I) Context : contexte d'utilisation de la librairie */
|
|
/* (I) Open_Mode : mode d'ouverture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Open_C ( int Instance, const char * Context, MSGT_Flags Open_Mode )
|
|
{
|
|
return MSG_Library_Open_I (Instance, Context, Open_Mode);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Close_Mode : mode de fermeture de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Close_C ( MSGT_Flags Close_Mode )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Close : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_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 */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Stderr_Set_C ( FILE * Out )
|
|
{
|
|
return MSG_Library_Stderr_Set_I (Out);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Affichage des ressources de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Out : Flux de sortie de l'affichage */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Library_Dump_C ( FILE * Out )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Dump : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Out)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Library_Dump : the out stream is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Library_Dump_I (Out);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Test de l'existence d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Name : nom du port de messages */
|
|
/* (O) Port : adresse d'un pointeur sur le port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Exist_C ( const char * Name, MSGT_Port ** Port )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Exist : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Name)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Exist : the port name is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Exist : the port address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Port_Exist_I (Name, Port);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création/ouverture d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Name : nom du port de messages */
|
|
/* (O) Port : adresse d'un pointeur sur le port de messages */
|
|
/* (I) Open_Mode : mode d'ouverture du port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Open_C ( const char * Name, MSGT_Port ** Port, MSGT_Flags Open_Mode )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Name)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the port name is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Open : the port address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Port_Open_I (Name, Port, Open_Mode);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Configuration d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Tag : type de configuration */
|
|
/* (I) ... : données de configuration */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Config_C ( MSGT_Port * Port, MSGT_Config Tag, ... )
|
|
{
|
|
MSGT_Status rc;
|
|
va_list Args;
|
|
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_SIZE)
|
|
{
|
|
size_t Size;
|
|
|
|
va_start (Args, Tag);
|
|
Size = va_arg (Args, size_t);
|
|
|
|
if (Size != MSGD_UNLIMITED)
|
|
{
|
|
/* On vérifie que la taille limite n'est pas déjà dépassée */
|
|
|
|
if ((size_t)(Port->MsgQueue->Node_Number) > Size)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : the limit has already been exceeded");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
}
|
|
|
|
MSG_Port_Lock (Port, MSGD_WRITE);
|
|
|
|
Port->Size = Size;
|
|
va_end (Args);
|
|
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_MSGQUEUE)
|
|
{
|
|
NDT_DataStruct_Type Type;
|
|
|
|
va_start (Args, Tag);
|
|
Type = va_arg (Args, NDT_DataStruct_Type);
|
|
|
|
MSG_Port_Lock (Port, MSGD_WRITE);
|
|
|
|
rc = DS_DataStruct_Convert (Port->MsgQueue, Type);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : unable to configure the message queue of port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
}
|
|
|
|
va_end (Args);
|
|
|
|
MSG_Port_Unlock (Port, MSGD_WRITE);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Config : unknown config type %d", Tag);
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Close_Mode : mode de fermeture du port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Close_C ( MSGT_Port * Port, MSGT_Flags Close_Mode )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Close : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Close : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Port_Close_I (Port, Close_Mode);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Verrouillage d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Mode : type de verrouillage */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Lock_C ( MSGT_Port * Port, MSGT_Flags Mode )
|
|
{
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Lock : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Port_Lock_I (Port, Mode);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Déverrouillage d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Mode : type de verrou à enlever */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Port_Unlock_C ( MSGT_Port * Port, MSGT_Flags Mode )
|
|
{
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Port_Unlock : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Port_Unlock_I (Port, Mode);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création/ouverture d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) PortList : adresse d'un pointeur sur la liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Open_C ( MSGT_PortList ** PortList )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Open : the port list address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_PortList_Open_I (PortList);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ajout d'un port de messages à une liste de ports */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/* (I) Port : pointeur sur un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Port_Add_C ( MSGT_PortList * PortList, MSGT_Port * Port )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Add : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Add : the message port list is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Add : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_PortList_Port_Add_I (PortList, Port);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retrait d'un port de messages d'une liste de ports */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/* (I) Port : pointeur sur un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Port_Remove_C ( MSGT_PortList * PortList, MSGT_Port * Port )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : the message port list is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Port_Remove : the message port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_PortList_Port_Remove_I (PortList, Port);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Suppression d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur la liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Close_C ( MSGT_PortList * PortList )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Close : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Close : the message port list is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_PortList_Close_I (PortList);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ecoute d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) PortList : pointeur sur une liste de ports de messages */
|
|
/* (I) Type : type du message à récupérer */
|
|
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
|
|
/* (I) Flags : paramètres de réception */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_PortList_Listen_C ( MSGT_PortList * PortList, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!PortList)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen : the message port list is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_PortList_Listen : the message address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_PortList_Listen_I (PortList, Type, Msg, Flags);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Création d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Msg : adresse d'un pointeur sur le message */
|
|
/* (I) Size : taille en octets des données du message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Alloc_C ( MSGT_Message ** Msg, size_t Size )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : the message address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Size)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Alloc : the allocation size must be > 0");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Alloc_I (Msg, Size);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Configuration d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur un message */
|
|
/* (I) Tag : type de configuration */
|
|
/* (I) ... : données de configuration */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Config_C ( MSGT_Message * Msg, MSGT_Config Tag, ... )
|
|
{
|
|
va_list Args;
|
|
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_PRIORITY)
|
|
{
|
|
int Priority;
|
|
|
|
va_start (Args, Tag);
|
|
Priority = va_arg (Args, int);
|
|
|
|
if (Priority < MSGD_SYSTEM_HIGH_PRIORITY || Priority > MSGD_SYSTEM_LOW_PRIORITY)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : incorrect value (%d) for a priority", Priority);
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
Msg->Priority = Priority;
|
|
|
|
va_end (Args);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
if (Tag == MSGD_CONFIG_TYPE)
|
|
{
|
|
unsigned int Type;
|
|
|
|
va_start (Args, Tag);
|
|
Type = va_arg (Args, int);
|
|
|
|
if (Type == MSGD_NO_TYPE)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : incorrect value (%d) for a message type", Type);
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*
|
|
Petite sécurité pour le messages système PING :
|
|
|
|
La taille du message doit être suffisante pour contenir
|
|
4 dates (mises à jour automatiquement par la librairie) :
|
|
|
|
- date d'envoi du PING REQUEST
|
|
- date de réception du PING REQUEST
|
|
- date d'envoi du PING REPLY
|
|
- date de réception du PING REPLY
|
|
*/
|
|
|
|
if (Type == MSGD_SYSTEM_PING_REQUEST)
|
|
{
|
|
if (Msg->Size < sizeof (MSGT_PingData))
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : the message size (%d byte(s)) must be greater than %d bytes for a PING message", Msg->Size, sizeof (MSGT_PingData));
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
}
|
|
|
|
Msg->Type = Type;
|
|
|
|
va_end (Args);
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Config : unknown config type %d", Tag);
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Destruction d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Free_C ( MSGT_Message * Msg )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Free : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Free : the message is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Free_I (Msg);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Envoi d'un message dans un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) From : nom du port de messages de l'envoyeur */
|
|
/* (I) To : pointeur sur le port de messages destinataire */
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Send_C ( const char * From, MSGT_Port * To, MSGT_Message * Msg )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!To)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : the target port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Send : the message is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Send_I (From, To, Msg);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Réception d'un message dans un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Port : pointeur sur le port de messages */
|
|
/* (I) Type : type du message à récupérer */
|
|
/* (O) Msg : adresse d'un pointeur sur le message à recevoir */
|
|
/* (I) Flags : paramètres de réception */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Receive_C ( MSGT_Port * Port, unsigned int Type, MSGT_Message ** Msg, MSGT_Flags Flags)
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Port)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : the port is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Receive : the message address is undefined");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Receive_I (Port, Type, Msg, Flags);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retour à l'envoyeur d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Reply_C ( MSGT_Message * Msg )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Reply : the message is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Reply_I (Msg);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Retour à l'initiateur d'un message */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Msg : pointeur sur le message */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Message_Return_C ( MSGT_Message * Msg )
|
|
{
|
|
if (!MSG_Base)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Return : the library is not open");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
if (!Msg)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Message_Return : the message is null");
|
|
MSG_Error_Print ();
|
|
return MSGS_ERRAPI;
|
|
}
|
|
|
|
return MSG_Message_Return_I (Msg);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS PRIVEES */
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Manager de la liste des ports de messages référencés par la base */
|
|
/*------------------------------------------------------------------------------*/
|
|
NDT_Status MSG_Base_Port_List_Manager (va_list Args)
|
|
{
|
|
MSGT_Status rc;
|
|
NDT_Command Command = (NDT_Command) va_arg (Args, NDT_Command);
|
|
|
|
if (Command == NDD_CMD_MAKE_VALUE)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
MSGT_Port ** Port = va_arg (Args, MSGT_Port **);
|
|
va_list Args_Value = va_arg (Args, va_list);
|
|
char * Name = va_arg (Args_Value, char *);
|
|
|
|
*Port = NULL;
|
|
|
|
rc = DS_Alloc (Root, sizeof (MSGT_Port), (void **)Port);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Base_Port_List_Manager : unable to allocate a new port");
|
|
MSG_Error_Print ();
|
|
return NDS_KO;
|
|
}
|
|
|
|
strcpy ((*Port)->Name, Name);
|
|
(*Port)->ListenSemID = 0;
|
|
(*Port)->LockSemID = 0;
|
|
(*Port)->MsgQueue = NULL;
|
|
(*Port)->SemList = NULL;
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_PRINT_VALUE)
|
|
{
|
|
MSGT_Port * Port = (MSGT_Port *) va_arg (Args, void *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
MSGT_Port * Tmp_Port ;
|
|
|
|
/* Pour afficher le port de messages, il faut préalablement l'ouvrir */
|
|
|
|
rc = MSG_Port_Open_I (Port->Name, &Tmp_Port, MSGD_OPEN);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Base_Port_List_Manager : unable to open port \"%s\" for printing", Port->Name);
|
|
MSG_Error_Print ();
|
|
return NDS_KO;
|
|
}
|
|
|
|
fprintf (Out, "Port \"%s\" :\n\t- status = %s\n\t- queue = %ld message%c\n\t- listen semaphore = %d", Port->Name, MSG_LockStatus_Get (Port->LockSemID), Port->MsgQueue->Node_Number, Port->MsgQueue->Node_Number > 1 ? 's' : ' ', Port->ListenSemID);
|
|
if (Port->Size == MSGD_UNLIMITED)
|
|
fprintf (Out, "\n\t- max size = unlimited");
|
|
else
|
|
fprintf (Out, "\n\t- max size = %d", Port->Size);
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_PRINT_INFO)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
char * Root_Type;
|
|
DST_RootDesc * RootDesc;
|
|
|
|
switch ((int)(Root->Type & NDD_DS_MSK))
|
|
{
|
|
case NDD_DS_LIST :
|
|
|
|
switch ((int)(Root->Type & NDD_MN_MSK))
|
|
{
|
|
case NDD_MN_ORDERED : Root_Type = "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 ports = %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_DELETE_VALUE)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
MSGT_Port * Port = (MSGT_Port *) va_arg (Args, void *);
|
|
union semun Sem_Ctl;
|
|
|
|
/* Suppression de la queue de messages du port */
|
|
|
|
if (Port->MsgQueue)
|
|
{
|
|
NDT_Root * MSQ_Root;
|
|
NDT_Node * Node;
|
|
|
|
/* Avant de supprimer la queue de messages, on l'ouvre au cas où cela n'aurait pas été fait */
|
|
|
|
rc = DS_DataStruct_Open (MSG_Name_Prefix (Port->Name), &MSQ_Root, NULL, NULL, 0, DSD_OPEN, TRUE);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Base_Port_List_Manager : unable to open the message queue of port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
/* Les messages étant alloués indépendament de la queue de messages, on les détruit à part */
|
|
|
|
ND_Node_First_Get (Port->MsgQueue, &Node);
|
|
|
|
while (Node)
|
|
{
|
|
NDT_Node * Next_Node;
|
|
MSGT_Message * Msg = (MSGT_Message *)(Node->Value);
|
|
|
|
ND_Node_Next_Get (Node, &Next_Node);
|
|
|
|
/* Détachement du noeud de la data structure */
|
|
|
|
ND_Node_Remove (Node);
|
|
|
|
/* Désallocation du message (et de son noeud) */
|
|
|
|
MSG_Message_Free (Msg);
|
|
|
|
Node = Next_Node;
|
|
}
|
|
|
|
/* On peut maintenant détruire la data structure proprement dite */
|
|
|
|
rc = DS_DataStruct_Close (Port->MsgQueue, DSD_DESTROY);
|
|
if (rc != DSS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_Base_Port_List_Manager : unable to destroy the message queue of port \"%s\"", Port->Name);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
/* Suppression des sémaphores */
|
|
|
|
if (Port->ListenSemID) semctl (Port->ListenSemID, 0, IPC_RMID, Sem_Ctl);
|
|
|
|
if (Port->LockSemID) semctl (Port->LockSemID, 0, IPC_RMID, Sem_Ctl);
|
|
|
|
/* Désallocation de la structure du port */
|
|
|
|
DS_Free (Root, Port);
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_COMP_VALUE)
|
|
{
|
|
MSGT_Port * Port1, * Port2;
|
|
long comp;
|
|
|
|
Port1 = (MSGT_Port *) va_arg (Args, void *);
|
|
Port2 = (MSGT_Port *) va_arg (Args, void *);
|
|
|
|
va_end (Args);
|
|
comp = strcmp (Port1->Name, Port2->Name);
|
|
|
|
if (comp < 0) return NDS_LOWER;
|
|
if (comp > 0) return NDS_GREATER;
|
|
return NDS_EQUAL;
|
|
}
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Manager d'une liste de ports de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
NDT_Status MSG_PortList_Manager (va_list Args)
|
|
{
|
|
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
|
|
|
|
if (Command == NDD_CMD_PRINT_VALUE)
|
|
{
|
|
MSGT_Port * Port = (MSGT_Port *) va_arg (Args, void *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
|
|
/* Le port de messages est censé être déjà ouvert par le procsesus courant */
|
|
|
|
fprintf (Out, "Port \"%s\" :\n\t- status = %s\n\t- queue = %ld message%c\n\t- listen semaphore = %d", Port->Name, MSG_LockStatus_Get (Port->LockSemID), Port->MsgQueue->Node_Number, Port->MsgQueue->Node_Number > 1 ? 's' : ' ', Port->ListenSemID);
|
|
if (Port->Size == MSGD_UNLIMITED) fprintf (Out, "\n\t- max size = unlimited\n");
|
|
else fprintf (Out, "\n\t- max size = %d\n", Port->Size);
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_PRINT_INFO)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
char * Root_Type;
|
|
DST_RootDesc * RootDesc;
|
|
|
|
switch ((int)(Root->Type & NDD_DS_MSK))
|
|
{
|
|
case NDD_DS_LIST :
|
|
|
|
switch ((int)(Root->Type & NDD_MN_MSK))
|
|
{
|
|
case NDD_MN_ORDERED : Root_Type = "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 ports = %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)
|
|
{
|
|
MSGT_Port * Port1, * Port2;
|
|
long comp;
|
|
|
|
Port1 = (MSGT_Port *) va_arg (Args, void *);
|
|
Port2 = (MSGT_Port *) va_arg (Args, void *);
|
|
|
|
va_end (Args);
|
|
comp = strcmp (Port1->Name, Port2->Name);
|
|
|
|
if (comp < 0) return NDS_LOWER;
|
|
if (comp > 0) return NDS_GREATER;
|
|
return NDS_EQUAL;
|
|
}
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Manager d'une liste de sémaphores */
|
|
/*------------------------------------------------------------------------------*/
|
|
NDT_Status MSG_Semaphore_List_Manager (va_list Args)
|
|
{
|
|
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
|
|
|
|
if (Command == NDD_CMD_PRINT_VALUE)
|
|
{
|
|
int SemID = (int) va_arg (Args, void *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
|
|
fprintf (Out, "Semaphore %d", SemID);
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_PRINT_INFO)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
char * Root_Type;
|
|
DST_RootDesc * RootDesc;
|
|
|
|
switch ((int)(Root->Type & NDD_DS_MSK))
|
|
{
|
|
case NDD_DS_LIST :
|
|
|
|
switch ((int)(Root->Type & NDD_MN_MSK))
|
|
{
|
|
case NDD_MN_ORDERED : Root_Type = "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 sémaphores = %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)
|
|
{
|
|
int Sem1, Sem2;
|
|
long comp;
|
|
|
|
Sem1 = (int) va_arg (Args, void *);
|
|
Sem2 = (int) va_arg (Args, void *);
|
|
|
|
va_end (Args);
|
|
comp = Sem1 - Sem2;
|
|
|
|
if (comp < 0) return NDS_LOWER;
|
|
if (comp > 0) return NDS_GREATER;
|
|
return NDS_EQUAL;
|
|
}
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Manager d'une queue de messages associée à un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
NDT_Status MSG_MessageQueue_Manager (va_list Args)
|
|
{
|
|
NDT_Command Command = (NDT_Command)va_arg(Args, NDT_Command);
|
|
|
|
if (Command == NDD_CMD_PRINT_VALUE)
|
|
{
|
|
MSGT_Message * Msg = (MSGT_Message *) va_arg(Args, void *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
unsigned int i, j;
|
|
|
|
fprintf (Out, "Message :\n\t- Type = %d\n\t- Priority = %d\n\t- From = %s\n\t- Via = %s\n\t- To = %s\n\t- Size = %d\n\t- Data = \"", Msg->Type, Msg->Priority, Msg->From, Msg->Via, Msg->To, Msg->Size);
|
|
j = (Msg->Size > 50 ? 50 : Msg->Size);
|
|
for (i = 0; i < j; i++)
|
|
{
|
|
char c;
|
|
|
|
c = *(char *)((size_t)(Msg->Data) + i);
|
|
switch ((int)c)
|
|
{
|
|
case '\0': fprintf (Out, "\\0"); break;
|
|
case '\n': fprintf (Out, "\\r"); break;
|
|
case '\t': fprintf (Out, "\\t"); break;
|
|
default : fprintf (Out, "%c", c);
|
|
}
|
|
}
|
|
if (i < Msg->Size) fprintf (Out, "...");
|
|
fprintf (Out, "\"");
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
if (Command == NDD_CMD_PRINT_INFO)
|
|
{
|
|
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
|
FILE * Out = va_arg (Args, FILE *);
|
|
char * Root_Type;
|
|
DST_RootDesc * RootDesc;
|
|
|
|
switch ((int)(Root->Type & NDD_DS_MSK))
|
|
{
|
|
case NDD_DS_LIST :
|
|
|
|
switch ((int)(Root->Type & NDD_MN_MSK))
|
|
{
|
|
case NDD_MN_ORDERED : Root_Type = "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 messages = %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)
|
|
{
|
|
MSGT_Message * Msg1, * Msg2;
|
|
long comp;
|
|
|
|
Msg1 = (MSGT_Message *) va_arg(Args, void *);
|
|
Msg2 = (MSGT_Message *) va_arg(Args, void *);
|
|
|
|
va_end (Args);
|
|
|
|
/* On trie les messages :
|
|
- par ordre inverse de priorité
|
|
- par ordre d'arrivée
|
|
*/
|
|
|
|
comp = Msg1->Priority - Msg2->Priority;
|
|
|
|
if (comp > 0) return NDS_LOWER;
|
|
if (comp < 0) return NDS_GREATER;
|
|
return NDS_EQUAL;
|
|
}
|
|
|
|
return NDS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Routine d'affichage d'un message d'erreur */
|
|
/*------------------------------------------------------------------------------*/
|
|
void MSG_Error_Print ( void )
|
|
{
|
|
if (MSG_stderr) fprintf (MSG_stderr, "%s\n", MSG_Error_Msg);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pose d'un verrou en lecture */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_ShareLock_Set (int SemID)
|
|
{
|
|
MSGT_Status rc;
|
|
rc = MSG_Semaphore_Operate (SemID, MSG_SemOp_SSL, 2);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_ShareLock_Set : unable to operate on semaphore %d", SemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Libération d'un verrou en lecture */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_ShareLock_Release (int SemID)
|
|
{
|
|
MSGT_Status rc;
|
|
rc = MSG_Semaphore_Operate (SemID, MSG_SemOp_RSL, 2);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_ShareLock_Release : unable to operate on semaphore %d", SemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pose d'un verrou en écriture */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_ExclusiveLock_Set (int SemID)
|
|
{
|
|
MSGT_Status rc;
|
|
rc = MSG_Semaphore_Operate (SemID, MSG_SemOp_SEL, 2);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_ExclusiveLock_Set : unable to operate on semaphore %d", SemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Libération d'un verrou en écriture */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_ExclusiveLock_Release (int SemID)
|
|
{
|
|
MSGT_Status rc;
|
|
rc = MSG_Semaphore_Operate (SemID, MSG_SemOp_REL, 2);
|
|
if (rc != MSGS_OK)
|
|
{
|
|
sprintf (MSG_Error_Msg, "Error MSG_ExclusiveLock_Release : unable to operate on semaphore %d", SemID);
|
|
MSG_Error_Print ();
|
|
return rc;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Opération sur un sémaphore */
|
|
/*------------------------------------------------------------------------------*/
|
|
MSGT_Status MSG_Semaphore_Operate (int SemID, struct sembuf * Operations, unsigned int Nb_Oper)
|
|
{
|
|
if (semop (SemID, Operations, Nb_Oper) == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EAGAIN:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : the operation would result in suspension of the calling process but the operations have been defined in no wait mode");
|
|
return MSGS_ERRNOWAIT;
|
|
|
|
case EINTR:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : a signal was received while operating on semaphore %d", SemID);
|
|
return MSGS_ERRSIG;
|
|
break;
|
|
|
|
case EACCES:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : current process is not allowed to operate on semaphore %d", SemID);
|
|
break;
|
|
|
|
case EIDRM:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : semaphore %d does not exist", SemID);
|
|
break;
|
|
|
|
case EINVAL:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : the semaphore %d is incorrect or the number of operations which can be done in UNDO mode exceeds the system-imposed limit", SemID);
|
|
break;
|
|
|
|
case ENOSPC:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : the maximum number of process which can operate on semaphore in UNDO mode has been reached");
|
|
break;
|
|
|
|
case ERANGE:
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate: the value of semaphore %d has reached the system-imposed limit", SemID);
|
|
break;
|
|
|
|
default :
|
|
sprintf (MSG_Error_Msg, "Error MSG_Semaphore_Operate : unknown error %d while operating on semaphore %d", errno, SemID);
|
|
break;
|
|
}
|
|
|
|
MSG_Error_Print ();
|
|
|
|
return MSGS_ERRSEM;
|
|
}
|
|
|
|
return MSGS_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pour préfixer les noms de heap avec le contexte de la librairie LIBMSG */
|
|
/*------------------------------------------------------------------------------*/
|
|
static char * MSG_Name_Prefix (const char * Name)
|
|
{
|
|
static char Prefixed [256];
|
|
|
|
sprintf (Prefixed, "%s/%s", MSG_PREFIX, Name);
|
|
|
|
return Prefixed;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pour récupérer l'état de verrouillage d'un port de messages */
|
|
/*------------------------------------------------------------------------------*/
|
|
char * MSG_LockStatus_Get (int SemID)
|
|
{
|
|
static char Status [50];
|
|
union semun Sem_Ctl;
|
|
int i;
|
|
|
|
i = semctl (SemID, 0, GETVAL, Sem_Ctl);
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
sprintf (Status, "exclusive lock");
|
|
break;
|
|
|
|
case 1:
|
|
sprintf (Status, "unlocked");
|
|
break;
|
|
|
|
default :
|
|
if (i < 0) sprintf (Status, "anormal status (%d)", i);
|
|
else sprintf (Status, "share lock (%d process)", i - 1);
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|