#include #include #include #include #include #define MSG_MODE 1 #include #include #include VER_INFO_EXPORT (logagent, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: smas $") void Parse_Arg (int , char **); void Event_Msg_Process ( MSGT_Message * ); void System_Msg_Process ( MSGT_Message * ); void Info_Trace ( void ); unsigned int End_Agent, Nb_Event, Nb_System_Msg; MSGT_Port * Private_Port, * Event_Port; MSGT_PortList * Private_PortList; unsigned int Num_Agent, Status, Debug; char Debug_Trace [512]; /*--------------------------------------------------------------------------------------------------*/ /* Fonction principale */ /*--------------------------------------------------------------------------------------------------*/ int main ( int argc, char ** argv ) { MSGT_Message * Msg; char Private_Port_Name [256]; /* Récupération des arguments de la ligne de commande */ Parse_Arg (argc, argv); /* Démarrage de l'agent */ Status = ACTIVE; /* Ouverture de la librairie LIBMSG */ if (MSG_Library_Open (NULL, NULL, MSGD_OPEN) != MSGS_OK) { strcpy (Debug_Trace, "impossible d'ouvrir la librairie LIBMSG"); Info_Trace (); return KO; } /* Ouverture du port de message dans lequel sont envoyés les événements */ if (MSG_Port_Open (LOGD_EVENT_PORT_NAME, &Event_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) { strcpy (Debug_Trace, "impossible d'ouvrir le port de messages des événements"); Info_Trace (); MSG_Library_Close (MSGD_CLOSE); return KO; } /* Ouverture (cas du restart) ou création du port privé de l'agent */ sprintf (Private_Port_Name, "Agent_%d_port", Num_Agent); if (MSG_Port_Open (Private_Port_Name, &Private_Port, MSGD_OPEN | MSGD_CREATE) != MSGS_OK) { strcpy (Debug_Trace, "impossible de d'ouvrir ou de créer mon port de messages privé"); Info_Trace (); MSG_Port_Close (Event_Port, MSGD_CLOSE); MSG_Library_Close (MSGD_CLOSE); return KO; } /* Création d'une liste de ports (port public + port privé) que l'agent va écouter */ if (MSG_PortList_Open (&Private_PortList) != MSGS_OK) { strcpy (Debug_Trace, "impossible de créer ma liste de ports"); Info_Trace (); MSG_Port_Close (Event_Port, MSGD_CLOSE); MSG_Port_Close (Private_Port, MSGD_DESTROY); MSG_Library_Close (MSGD_CLOSE); return KO; } if (MSG_PortList_Port_Add (Private_PortList, Private_Port) != MSGS_OK || MSG_PortList_Port_Add (Private_PortList, Event_Port) != MSGS_OK) { strcpy (Debug_Trace, "impossible d'ajouter les ports privé et public à ma liste de ports"); Info_Trace (); MSG_PortList_Close (Private_PortList); MSG_Port_Close (Event_Port, MSGD_CLOSE); MSG_Port_Close (Private_Port, MSGD_DESTROY); MSG_Library_Close (MSGD_CLOSE); return KO; } sprintf (Debug_Trace, "démarrage en mode trace %s", Debug == TRUE ? "activé" : "désactivé"); Info_Trace (); /* Boucle principale */ Nb_System_Msg = 0; Nb_Event = 0; End_Agent = FALSE; while (End_Agent == FALSE) { unsigned int Expected_Type; if (Status == ACTIVE) { /* Quand l'agent est actif, il traite tous les types de messages */ Expected_Type = MSGD_NO_TYPE; } else { /* Quand l'agent est stoppé, il ne traite que les messages système */ Expected_Type = MSGD_SYSTEM_GENERIC; } /* Ecoute des ports de messages de la liste */ if (MSG_PortList_Listen (Private_PortList, Expected_Type, &Msg, MSGD_WAIT) != MSGS_OK) { strcpy (Debug_Trace, "impossible de réceptionner un message depuis l'un des ports écoutés"); Info_Trace (); MSG_PortList_Close (Private_PortList); MSG_Port_Close (Private_Port, MSGD_DESTROY); MSG_Library_Close (MSGD_CLOSE); return KO; } /* Traitement du message */ switch (Msg->Type) { case LOGD_EVENT_MSG_TYPE: /* Il s'agit d'un événement */ Event_Msg_Process (Msg); Nb_Event ++; break; default: /* Il s'agit d'un message système */ System_Msg_Process (Msg); Nb_System_Msg ++; break; } } /* Suppression de la liste de ports de l'agent */ if (MSG_PortList_Close (Private_PortList) != MSGS_OK) { strcpy (Debug_Trace, "impossible de supprimer ma liste de ports"); Info_Trace (); MSG_Port_Close (Private_Port, MSGD_DESTROY); MSG_Library_Close (MSGD_CLOSE); return KO; } /* Suppression du port privé de l'agent */ if (MSG_Port_Close (Private_Port, MSGD_DESTROY) != MSGS_OK) { strcpy (Debug_Trace, "impossible de supprimer mon port de messages privé"); Info_Trace (); MSG_Library_Close (MSGD_CLOSE); return KO; } /* Fermeture de la librairie */ if (MSG_Library_Close (MSGD_CLOSE) != MSGS_OK) { strcpy (Debug_Trace, "impossible de fermer la librairie LIBMSG"); Info_Trace (); return KO; } strcpy (Debug_Trace, "terminé"); Info_Trace (); return OK; } /*--------------------------------------------------------------------------------------------------*/ /* Récupération de la ligne de commande */ /*--------------------------------------------------------------------------------------------------*/ void Parse_Arg (int argc, char ** argv) { int i; Debug = FALSE; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) { fprintf (stderr, "Usage : %s [ [--help|-h] | --version [-v] | -id [--debug] ]\n", argv [0]); exit (1); } if (!strcmp (argv[i], "-id")) { i++; if (i == argc) { fprintf (stderr, "Argument manquant après \"%s\"\n", argv[i - 1]); exit (0); } Num_Agent = atoi (argv[i]); continue; } if (!strcmp (argv[i], "--version")) { if (i+1 < argc && !strcmp (argv[i+1], "-v")) { VER_Object_Print (stdout, VERD_VERBOSE); exit (0); } else { VER_Object_Print (stdout, VERD_MINIMAL); exit (0); } } if (!strcmp (argv[i], "--debug")) { Debug = TRUE; continue; } fprintf (stderr, "Option invalide \"%s\"\n", argv[i]); exit (0); } if (Num_Agent == 0) { fprintf (stderr, "Option \"-id\" manquante ou bien valeur incorrecte (doit être > 0)\n"); exit (0); } } /*--------------------------------------------------------------------------------------------------*/ /* Traitement d'un message contenant un événement */ /*--------------------------------------------------------------------------------------------------*/ void Event_Msg_Process (MSGT_Message * Msg) { LOGT_Event_Msg_Data * Msg_Data; unsigned int Length, Event_Type; char Event_Name [256]; char Cd_Support [256]; char Data_Name [256]; char Data_Value [256]; unsigned int i; char * Event_Data_Ptr; /* Récupération des données de l'entête de l'événement */ Msg_Data = (LOGT_Event_Msg_Data *)(Msg->Data); /* Vérification de la version du format */ if (strcmp (Msg_Data->Header.Version, EVENT_FORMAT_VERSION)) { sprintf (Debug_Trace, "version du format de message \"%s\" incorrect (\"%s\" attendu)", Msg_Data->Header.Version, EVENT_FORMAT_VERSION); Info_Trace (); /* Suppression du message */ MSG_Message_Free (Msg); return; } sprintf (Debug_Trace, "réception d'un événement de la part du processus %d (module %d/%d)", Msg_Data->Header.Sending_Pid, Msg_Data->Header.ModuleId, Msg_Data->Header.Master_ModuleId); /* Récupération de l'identifiant du type d'événement */ Event_Type = Msg_Data->Event_Type; /* Récupération du nom de l'événement */ Event_Data_Ptr = &(Msg_Data->Event_Data); i = 0; Length = (unsigned int)(Event_Data_Ptr [i]); strncpy (Event_Name, Event_Data_Ptr + i + 1, Length); Event_Name [Length] = (char)0; i += 1 + Length; if (Debug == TRUE) fprintf (stderr, "%s\nEvénement \"%s\" (type=%d):", Debug_Trace, Event_Name, Event_Type); Length = (unsigned int)(Event_Data_Ptr [i]); strncpy (Cd_Support, Event_Data_Ptr + i + 1, Length); Cd_Support [Length] = (char)0; if (Debug == TRUE) fprintf (stderr, "%s\n\t- support=\"%s\"\n", Debug_Trace, Cd_Support); i += 1 + Length; /* Récupération des macro-données */ while (i < Msg_Data->Data_Size) { /* Récupération du nom de la macro-donnée */ Length = (unsigned int)(Event_Data_Ptr [i]); strncpy (Data_Name, Event_Data_Ptr + i + 1, Length); Data_Name [Length] = (char)0; i += 1 + Length; if (i < Msg->Size) { /* Récupération de la valeur de la macro-donnée */ Length = (unsigned int)(Event_Data_Ptr [i]); strncpy (Data_Value, Event_Data_Ptr + i + 1, Length); Data_Value [Length] = (char)0; i += 1 + Length; } else { strcpy (Debug_Trace, "mauvais format d'événement"); Info_Trace (); } if (Debug == TRUE) fprintf (stderr, "\t- %s=%s\n", Data_Name, Data_Value); } /* Traitement de l'événement ... ... ... */ /* Renvoi du message à l'envoyeur */ if (MSG_Message_Reply (Msg) != MSGS_OK) { strcpy (Debug_Trace, "impossible de renvoyer le message de l'événement à son envoyeur"); Info_Trace (); } } /*--------------------------------------------------------------------------------------------------*/ /* Traitement d'un message système par un agent */ /*--------------------------------------------------------------------------------------------------*/ void System_Msg_Process (MSGT_Message * Msg) { /* Pour accuser réception du message système, on commence par remplir les données liées à l'agent */ ((Agent_Stat *)(Msg->Data))->Num_Agent = Num_Agent; ((Agent_Stat *)(Msg->Data))->Pid = getpid (); switch (Msg->Type) { case MSGD_SYSTEM_STOP_REQUEST: if (Status == ACTIVE) { /* On indique que la requête a bien été prise en compte */ ((Agent_Stat *)(Msg->Data))->Answer = TRUE; /* Pause de l'agent jusqu'à réception d'un message MSGD_SYSTEM_CONTINUE_REQUEST */ Status = STOPPED; strcpy (Debug_Trace, "pause"); Info_Trace (); } else { /* On indique que la requête n'a pas été prise en compte */ ((Agent_Stat *)(Msg->Data))->Answer = FALSE; } break; case MSGD_SYSTEM_CONTINUE_REQUEST: if (Status == STOPPED) { /* On indique que la requête a bien été prise en compte */ ((Agent_Stat *)(Msg->Data))->Answer = TRUE; /* Reprise de l'agent */ Status = ACTIVE; strcpy (Debug_Trace, "reprise"); Info_Trace (); } else { /* On indique que la requête n'a pas été prise en compte */ ((Agent_Stat *)(Msg->Data))->Answer = FALSE; } break; case MSGD_SYSTEM_SHUTDOWN_REQUEST: /* Fin de la boucle principale de l'agent */ End_Agent = TRUE; strcpy (Debug_Trace, "terminaison en cours..."); Info_Trace (); break; case MSGD_SYSTEM_STATUS_REQUEST: /* On informe le superviseur sur l'état dans lequel on se trouve */ ((Agent_Stat *)(Msg->Data))->Status = Status; ((Agent_Stat *)(Msg->Data))->Debug = Debug; break; case MSGD_SYSTEM_INFO_REQUEST: /* On informe le superviseur sur le nombre de messages (système et événement) traités */ ((Agent_Stat *)(Msg->Data))->Cpt_Event = Nb_Event; ((Agent_Stat *)(Msg->Data))->Cpt_System = Nb_System_Msg; break; case MSGD_SYSTEM_TRACEON_REQUEST: Debug = TRUE; strcpy (Debug_Trace, "activation du mode trace"); Info_Trace (); break; case MSGD_SYSTEM_TRACEOFF_REQUEST: strcpy (Debug_Trace, "désactivation du mode trace"); Info_Trace (); Debug = FALSE; break; default : /* On indique que la requête n'a pas été prise en compte */ ((Agent_Stat *)(Msg->Data))->Answer = FALSE; break; } /* On accuse réception du message */ MSG_Message_Reply (Msg); } /*--------------------------------------------------------------------------------------------------*/ /* Affichage sur la sortie standard d'erreur d'un message généré par un agent */ /*--------------------------------------------------------------------------------------------------*/ void Info_Trace ( void ) { time_t dts; struct tm * dt; char Current_Date [25]; if (Debug == TRUE) { /* Récupère la date courante */ time (&dts); dt = localtime (&dts); sprintf (Current_Date, "%02d/%02d/%04d %02d:%02d:%02d", dt->tm_mday, dt->tm_mon + 1, dt->tm_year + 1900, dt->tm_hour, dt->tm_min, dt->tm_sec); fprintf (stderr, "[%s] Agent n°%d : %s\n", Current_Date, Num_Agent, Debug_Trace); } }