libmsg/util/pingpong_msg.c

544 lines
12 KiB
C
Raw Normal View History

2000-07-28 17:34:22 +02:00
#define MSG_MODE 1
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <shmem.h>
#include <msg.h>
VER_INFO_EXPORT (pingpong, "1.0", "", __FILE__, "severin")
#define DEFAULT_TIMER 60 /* Dur<75>e par d<>faut du test (en secondes) */
#define DEFAULT_WINSIZE 100 /* Taille par d<>faut de la fen<65>tre de messages */
#define DEFAULT_MSGSIZE 100 /* Taille par d<>faut de chaque message */
#define FATHER_KEY "father_port" /* Cl<43> du port de messages d'<27>coute du p<>re */
#define CHILD_KEY "child_port" /* Cl<43> du port de messages d'<27>coute du fils */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*----------------------------------------------------------------*/
MSGT_Port * My_Port, * Its_Port;
unsigned int Child_Pid, Father_Pid, Its_Pid, My_Pid;
int Verbose, Tree;
unsigned int Win_Size, Msg_Size, Cpt_Msg, Timer;
SMT_DSH * DSH;
SMT_Heap * Heap;
int End_Test, End_Sigum;
char str [100];
void stop_test (int);
void stop_father (void);
void stop_child (void);
void clean (int);
void trace (char *);
void print_result (void);
void parse_arg (int, char **);
extern char * strdup (const char *);
extern kill (int, int);
/*----------------------------------------------------------------*/
int main (int argc, char ** argv)
{
unsigned int i;
MSGT_Message * Msg;
/* R<>cup<75>ration des arguments de la ligne de commande */
parse_arg (argc, argv);
/* R<>cup<75>ration du num<75>ro de processus courant */
Father_Pid = getpid ();
/* Cr<43>ation d'un process fils avec qui dialoguer */
if ((Child_Pid = fork ()) != 0)
{
Heap = NULL;
/*--------- Code pour le process p<>re -----------*/
/* Ouverture de la librairie libmsg */
if (MSG_Library_Open (0, NULL, MSGD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK) return 0;
Its_Pid = Child_Pid;
My_Pid = Father_Pid;
signal (SIGINT, stop_test);
signal (SIGUSR1, stop_test);
/* Cr<43>ation d'un port de messages priv<69> pour le p<>re */
if (MSG_Port_Open (FATHER_KEY, &My_Port, MSGD_CREATE) != MSGS_OK)
{
fprintf (stderr, "Unable to create a message port for the father process\n");
clean (TRUE);
return 0;
}
else if (Verbose)
{
sprintf (str, "Message port \"%s\" created", My_Port->Name);
trace (str);
}
if (Tree == TRUE)
{
if (MSG_Port_Config (My_Port, MSGD_CONFIG_MSGQUEUE, NDD_DS_TREE) != MSGS_OK)
{
fprintf (stderr, "Unable to create a message port for the father process\n");
clean (TRUE);
return 0;
}
}
/* On attend que le fils ait cr<63><72> son port de messages */
sleep (1);
/* R<>cup<75>ration du port de messages priv<69> du fils */
if (MSG_Port_Open (CHILD_KEY, &Its_Port, MSGD_OPEN) != MSGS_OK)
{
fprintf (stderr, "Unable to retrieve the message port of the child process\n");
clean (TRUE);
return 0;
}
else if (Verbose)
{
sprintf (str, "Message port \"%s\" retrieved", Its_Port->Name);
trace (str);
}
/* Initialisation du Timer */
signal (SIGALRM, stop_test);
alarm (Timer);
/* D<>but du test : traitement des messages */
fprintf (stdout, "Testing LIBMSG for %d second(s) with %d message(s) of %d byte(s)...\n", Timer, Win_Size, Msg_Size);
/* Cr<43>ation et envoi de tous les messages au fils */
for (i = 0; i < Win_Size; i++)
{
if (MSG_Message_Alloc (&Msg, Msg_Size) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d created", i);
trace (str);
}
if (MSG_Message_Send (My_Port->Name, Its_Port, Msg) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d sent to port \"%s\"", i, Its_Port->Name);
trace (str);
}
}
}
}
Cpt_Msg = 0;
while (End_Test == FALSE)
{
/* R<>ception de messages */
if (MSG_Message_Receive (My_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d received from port \"%s\"", Msg->Type, My_Port->Name);
trace (str);
}
Cpt_Msg++;
/* R<>envoi du message au fils */
if (MSG_Message_Reply (Msg) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d replied", Msg->Type);
trace (str);
}
}
}
}
stop_father ();
}
else
{
/*---------- Code pour le process fils ----------*/
Heap = NULL;
My_Pid = getpid ();
Its_Pid = Father_Pid;
/* Ouverture de la librairie libmsg */
if (MSG_Library_Open (0, NULL, SMD_OPEN | MSGD_DEBUG_ALL) != MSGS_OK) return 0;
/* Trap du signal SIGUSR1 envoy<6F> par le process p<>re <20> la fin du test */
signal (SIGUSR1, stop_test);
signal (SIGINT, stop_test);
/* Cr<43>ation d'un port de messages priv<69> pour le fils */
if (MSG_Port_Open (CHILD_KEY, &My_Port, MSGD_CREATE) != MSGS_OK)
{
fprintf (stderr, "Unable to create message port for the child process\n");
clean (TRUE);
return 0;
}
else if (Verbose)
{
sprintf (str, "Message port \"%s\" created", My_Port->Name);
trace (str);
}
/* On attend que le p<>re ait cr<63><72> son port de messages priv<69> */
sleep (1);
/* R<>cup<75>ration du port de messages priv<69> du p<>re */
if (MSG_Port_Open (FATHER_KEY, &Its_Port, MSGD_OPEN) != MSGS_OK)
{
fprintf (stderr, "Unable to retrieve the message port of the father process\n");
clean (TRUE);
return 0;
}
else if (Verbose)
{
sprintf (str, "Message port \"%s\" retrieved", Its_Port->Name);
trace (str);
}
/* Traitement des messages */
while (End_Test == FALSE)
{
/* R<>ception de messages */
if (MSG_Message_Receive (My_Port, MSGD_NO_TYPE, &Msg, MSGD_WAIT) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d received from port \"%s\"", Msg->Type, My_Port->Name);
trace (str);
}
/* Renvoi du message */
if (MSG_Message_Reply (Msg) == MSGS_OK)
{
if (Verbose)
{
sprintf (str, "Message %d replied", Msg->Type);
trace (str);
}
}
}
}
stop_child ();
}
return 0;
}
/*----------------------------------------------------------------*/
void stop_test (int signum)
{
End_Sigum = signum;
End_Test = TRUE;
}
/*----------------------------------------------------------------*/
void stop_father (void)
{
switch (End_Sigum)
{
case SIGINT:
/* Fin initi<74>e par l'utilisateur : m<>nage simple */
case SIGUSR1:
/* Fin anormale en provenance du fils : m<>nage simple */
sprintf (str, "Signal USR1 received from child process");
trace (str);
clean (FALSE);
break;
case SIGALRM:
/* Fin normale : m<>nage + stop du fils + affichage du r<>ultat */
clean (TRUE);
print_result ();
break;
default:
/* Fin anormale sur le process p<>re : m<>nage + avertit le process fils */
clean (TRUE);
break;
}
exit (1);
}
/*----------------------------------------------------------------*/
void print_result (void)
{
/* Affichage du r<>sultat du test */
fprintf (stdout, "%d message(s) exchanged (%d msg/sec)\n", Cpt_Msg, (int)(Cpt_Msg / Timer));
}
/*----------------------------------------------------------------*/
void stop_child (void)
{
switch (End_Sigum)
{
case SIGINT:
/* Fin initi<74>e par l'utilisateur : m<>nage simple */
case SIGUSR1:
/* Fin initi<74>e par le process p<>re : m<>nage simple */
sprintf (str, "Signal USR1 received from father process");
trace (str);
clean (FALSE);
break;
default:
/* Fin anormale sur le process fils : m<>nage + avertit le process p<>re */
clean (TRUE);
break;
}
exit (0);
}
/*----------------------------------------------------------------*/
void clean (int warn)
{
/* On avertit l'autre process */
if (warn == TRUE) kill (Its_Pid, SIGUSR1);
/* Fermeture du port de l'autre process */
if (Its_Port != NULL)
{
char Port_Name [256];
strcpy (Port_Name, Its_Port->Name);
MSG_Port_Close (Its_Port, MSGD_CLOSE);
if (Verbose)
{
sprintf (str, "Message port \"%s\" closed", Port_Name);
trace (str);
}
}
/* Destruction du port de messages priv<69> */
if (My_Port != NULL)
{
char Port_Name [256];
strcpy (Port_Name, My_Port->Name);
/* On attend un peu afin que l'autre process puisse fermer mon port de messages */
sleep (1);
MSG_Port_Close (My_Port, MSGD_DESTROY);
if (Verbose)
{
sprintf (str, "Message port \"%s\" removed", Port_Name);
trace (str);
}
}
MSG_Library_Close (MSGD_CLOSE);
}
/*----------------------------------------------------------------*/
void trace (char * s)
{
time_t dts;
struct tm * dt;
char Current_Date [25];
char strace [100];
/* Get current date */
time (&dts);
dt = localtime (&dts);
sprintf (Current_Date, "%04d/%02d/%02d %02d:%02d:%02d", dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec);
sprintf (strace, "Process %d - %s : %s\n", My_Pid, Current_Date, s);
fprintf (stderr, strace);
fflush (stderr);
}
/*----------------------------------------------------------------*/
void parse_arg (int argc, char **argv)
{
int i;
Verbose = Tree = FALSE;
for (i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h"))
{
fprintf (stdout, "Usage : %s [options]\n", argv[0]);
fprintf (stdout,"options :\n");
fprintf (stdout, "\t --help | -h\n");
fprintf (stdout, "\t --clean\n");
fprintf (stdout, "\t --verbose\n");
fprintf (stdout, "\t --duration <time in seconds> (default is %d)\n", DEFAULT_TIMER);
fprintf (stdout, "\t --window <message number> (default is %d)\n", DEFAULT_WINSIZE);
fprintf (stdout, "\t --message <message size> (default is %d bytes)\n", DEFAULT_MSGSIZE);
fprintf (stdout, "\t --tree\n");
fprintf (stdout, "\t --version [-v]\n");
exit (1);
}
if (!strcmp (argv[i], "--clean"))
{
if (MSG_Library_Open (NULL, NULL, MSGD_OPEN) == MSGS_OK)
{
if (MSG_Port_Open (FATHER_KEY, &My_Port, MSGD_OPEN) == MSGS_OK)
MSG_Port_Close (My_Port, MSGD_DESTROY);
if (MSG_Port_Open (CHILD_KEY, &Its_Port, MSGD_OPEN) == MSGS_OK)
MSG_Port_Close (Its_Port, MSGD_DESTROY);
MSG_Library_Close (MSGD_CLOSE);
}
exit (1);
}
if (!strcmp (argv[i], "--verbose"))
{
Verbose = TRUE;
continue;
}
if (!strcmp (argv[i], "--tree"))
{
Tree = TRUE;
continue;
}
if (!strcmp (argv[i], "--duration"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Timer = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--window"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Win_Size = atoi (argv[i]);
continue;
}
if (!strcmp (argv[i], "--message"))
{
i++;
if (i == argc)
{
fprintf (stderr, "Missing argument after %s\n", argv[i - 1]);
exit (0);
}
Msg_Size = 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);
}
}
fprintf (stdout, "Unknown option '%s'\n", argv[i]);
exit (0);
}
if (Timer <= 0) Timer = DEFAULT_TIMER;
if (Win_Size <= 0) Win_Size = DEFAULT_WINSIZE;
if (Msg_Size <= 0) Msg_Size = DEFAULT_MSGSIZE;
}