1247 lines
40 KiB
C
1247 lines
40 KiB
C
#include <sys/types.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/times.h>
|
|
#include <signal.h>
|
|
#ifdef LINUX
|
|
#include <bits/siginfo.h>
|
|
#include <sys/wait.h>
|
|
#else
|
|
#include <sys/siginfo.h>
|
|
#include <wait.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#include <ver.h>
|
|
#define ND_MODE 1
|
|
#include <node.h>
|
|
#define MSG_MODE 1
|
|
#include <msg.h>
|
|
#include <logagent.h>
|
|
|
|
extern int sigignore(int sig);
|
|
|
|
VER_INFO_EXPORT (logsupervisor, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $")
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
|
|
#define Date_IsSet(tvp) ((tvp).tv_sec || (tvp).tv_usec)
|
|
#define Date_Compare(tvp, uvp) ((tvp).tv_sec < (uvp).tv_sec || ((tvp).tv_sec == (uvp).tv_sec && (tvp).tv_usec < (uvp).tv_usec))
|
|
|
|
/* Tableau permettant de référéncer les agents suivis par le superviseur */
|
|
|
|
typedef struct {
|
|
pid_t Pid; /* Identifiant du processus */
|
|
short int Restarted; /* Indique si l'agent est déjà tombé puis a été redémarré */
|
|
short int GivenUp; /* Indique si l'agent a été abandonné (car tombé plusieur fois) */
|
|
} Agent_Ref;
|
|
|
|
Agent_Ref * Tab_Agent;
|
|
|
|
/* Requêtes à traiter par le superviseur (classées par type de message système) */
|
|
|
|
typedef struct {
|
|
struct timeval Request_Date; /* Date de début de la requête */
|
|
unsigned int Nb_Reply; /* Nombre de réponses recues de la part des agents */
|
|
Agent_Stat Reply_Stat [NB_MAX_AGENT]; /* Statistiques des agents ayant répondu */
|
|
NDT_Root * Msg_List; /* Liste chaînée des messages en attente sur cette requête */
|
|
} Waiting_Request;
|
|
|
|
Waiting_Request Tab_Request [MSGD_NB_SYSTEM_MESSAGE];
|
|
|
|
char Debug_Trace [256];
|
|
unsigned int Timeout;
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
|
|
#define AGENT_PATH "logagent"
|
|
|
|
#define SUPERVISOR_START 1
|
|
#define SUPERVISOR_PING 2
|
|
#define SUPERVISOR_STATUS_GET 3
|
|
#define SUPERVISOR_INFO_GET 4
|
|
#define SUPERVISOR_STOP_AGENT 5
|
|
#define SUPERVISOR_CONTINUE_AGENT 6
|
|
#define SUPERVISOR_TRACEON 7
|
|
#define SUPERVISOR_TRACEOFF 8
|
|
#define SUPERVISOR_SHUTDOWN 9
|
|
|
|
void Parse_Arg ( int, char ** );
|
|
void Supervisor_Start ( void );
|
|
void Supervisor_Request (unsigned int, size_t, int);
|
|
void Supervisor_Ping ( void );
|
|
void Supervisor_Status_Get ( void );
|
|
void Supervisor_Info_Get ( void );
|
|
void Supervisor_Agent_Stop ( void );
|
|
void Supervisor_Agent_Continue ( void );
|
|
void Supervisor_Shutdown ( void );
|
|
|
|
void System_Msg_Process ( MSGT_Message * );
|
|
int Agent_Msg_Send ( unsigned int, unsigned int, int );
|
|
int Agent_Start ( unsigned int );
|
|
void Agent_Restart ( int signum );
|
|
char * Agent_Status_Get ( unsigned int Agent_Status, unsigned int Agent_Debug );
|
|
void Request_Answer ( unsigned int Idx );
|
|
void Timeout_Handle ( int signum );
|
|
void Info_Trace ( void );
|
|
char * Status_Get ( void );
|
|
NDT_Status Request_List_Manager ( va_list );
|
|
|
|
unsigned int Nb_Agent, Nb_GivenUp, End_Supervisor, Status, Debug, Action;
|
|
MSGT_Port * Supervisor_Port, * System_Port;
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
|
|
int main ( int argc , char ** argv )
|
|
{
|
|
/* Récupération des arguments de la ligne de commande */
|
|
|
|
Parse_Arg (argc, argv);
|
|
|
|
/* Lancement de l'action sur le superviseur */
|
|
|
|
switch (Action)
|
|
{
|
|
case SUPERVISOR_START:
|
|
Supervisor_Start ();
|
|
break;
|
|
|
|
case SUPERVISOR_PING:
|
|
Supervisor_Request (MSGD_SYSTEM_PING_REQUEST, sizeof (MSGT_PingData), MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_STATUS_GET:
|
|
Supervisor_Request (MSGD_SYSTEM_STATUS_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_INFO_GET:
|
|
Supervisor_Request (MSGD_SYSTEM_INFO_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_STOP_AGENT:
|
|
Supervisor_Request (MSGD_SYSTEM_STOP_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_CONTINUE_AGENT:
|
|
Supervisor_Request (MSGD_SYSTEM_CONTINUE_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_TRACEON:
|
|
Supervisor_Request (MSGD_SYSTEM_TRACEON_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_TRACEOFF:
|
|
Supervisor_Request (MSGD_SYSTEM_TRACEOFF_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
case SUPERVISOR_SHUTDOWN:
|
|
Supervisor_Request (MSGD_SYSTEM_SHUTDOWN_REQUEST, ANSWER_SIZE, MSGD_SYSTEM_HIGH_PRIORITY);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Récupération de la ligne de commande */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Parse_Arg (int argc, char ** argv)
|
|
{
|
|
int i;
|
|
|
|
Debug = FALSE;
|
|
Nb_Agent = 0;
|
|
Timeout = 0;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h"))
|
|
{
|
|
char Usage [1000];
|
|
|
|
sprintf (Usage,
|
|
"Usage : %s <options>\nOptions :\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n\t%-50s\t%s\n",
|
|
argv [0],
|
|
"--help | -h", "-> Affiche l'aide courante",
|
|
"--version [-v]", "-> Affiche le numéro de version",
|
|
"--start <nb_agent> [--debug] [--timeout <nb_sec>]", "-> Démarre le superviseur et <nb_agent> agents",
|
|
"--ping", "-> Ping le superviseur",
|
|
"--status", "-> Affiche le status de tous les agents et du superviseur",
|
|
"--info", "-> Affiche des informations statistiques de tous les agents",
|
|
"--stop", "-> Stoppe tous les agents",
|
|
"--continue", "-> Continue tous les agents stoppés",
|
|
"--traceon", "-> Active le mode trace du superviseur et des agents",
|
|
"--traceoff", "-> Désactive le mode trace du superviseur et des agents",
|
|
"--shutdown", "-> Tue tous les agents et le superviseur");
|
|
fprintf (stderr, Usage);
|
|
exit (1);
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--version"))
|
|
{
|
|
if (i+1 < argc && !strcmp (argv[i+1], "-v"))
|
|
{
|
|
VER_Object_Print (stdout, VERD_VERBOSE);
|
|
exit (0);
|
|
}
|
|
else
|
|
{
|
|
VER_Object_Print (stdout, VERD_MINIMAL);
|
|
exit (0);
|
|
}
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--start"))
|
|
{
|
|
Action = SUPERVISOR_START;
|
|
i++;
|
|
if (i == argc)
|
|
{
|
|
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
|
|
exit (0);
|
|
}
|
|
|
|
if ((Nb_Agent = atoi (argv[i])) <= 0)
|
|
{
|
|
fprintf (stderr, "Bad value (%s) after %s\n", argv[i], argv[i - 1]);
|
|
exit (0);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--ping"))
|
|
{
|
|
Action = SUPERVISOR_PING;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--status"))
|
|
{
|
|
Action = SUPERVISOR_STATUS_GET;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--info"))
|
|
{
|
|
Action = SUPERVISOR_INFO_GET;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--stop"))
|
|
{
|
|
Action = SUPERVISOR_STOP_AGENT;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--continue"))
|
|
{
|
|
Action = SUPERVISOR_CONTINUE_AGENT;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--traceon"))
|
|
{
|
|
Action = SUPERVISOR_TRACEON;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--traceoff"))
|
|
{
|
|
Action = SUPERVISOR_TRACEOFF;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--shutdown"))
|
|
{
|
|
Action = SUPERVISOR_SHUTDOWN;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--debug"))
|
|
{
|
|
Debug = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp (argv[i], "--timeout"))
|
|
{
|
|
i++;
|
|
if (i == argc)
|
|
{
|
|
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
|
|
exit (0);
|
|
}
|
|
|
|
if ((Timeout = atoi (argv[i])) <= 0)
|
|
{
|
|
fprintf (stderr, "Bad value (%s) after %s\n", argv[i], argv[i - 1]);
|
|
exit (0);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
fprintf (stderr, "Option invalide \"%s\"\n", argv[i]);
|
|
exit (0);
|
|
}
|
|
|
|
if (Timeout == 0) Timeout = DEFAULT_TIMEOUT;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/*--------------------------------------- SUPERVISEUR ----------------------------------------------*/
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Envoie une requête au superviseur */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Supervisor_Request (unsigned int Type, size_t Size, int Priority)
|
|
{
|
|
MSGT_Message * Msg;
|
|
|
|
Debug = TRUE;
|
|
|
|
/* Ouverture de la librairie LIBLOG */
|
|
|
|
if (MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible d'ouvrir la librairie LIBMSG\n");
|
|
return;
|
|
}
|
|
|
|
/* Ouverture du port de messages du superviseur */
|
|
|
|
if (MSG_Port_Open (MSGD_SUPERVISOR_PORT_NAME, &Supervisor_Port, MSGD_OPEN) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible d'ouvrir le port de messages du superviseur\n");
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Création / ouverture du port système dont on se sert pour les accusés réception */
|
|
|
|
if (MSG_Port_Open (MSGD_SYSTEM_PORT_NAME, &System_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible d'ouvrir ou de créer le port de messages système\n");
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Création du message */
|
|
|
|
if (MSG_Message_Alloc (&Msg, Size) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de créer un message\n");
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Port_Close (System_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
memset (Msg->Data, 0, Msg->Size);
|
|
|
|
if (MSG_Message_Config (Msg, MSGD_CONFIG_TYPE, Type) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de configurer le type du message\n");
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (System_Port, MSGD_CLOSE);
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
if (MSG_Message_Config (Msg, MSGD_CONFIG_PRIORITY, Priority) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de configurer la priorité du message\n");
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (System_Port, MSGD_CLOSE);
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Envoi du message avec demande d'accusé réception dans le port système */
|
|
|
|
if (MSG_Message_Send (MSGD_SYSTEM_PORT_NAME, Supervisor_Port, Msg) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible d'envoyer le message\n");
|
|
MSG_Port_Close (System_Port, MSGD_CLOSE);
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Fermeture du port de messages du superviseur */
|
|
|
|
if (MSG_Port_Close (Supervisor_Port, MSGD_CLOSE) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de fermer le port de messages du superviseur\n");
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Ecoute du port de messages système */
|
|
|
|
if (MSG_Message_Receive (System_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de réceptionner un message dans le port système\n");
|
|
MSG_Message_Free (Msg);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
if (Msg->Type == MSGD_SYSTEM_PING_REPLY)
|
|
{
|
|
double send_delay, rcv_delay, ping_delay;
|
|
struct timeval t1, t2, t3, t4;
|
|
|
|
t1 = ((MSGT_PingData *)(Msg->Data))->Snd1;
|
|
t2 = ((MSGT_PingData *)(Msg->Data))->Rcv1;
|
|
t3 = ((MSGT_PingData *)(Msg->Data))->Snd2;
|
|
t4 = ((MSGT_PingData *)(Msg->Data))->Rcv2;
|
|
|
|
send_delay = (double)(t2.tv_sec) - (double)(t1.tv_sec) + ((double)(t2.tv_usec) - (double)(t1.tv_usec)) / 1000000;
|
|
rcv_delay = (double)(t4.tv_sec) - (double)(t3.tv_sec) + ((double)(t4.tv_usec) - (double)(t3.tv_usec)) / 1000000;
|
|
ping_delay = (double)(t4.tv_sec) - (double)(t1.tv_sec) + ((double)(t4.tv_usec) - (double)(t1.tv_usec)) / 1000000;
|
|
|
|
fprintf (stdout, "Ping = %.4f sec (Aller = %.4f sec / Retour = %.4f sec)\n", ping_delay, send_delay, rcv_delay);
|
|
}
|
|
else
|
|
{
|
|
/* Autres messages système */
|
|
|
|
fprintf (stdout, (char *)(Msg->Data));
|
|
}
|
|
|
|
/* Désallocation du message */
|
|
|
|
if (MSG_Message_Free (Msg) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de supprimer le message\n");
|
|
MSG_Port_Close (System_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Fermeture du port de messages système */
|
|
|
|
if (MSG_Port_Close (System_Port, MSGD_CLOSE) != MSGS_OK)
|
|
{
|
|
fprintf (stderr, "=> Impossible de fermer le port de messages système\n");
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return ;
|
|
}
|
|
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Procédure de démarrage du superviseur */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Supervisor_Start ( void )
|
|
{
|
|
MSGT_Message * Msg;
|
|
unsigned int i;
|
|
|
|
Nb_GivenUp = 0;
|
|
End_Supervisor = FALSE;
|
|
Status = ACTIVE;
|
|
|
|
/* Allocation d'un tableau pour référencer les agents */
|
|
|
|
Tab_Agent = (Agent_Ref *)malloc (Nb_Agent * sizeof (Agent_Ref));
|
|
|
|
if (!Tab_Agent)
|
|
{
|
|
strcpy (Debug_Trace, "impossible d'allouer de la mémoire pour référencer les agents");
|
|
Info_Trace ();
|
|
return;
|
|
}
|
|
|
|
/* Initialisation du tableau des requêtes soumises au superviseur */
|
|
|
|
for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++)
|
|
{
|
|
memset (&(Tab_Request [i]), 0, sizeof (Waiting_Request));
|
|
ND_DataStruct_Open (&(Tab_Request [i].Msg_List), NDD_DS_LIST | NDD_MN_FIFO, NULL, NULL, NULL, TRUE);
|
|
strcpy (Tab_Request [i].Msg_List->Manager, "Request_List_Manager");
|
|
}
|
|
|
|
/* Ouverture de la librairie LIBMSG */
|
|
|
|
if (MSG_Library_Open (0, NULL, MSGD_OPEN) != MSGS_OK)
|
|
{
|
|
strcpy (Debug_Trace, "impossible d'ouvrir la librairie LIBMSG");
|
|
Info_Trace ();
|
|
return;
|
|
}
|
|
|
|
/* Ouverture / création du port de messages du superviseur */
|
|
|
|
if (MSG_Port_Open (MSGD_SUPERVISOR_PORT_NAME, &Supervisor_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK)
|
|
{
|
|
strcpy (Debug_Trace, "impossible d'ouvrir mon port de messages privé");
|
|
Info_Trace ();
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* On trappe le signal SIGCHLD pour détecter les agents qui tombent */
|
|
|
|
signal (SIGCHLD, Agent_Restart);
|
|
|
|
/* Lancement des agents */
|
|
|
|
for (i = 1; i <= Nb_Agent; i++) Agent_Start (i);
|
|
|
|
/* Boucle principale du superviseur */
|
|
|
|
while (End_Supervisor == FALSE)
|
|
{
|
|
/* Ecoute du port de messages du superviseur */
|
|
|
|
int rc = MSG_Message_Receive (Supervisor_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT);
|
|
|
|
switch (rc)
|
|
{
|
|
case MSGS_OK:
|
|
|
|
/* Traitement des messages envoyés au superviseur */
|
|
|
|
System_Msg_Process (Msg);
|
|
|
|
break;
|
|
|
|
case MSGS_ERRSIG:
|
|
|
|
/* On continue à boucler sur l'écoute */
|
|
|
|
break;
|
|
|
|
default:
|
|
strcpy (Debug_Trace, "impossible de réceptionner un message dans mon port du messages privé");
|
|
Info_Trace ();
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (Supervisor_Port, MSGD_CLOSE);
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Fermeture du port de messages du superviseur */
|
|
|
|
if (MSG_Port_Close (Supervisor_Port, MSGD_CLOSE) != MSGS_OK)
|
|
{
|
|
strcpy (Debug_Trace, "impossible de fermer mon port de messages privé");
|
|
Info_Trace ();
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
return;
|
|
}
|
|
|
|
/* Fermeture de la librairie LIBMSG */
|
|
|
|
MSG_Library_Close (MSGD_CLOSE);
|
|
|
|
/* Désallocation des ressources locales */
|
|
|
|
for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++)
|
|
{
|
|
if (Tab_Request [i].Msg_List) ND_DataStruct_Close (Tab_Request [i].Msg_List);
|
|
}
|
|
|
|
strcpy (Debug_Trace, "terminé");
|
|
Info_Trace ();
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Traitement d'un message système par le superviseur */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void System_Msg_Process (MSGT_Message * Msg)
|
|
{
|
|
unsigned int Idx;
|
|
unsigned int i;
|
|
|
|
/* S'agit-il d'un message de type REQUEST ou REPLY ? */
|
|
|
|
if (MSGD_IS_SYSTEM_REQUEST (Msg->Type))
|
|
{
|
|
Idx = (Msg->Type - 1) / 2;
|
|
|
|
/* Le message est-il de taille suffisante pour que l'on y réponde ? */
|
|
|
|
if (Msg->Size < ANSWER_SIZE)
|
|
{
|
|
/* On le supprime : tant pis pour l'envoyeur ! */
|
|
|
|
MSG_Message_Free (Msg);
|
|
|
|
sprintf (Debug_Trace, "la requête envoyée par \"%s\" ne sera pas prise en compte car le message est de taille insuffisante (%d octets minimum)", Msg->From, ANSWER_SIZE);
|
|
Info_Trace ();
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
Mise du message en attente : on y répondra lorque tous les
|
|
agents y auront répondu ou bien lorsque le timeout aura expiré.
|
|
*/
|
|
|
|
ND_Value_Add (Tab_Request [Idx].Msg_List, Msg);
|
|
|
|
/* On regarde si une requête du même type était déjà en cours */
|
|
|
|
if (Tab_Request [Idx].Msg_List->Node_Number == 1)
|
|
{
|
|
/* S'il s'agit d'une requête SHUTDOWN_REQUEST, il faut désormais ignorer les signaux de type SIGCHLD */
|
|
|
|
if (Msg->Type == MSGD_SYSTEM_SHUTDOWN_REQUEST)
|
|
sigignore (SIGCHLD);
|
|
|
|
/* On prend en compte les requêtes TRACEON_REQUEST et TRACEOFF_REQUEST */
|
|
|
|
if (Msg->Type == MSGD_SYSTEM_TRACEON_REQUEST)
|
|
{
|
|
Debug = TRUE;
|
|
sprintf (Debug_Trace, "activation du mode trace");
|
|
Info_Trace ();
|
|
}
|
|
|
|
if (Msg->Type == MSGD_SYSTEM_TRACEOFF_REQUEST)
|
|
{
|
|
sprintf (Debug_Trace, "désactivation du mode trace");
|
|
Info_Trace ();
|
|
Debug = FALSE;
|
|
}
|
|
|
|
/* On mémorise la date de la requête */
|
|
|
|
gettimeofday (&(Tab_Request [Idx].Request_Date), NULL);
|
|
|
|
if (Nb_Agent - Nb_GivenUp == 0)
|
|
{
|
|
/* S'il n'y a plus d'agent valide, on répond tout de suite à la requête */
|
|
|
|
Request_Answer (Idx);
|
|
}
|
|
else
|
|
{
|
|
/* Sinon, on initie une alarme ... */
|
|
|
|
signal (SIGALRM, Timeout_Handle);
|
|
alarm (Timeout);
|
|
|
|
/* ... et on transmet la requête à tous les agents qui devront y répondre avant le timeout */
|
|
|
|
for (i = 1; i <= Nb_Agent; i++)
|
|
{
|
|
if (Tab_Agent [i -1].GivenUp == FALSE)
|
|
{
|
|
if (Agent_Msg_Send (i, Msg->Type, MSGD_SYSTEM_HIGH_PRIORITY) != OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de transmettre la requête à l'agent n°%d", i);
|
|
Info_Trace ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (MSGD_IS_SYSTEM_REPLY (Msg->Type)) /* Il s'agit d'une réponse d'un agent */
|
|
{
|
|
Idx = (Msg->Type / 2) - 1;
|
|
|
|
/* Une requête de ce type a-t'elle déjà été lancée ? */
|
|
|
|
if (Tab_Request [Idx].Msg_List->Node_Number > 0)
|
|
{
|
|
int Num_Agent;
|
|
Agent_Stat * Stat;
|
|
|
|
Tab_Request [Idx].Nb_Reply++;
|
|
|
|
/* Mise à jour de statistiques : on recopie celles renvoyés par l'agent dans notre tableau */
|
|
|
|
Stat = (Agent_Stat *)(Msg->Data);
|
|
|
|
Num_Agent = Stat->Num_Agent;
|
|
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Num_Agent = Stat->Num_Agent;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Pid = Stat->Pid;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Cpt_Event = Stat->Cpt_Event;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Cpt_System = Stat->Cpt_System;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Status = Stat->Status;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Debug = Stat->Debug;
|
|
Tab_Request [Idx].Reply_Stat [Num_Agent - 1].Answer = Stat->Answer;
|
|
|
|
/* Tous les agents ont-ils répondu à la requête ? */
|
|
|
|
if (Tab_Request [Idx].Nb_Reply == Nb_Agent - Nb_GivenUp)
|
|
{
|
|
/* On répond à la requête */
|
|
|
|
Request_Answer (Idx);
|
|
}
|
|
else
|
|
{
|
|
/* Tous les agents n'ont pas encore répondu : on attend encore */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* L'agent a répondu trop tard : tant pis pour lui, on ne tient pas compte de cette réponse */
|
|
}
|
|
|
|
/* On supprime le message */
|
|
|
|
MSG_Message_Free (Msg);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Réponse à une requête (procédure exécutée au timeout ou bien lorsque tous les agents ont répondu)*/
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Request_Answer ( unsigned int Idx )
|
|
{
|
|
char Answer [ANSWER_SIZE];
|
|
unsigned int i, j;
|
|
unsigned int Type = 2 * Idx + 1;
|
|
NDT_Node * Node, * Next_Node;
|
|
NDT_Root * Msg_List;
|
|
char str [256];
|
|
|
|
Answer [0] = (char)0;
|
|
|
|
/* Réponse concernant le superviseur lui-même */
|
|
|
|
switch (Type)
|
|
{
|
|
case MSGD_SYSTEM_TRACEON_REQUEST:
|
|
|
|
sprintf (str, "Superviseur : mode trace activé\n");
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_TRACEOFF_REQUEST:
|
|
|
|
sprintf (str, "Superviseur : mode trace désactivé\n");
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_STATUS_REQUEST:
|
|
|
|
sprintf (str, "Superviseur : %s\n", Status_Get ());
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_INFO_REQUEST:
|
|
|
|
/* Informations concernant les agents suivis */
|
|
|
|
sprintf (str, "Superviseur :\n\t- %d agent(s) suivi(s)\n\t- %d agent(s) abandonné(s)\n", Nb_Agent - Nb_GivenUp, Nb_GivenUp);
|
|
strcat (Answer, str);
|
|
|
|
/* On compte le nombre de requêtes en attente */
|
|
|
|
j = 0;
|
|
for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++)
|
|
if (i != Idx && Tab_Request [i].Msg_List->Node_Number > 0) j++;
|
|
|
|
sprintf (str, "\t- %d requête(s) en attente de réponse de la part des agents\n", j);
|
|
strcat (Answer, str);
|
|
|
|
/* On consolide les statistiques des agents concernant le nombre d'événements traités */
|
|
|
|
j = 0;
|
|
for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++)
|
|
j += Tab_Request [Idx].Reply_Stat [i].Cpt_Event;
|
|
|
|
sprintf (str, "\t- %d événement(s) traité(s) par l'ensemble des agents ayant répondu\n\n", j);
|
|
strcat (Answer, str);
|
|
|
|
break;
|
|
|
|
case MSGD_SYSTEM_SHUTDOWN_REQUEST:
|
|
|
|
End_Supervisor = TRUE;
|
|
|
|
strcpy (Debug_Trace, "terminaison en cours...");
|
|
Info_Trace ();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
/* Réponse concernant les agents auxquels la requête a été transmise */
|
|
|
|
sprintf (str, "%d/%d agent(s) ont répondu à la requête%s\n", Tab_Request [Idx].Nb_Reply, Nb_Agent - Nb_GivenUp, Tab_Request [Idx].Nb_Reply > 0 ? " :" : ".");
|
|
strcat (Answer, str);
|
|
|
|
for (i = 0; i < Nb_Agent; i++)
|
|
{
|
|
if (Tab_Agent [i].GivenUp == TRUE) continue;
|
|
|
|
sprintf (str, "\t- Agent n°%d (process %ld) : ", i + 1, Tab_Agent [i].Pid);
|
|
strcat (Answer, str);
|
|
|
|
if (Tab_Request [Idx].Reply_Stat [i].Num_Agent == 0)
|
|
strcat (Answer, "pas de réponse\n");
|
|
else
|
|
{
|
|
switch (Type)
|
|
{
|
|
case MSGD_SYSTEM_STOP_REQUEST:
|
|
sprintf (str, "%s\n", Tab_Request [Idx].Reply_Stat [i].Answer == TRUE ? "stoppé" : "déjà stoppé");
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_CONTINUE_REQUEST:
|
|
sprintf (str, "%s\n", Tab_Request [Idx].Reply_Stat [i].Answer == TRUE ? "repris" : "déjà actif");
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_SHUTDOWN_REQUEST:
|
|
strcat (Answer, "arrêté\n");
|
|
break;
|
|
|
|
case MSGD_SYSTEM_STATUS_REQUEST:
|
|
sprintf (str, "%s\n", Agent_Status_Get (Tab_Request [Idx].Reply_Stat [i].Status, Tab_Request [Idx].Reply_Stat [i].Debug));
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_INFO_REQUEST:
|
|
sprintf (str, "%d événement(s) traité(s) / %d message(s) système(s) reçu(s)\n", Tab_Request [Idx].Reply_Stat [i].Cpt_Event, Tab_Request [Idx].Reply_Stat [i].Cpt_System);
|
|
strcat (Answer, str);
|
|
break;
|
|
|
|
case MSGD_SYSTEM_TRACEON_REQUEST:
|
|
strcat (Answer, "mode trace activé\n");
|
|
break;
|
|
|
|
case MSGD_SYSTEM_TRACEOFF_REQUEST:
|
|
strcat (Answer, "mode trace désactivé\n");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Type == MSGD_SYSTEM_SHUTDOWN_REQUEST) strcat (Answer, "Superviseur terminé.\n");
|
|
|
|
/* On répond à tous les messages en attente sur cette requête */
|
|
|
|
Msg_List = Tab_Request [Idx].Msg_List;
|
|
|
|
ND_Node_First_Get (Msg_List, &Node);
|
|
|
|
while (Node)
|
|
{
|
|
MSGT_Message * Msg = (MSGT_Message *)(Node->Value);
|
|
char * Msg_Data = Msg->Data;
|
|
|
|
ND_Node_Next_Get (Node, &Next_Node);
|
|
|
|
ND_Node_Remove (Node);
|
|
|
|
/* On remplit le champ de données du message */
|
|
|
|
if (strlen (Answer) >= Msg->Size)
|
|
{
|
|
sprintf (Debug_Trace, "attention, le message (%d octets) n'est pas assez long pour contenir toute la réponse (%d caractères)\n", Msg->Size, strlen (Answer));
|
|
Info_Trace ();
|
|
strncpy (Msg_Data, Answer, Msg->Size - 1);
|
|
Msg_Data [Msg->Size - 1] = (char)0;
|
|
}
|
|
else strcpy (Msg_Data, Answer);
|
|
|
|
/* On renvoie le message à son envoyeur */
|
|
|
|
MSG_Message_Reply (Msg);
|
|
|
|
/* Message suivant */
|
|
|
|
Node = Next_Node;
|
|
}
|
|
|
|
/* On réinitialise les données concernant la requête */
|
|
|
|
memset (&(Tab_Request [Idx]), 0, sizeof (Waiting_Request));
|
|
Tab_Request [Idx].Msg_List = Msg_List;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Procédure appelée lorsqu'un timeout expire */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Timeout_Handle ( int signum )
|
|
{
|
|
unsigned int i, Older;
|
|
int Found = FALSE;
|
|
|
|
/* On recherche la requête la plus ancienne */
|
|
|
|
for (i = 0; i < MSGD_NB_SYSTEM_MESSAGE; i++)
|
|
{
|
|
if (Date_IsSet (Tab_Request [i].Request_Date) && (Found == FALSE || Date_Compare (Tab_Request [i].Request_Date, Tab_Request [Older].Request_Date)))
|
|
{
|
|
Found = TRUE;
|
|
Older = i;
|
|
}
|
|
}
|
|
|
|
/* On répond à la requête */
|
|
|
|
if (Found == TRUE)
|
|
{
|
|
strcpy (Debug_Trace, "timeout expiré => réponse à la requête la plus ancienne");
|
|
Info_Trace ();
|
|
Request_Answer (Older);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Redémarrage automatique d'un agent tombé */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Agent_Restart ( int signum )
|
|
{
|
|
unsigned int Found, i;
|
|
pid_t Child_Pid;
|
|
#ifdef LINUX
|
|
int Child_Info;
|
|
#else
|
|
siginfo_t Child_Info;
|
|
#endif
|
|
unsigned int Restart;
|
|
|
|
/* On réinitialise le trap du signal SIGCHLD */
|
|
|
|
signal (SIGCHLD, Agent_Restart);
|
|
|
|
/* On récupère les informations concernant le processus fils qui est tombé */
|
|
|
|
#ifdef LINUX
|
|
Child_Pid = waitpid (-1, &Child_Info, WNOHANG);
|
|
|
|
if (Child_Pid == -1)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de récupérer les informations concernant un processus fils tombé");
|
|
Info_Trace ();
|
|
return;
|
|
}
|
|
#else
|
|
if (waitid (P_ALL, 0, &Child_Info, WEXITED) == -1)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de récupérer les informations concernant un processus fils tombé");
|
|
Info_Trace ();
|
|
return;
|
|
}
|
|
|
|
Child_Pid = Child_Info.si_pid;
|
|
#endif
|
|
|
|
/* On recherche l'agent correspondant au process fils tombé */
|
|
|
|
Found = FALSE;
|
|
i = 0;
|
|
while (i < Nb_Agent && Found == FALSE)
|
|
{
|
|
if (Tab_Agent [i].GivenUp == FALSE)
|
|
{
|
|
if (Tab_Agent [i].Pid == Child_Pid) Found = TRUE;
|
|
else i++;
|
|
|
|
}
|
|
else i++;
|
|
}
|
|
|
|
if (Found == FALSE)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de trouver l'agent correspondant au processus fils %ld tombé", Child_Pid);
|
|
Info_Trace ();
|
|
return;
|
|
}
|
|
|
|
/* Analyse de la raison pour laquelle le fils est tombé */
|
|
|
|
#ifdef LINUX
|
|
if (WIFEXITED(Child_Info))
|
|
#else
|
|
if (Child_Info.si_code == CLD_EXITED)
|
|
#endif
|
|
{
|
|
/* L'agent s'est terminé tout seul (comme un grand !!!) : on ne le relance pas */
|
|
|
|
Restart = FALSE;
|
|
|
|
#ifdef LINUX
|
|
sprintf (Debug_Trace, "détection agent n°%d terminé avec code retour %d", i + 1, WEXITSTATUS(Child_Info));
|
|
#else
|
|
sprintf (Debug_Trace, "détection agent n°%d terminé avec code retour %d", i + 1, Child_Info.si_status);
|
|
#endif
|
|
Info_Trace ();
|
|
}
|
|
#ifdef LINUX
|
|
else if (WIFSIGNALED(Child_Info) && WTERMSIG(Child_Info) == SIGKILL)
|
|
#else
|
|
else if (Child_Info.si_code == CLD_KILLED)
|
|
#endif
|
|
{
|
|
/* L'agent a à priori été tué volontairement : on ne le relance donc pas */
|
|
|
|
Restart = FALSE;
|
|
|
|
sprintf (Debug_Trace, "détection agent n°%d tué", i + 1);
|
|
Info_Trace ();
|
|
|
|
}
|
|
#ifdef LINUX
|
|
else if WIFSIGNALED(Child_Info)
|
|
#else
|
|
else if (Child_Info.si_code == CLD_DUMPED)
|
|
#endif
|
|
{
|
|
/* L'agent s'est terminé anormallement : on essaie de relancer l'agent */
|
|
|
|
Restart = TRUE;
|
|
|
|
#ifdef LINUX
|
|
sprintf (Debug_Trace, "détection agent n°%d tombé suite à signal %d", i + 1, WTERMSIG(Child_Info));
|
|
#else
|
|
sprintf (Debug_Trace, "détection agent n°%d tombé suite à signal %d", i + 1, Child_Info.si_status);
|
|
#endif
|
|
Info_Trace ();
|
|
}
|
|
else Restart = TRUE;
|
|
|
|
if (Restart == TRUE)
|
|
{
|
|
/* Une tentative de relance a-t'elle déjà été lancée ? */
|
|
|
|
if (Tab_Agent [i].Restarted == TRUE)
|
|
{
|
|
sprintf (Debug_Trace, "abandon de l'agent n°%d", i + 1);
|
|
Info_Trace ();
|
|
Tab_Agent [i].GivenUp = TRUE;
|
|
Nb_GivenUp ++;
|
|
}
|
|
else
|
|
{
|
|
/* On redémarre l'agent */
|
|
|
|
sprintf (Debug_Trace, "relance de l'agent n°%d", i + 1);
|
|
Info_Trace ();
|
|
|
|
Agent_Start (i + 1);
|
|
|
|
Tab_Agent [i].Restarted = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf (Debug_Trace, "abandon de l'agent n°%d", i + 1);
|
|
Info_Trace ();
|
|
Tab_Agent [i].GivenUp = TRUE;
|
|
Nb_GivenUp ++;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Envoi d'un message à un agent */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
int Agent_Msg_Send ( unsigned int Num_Agent, unsigned int Type, int Priority )
|
|
{
|
|
MSGT_Message * Msg;
|
|
char Agent_Port_Name [256];
|
|
MSGT_Port * Agent_Port;
|
|
|
|
/* Ouverture du port de messages privé d'un agent dont on connait le numéro */
|
|
|
|
sprintf (Agent_Port_Name, "Agent_%d_port", Num_Agent);
|
|
|
|
if (MSG_Port_Open (Agent_Port_Name, &Agent_Port, MSGD_OPEN) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible d'ouvrir le port de messages \"%s\"", Agent_Port_Name);
|
|
Info_Trace ();
|
|
return KO;
|
|
}
|
|
|
|
/* Création du message (de la taille d'un message système standard du superviseur aux agents) */
|
|
|
|
if (MSG_Message_Alloc (&Msg, sizeof (Agent_Stat)) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de créer un message destiné à l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
MSG_Port_Close (Agent_Port, MSGD_CLOSE);
|
|
return KO;
|
|
}
|
|
|
|
/* Initialisation des données du message */
|
|
|
|
memset (Msg->Data, 0, Msg->Size);
|
|
|
|
/* Configuration du type de message */
|
|
|
|
if (MSG_Message_Config (Msg, MSGD_CONFIG_TYPE, Type) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de configurer le type du message destiné à l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (Agent_Port, MSGD_CLOSE);
|
|
return KO;
|
|
}
|
|
|
|
/* Configuration de la priorité du message */
|
|
|
|
if (MSG_Message_Config (Msg, MSGD_CONFIG_PRIORITY, Priority) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de configurer la priorité du message destiné à l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (Agent_Port, MSGD_CLOSE);
|
|
return KO;
|
|
}
|
|
|
|
/* Envoi du message avec demande d'accusé réception dans le port du superviseur */
|
|
|
|
if (MSG_Message_Send (MSGD_SUPERVISOR_PORT_NAME, Agent_Port, Msg) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible d'envoyer le message destiné à l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (Agent_Port, MSGD_CLOSE);
|
|
return KO;
|
|
}
|
|
|
|
/* Fermeture du port de messages d'envoi */
|
|
|
|
if (MSG_Port_Close (Agent_Port, MSGD_CLOSE) != MSGS_OK)
|
|
{
|
|
sprintf (Debug_Trace, "impossible de fermer le port de messages de l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
MSG_Message_Free (Msg);
|
|
MSG_Port_Close (Agent_Port, MSGD_CLOSE);
|
|
return KO;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Démarrage d'un agent */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
int Agent_Start ( unsigned int Num_Agent )
|
|
{
|
|
pid_t Agent_Pid;
|
|
|
|
if (Num_Agent > NB_MAX_AGENT)
|
|
{
|
|
strcpy (Debug_Trace, "Limite maximale du nombre d'agents atteinte");
|
|
Info_Trace ();
|
|
return KO;
|
|
}
|
|
|
|
/* On crée un process fils */
|
|
|
|
#ifdef LINUX
|
|
Agent_Pid = fork ();
|
|
#else
|
|
/* Sous Solaris, il faut utiliser la fonction fork1() pour supporter le multi-thread */
|
|
|
|
Agent_Pid = fork1 ();
|
|
#endif
|
|
|
|
if (Agent_Pid != 0)
|
|
{
|
|
/* Code pour le processus père (superviseur) : on référence le processus fils comme nouvel agent */
|
|
|
|
Tab_Agent [Num_Agent - 1].Pid = Agent_Pid;
|
|
Tab_Agent [Num_Agent - 1].Restarted = FALSE;
|
|
Tab_Agent [Num_Agent - 1].GivenUp = FALSE;
|
|
sprintf (Debug_Trace, "lancement de l'agent n°%d", Num_Agent);
|
|
Info_Trace ();
|
|
}
|
|
else
|
|
{
|
|
char sNum_Agent [10];
|
|
|
|
sprintf (sNum_Agent, "%d", Num_Agent);
|
|
|
|
/* Code pour le processus fils (agent) */
|
|
|
|
if (Debug == TRUE)
|
|
execlp (AGENT_PATH, AGENT_PATH, "-id", sNum_Agent, "--debug", NULL, NULL);
|
|
else
|
|
execlp (AGENT_PATH, AGENT_PATH, "-id", sNum_Agent, NULL, NULL);
|
|
|
|
sprintf (Debug_Trace, "erreur lors du lancement de l'agent n°%d (execl: errno %d)", Num_Agent, errno);
|
|
Info_Trace ();
|
|
|
|
exit (KO);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Affichage sur la sortie standard d'erreur d'un message généré par le superviseur */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
void Info_Trace ( void )
|
|
{
|
|
time_t dts;
|
|
struct tm * dt;
|
|
char Current_Date [25];
|
|
|
|
if (Debug)
|
|
{
|
|
/* Récupère la date courante */
|
|
|
|
time (&dts);
|
|
dt = localtime (&dts);
|
|
sprintf (Current_Date, "%02d/%02d/%04d %02d:%02d:%02d", dt->tm_mday, dt->tm_mon + 1, dt->tm_year + 1900, dt->tm_hour, dt->tm_min, dt->tm_sec);
|
|
|
|
fprintf (stderr, "[%s] Superviseur : %s\n", Current_Date, Debug_Trace);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Affiche le statut du superviseur */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
char * Status_Get ( void )
|
|
{
|
|
static char Status_Str [256];
|
|
|
|
sprintf (Status_Str, "Timeout = %d sec / Trace = %s", Timeout, Debug == TRUE ? "On" : "Off");
|
|
|
|
return Status_Str;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Affiche le statut d'un agent */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
char * Agent_Status_Get ( unsigned int Agent_Status, unsigned int Agent_Debug )
|
|
{
|
|
static char Status_Str [256];
|
|
|
|
sprintf (Status_Str, "Statut = %s / Trace = %s", Agent_Status == ACTIVE ? "actif" : "stoppé", Agent_Debug == TRUE ? "On" : "Off");
|
|
|
|
return Status_Str;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
/* Manager d'une liste de messages en attente sur une requête */
|
|
/*--------------------------------------------------------------------------------------------------*/
|
|
NDT_Status Request_List_Manager (va_list Args)
|
|
{
|
|
return NDS_OK;
|
|
}
|