libmsg/lib/libmsg.c

3182 lines
108 KiB
C
Raw Permalink Normal View History

2000-07-28 17:34:22 +02:00
/* 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 <20>t<EFBFBD> ouverte */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_IsOpen_I ( void )
{
if (!MSG_Base) return MSGS_NO;
return MSGS_YES;
}
/*------------------------------------------------------------------------------*/
/* Permet d'indiquer <20> la librairie qu'un signal a <20>t<EFBFBD> re<72>u. */
/* */
/* NB : cette fonction sera appel<65>e par l'utilisateur pour <20>viter que le */
/* processus se bloque sur une attente de message malgr<67> 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<75>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<63>s aux ressources partag<61>es de la librairie */
if (Open_Mode & MSGD_CREATE)
{
/* On v<>rifie que le processus courant n'a pas d<>j<EFBFBD> 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<43>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<43>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<43>ation du heap dans lequel seront allou<6F>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<63>de aux ressources que lors de la premi<6D>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<6F>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 <20> 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<69>re les ressources que lors de la derni<6E>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 <20> 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<75>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<43>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<EFBFBD>renc<6E>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<43>ation du port dans la liste des ports r<>f<EFBFBD>renc<6E>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<43>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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
/* Initialisation du s<>maphore <20> 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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
/* Cr<43>ation du s<>maphore permettant l'<27>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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
/* Initialisation du s<>maphore <20> 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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
/* Cr<43>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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
else strcpy ((*Port)->MsgQueue->Manager, "MSG_MessageQueue_Manager");
/* Cr<43>ation de la liste des s<>maphores des listes de ports qui sont <20> l'<27>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<70>c<EFBFBD>dement cr<63><72> */
DS_Value_Free (MSG_Base->Port_List, (void *)*Port);
return rc;
}
else strcpy ((*Port)->SemList->Manager, "MSG_Semaphore_List_Manager");
/* Ajout du port <20> la liste des ports r<>f<EFBFBD>renc<6E>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<70>c<EFBFBD>dement cr<63><72> */
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<6E>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<EFBFBD> d<>pass<73>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<EFBFBD>renc<6E> par une liste de ports (tant pis pour elle) */
/* Suppression du port de la liste des ports r<>f<EFBFBD>renc<6E>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 <20> 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<43>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<43>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<43>ation du s<>maphore pour l'<27>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 <20> 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 <20> 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 <20> 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 <20> jour du s<>maphore de la liste : pour cela, on verrouille temporairement le port <20>cout<75> */
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<EFBFBD>rence la pr<70>sente liste au niveau du port que l'on <20>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 <20> 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<EFBFBD>rence que le port avait sur la pr<70>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 <20> r<>cup<75>rer */
/* (O) Msg : adresse d'un pointeur sur le message <20> recevoir */
/* (I) Flags : param<61>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'<EFBFBD>coute d'une liste de ports est bas<EFBFBD>e sur le
m<EFBFBD>me algorithme que pour l'<EFBFBD>coute d'un seul port.
Pour cela, la liste de ports poss<EFBFBD>de un s<EFBFBD>maphore qui est
incr<EFBFBD>ment<EFBFBD>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<6F>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<6E> 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 <20>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 <20>t<EFBFBD> trouv<75> ? */
if (Found == TRUE)
{
/* Fin de la boucle de recherche */
End = TRUE;
}
else
{
/* En mode sans attente, on sort directement avec un code retour sp<73>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<69> sur l'un des ports de la liste ? */
switch ((int)rc)
{
case MSGS_OK:
/* On boucle <20> 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<43>ation d'un message */
/*------------------------------------------------------------------------------*/
/* (O) Msg : adresse d'un pointeur sur le message */
/* (I) Size : taille en octets des donn<6E>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 <20>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<6F> 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<6E>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<EFBFBD>curit<EFBFBD> pour le messages syst<EFBFBD>me PING :
La taille du message doit <EFBFBD>tre suffisante pour contenir
4 dates (mises <EFBFBD> jour automatiquement par la librairie) :
- date d'envoi du PING REQUEST
- date de r<EFBFBD>ception du PING REQUEST
- date d'envoi du PING REPLY
- date de r<EFBFBD>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 <20>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<6F> 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<EFBFBD>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<69> : on v<>rifie que le port de l'envoyeur est renseign<67> ! */
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 <20>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 <20> 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<EFBFBD> cr<63><72> dans la liste de messages g<>r<EFBFBD>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 <20> jour le s<>maphore d'<27>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 <20> jour les s<>maphores de toutes les liste de ports qui sont <20> l'<27>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-<2D>tre un processus a-t'il oubli<6C> 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 <20>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 <20> r<>cup<75>rer */
/* (O) Msg : adresse d'un pointeur sur le message <20> recevoir */
/* (I) Flags : param<61>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'<27>coute d'un port de messagee est bas<61>e sur l'algorithme suivant :
- le processus commence par consulter la queue de messages (apr<EFBFBD>s verrouillage exclusif)
- s'il ne trouve rien qui lui convienne, il se met en attente sur le s<EFBFBD>maphore attach<EFBFBD> au port.
NB : le s<EFBFBD>maphore du port est incr<EFBFBD>ment<EFBFBD> <EFBFBD> chaque fois qu'un nouveau message est pr<EFBFBD>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 <20>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<6F>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<6E> */
if (Type == MSGD_NO_TYPE)
{
/* Si aucun type n'est demand<6E> 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<73>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 <20>t<EFBFBD> trouv<75> ? */
if (Found == TRUE)
{
*Msg = (MSGT_Message *)(Node->Value);
/* Retrait du message = retrait du noeud (le noeud est g<>r<EFBFBD> dans la liste de messages r<>f<EFBFBD>renc<6E>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 <20>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<73>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<69> ? */
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 <EFBFBD>t<EFBFBD> retir<EFBFBD>, on met <EFBFBD> jour les s<EFBFBD>maphores
de toutes les listes de ports qui seraient <EFBFBD> l'<EFBFBD>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<70>cis<69>ment r<>veill<6C> */
break;
case MSGS_ERRSIG:
return MSGS_ERRSIG;
break;
default :
/* Peut-<2D>tre un processus a-t'il oubli<6C> 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 <20>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<EFBFBD>ception d'un PING (REQUEST ou REPLY), on modifie le contenu
du message en y mettant la date courante de r<EFBFBD>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'<EFBFBD> renvoyer automatiquement
le message <EFBFBD> son envoyeur, puis relancer l'<EFBFBD>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 <20> 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<EFBFBD>me de type REQUEST, on change le type en REPLY.
Pour les messages utilisateur, c'est <EFBFBD> l'utilisateur de changer le type si n<EFBFBD>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 <20> 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 <20> la librairie qu'un signal a <20>t<EFBFBD> re<72>u. */
/* */
/* NB : cette fonction sera appel<65>e par l'utilisateur pour <20>viter que le */
/* processus se bloque sur une attente de message malgr<67> la r<>ception de signal */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_Signal_C ( void )
{
return MSG_Library_Signal_I ();
}
/*------------------------------------------------------------------------------*/
/* Teste si la librairie a <20>t<EFBFBD> ouverte */
/*------------------------------------------------------------------------------*/
MSGT_Status MSG_Library_IsOpen_C ( void )
{
return MSG_Library_IsOpen_I ();
}
/*------------------------------------------------------------------------------*/
/* Ouverture de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : num<75>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<43>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<6E>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<EFBFBD> d<>pass<73>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 <20> 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<43>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 <20> 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 <20> r<>cup<75>rer */
/* (O) Msg : adresse d'un pointeur sur le message <20> recevoir */
/* (I) Flags : param<61>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<43>ation d'un message */
/*------------------------------------------------------------------------------*/
/* (O) Msg : adresse d'un pointeur sur le message */
/* (I) Size : taille en octets des donn<6E>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<6E>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<EFBFBD>curit<EFBFBD> pour le messages syst<EFBFBD>me PING :
La taille du message doit <EFBFBD>tre suffisante pour contenir
4 dates (mises <EFBFBD> jour automatiquement par la librairie) :
- date d'envoi du PING REQUEST
- date de r<EFBFBD>ception du PING REQUEST
- date d'envoi du PING REPLY
- date de r<EFBFBD>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 <20> r<>cup<75>rer */
/* (O) Msg : adresse d'un pointeur sur le message <20> recevoir */
/* (I) Flags : param<61>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 <20> 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 <20> 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<EFBFBD>renc<6E>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<70>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<72>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-<2D>quilibr<62>"; break;
default : Root_Type = "arbre non auto-<2D>quilibr<62>"; 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<66>rence maximale autoris<69>e = %ld\n\t- Nombre d'<27>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 <20>t<EFBFBD> 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 <20>tant allou<6F>s ind<6E>pendament de la queue de messages, on les d<>truit <20> 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<6E> <20>tre d<>j<EFBFBD> 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<72>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-<2D>quilibr<62>"; break;
default : Root_Type = "arbre non auto-<2D>quilibr<62>"; 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<66>rence maximale autoris<69>e = %ld\n\t- Nombre d'<27>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<72>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-<2D>quilibr<62>"; break;
default : Root_Type = "arbre non auto-<2D>quilibr<62>"; 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<66>rence maximale autoris<69>e = %ld\n\t- Nombre d'<27>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<63>e <20> 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<72>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-<2D>quilibr<62>"; break;
default : Root_Type = "arbre non auto-<2D>quilibr<62>"; 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<66>rence maximale autoris<69>e = %ld\n\t- Nombre d'<27>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<EFBFBD>
- par ordre d'arriv<EFBFBD>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<69>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 <20>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<69>ration d'un verrou en <20>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<4F>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<70>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<75>rer l'<27>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;
}