/************************************************************************/
/* fichier: pg_administrator.c						*/
/*									*/
/* @(#)PGPVM V2 administrator\						*/
/* @(#)June 1996\							*/
/*									*/
/************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include "pvm3.h"

/************************************************************************/
/* useful Macros */

#define TRACEBUFSIZ 1400

#define ADMINTAG  0x22cb173a
#define TRACETAG 0x22cb173b
#define ENDPROG 0x22cb173c
#define NEWTASKSNB 0x22cb173d
#define ADMINTID 0x22cb173d

/************************************************************************/
/*variables*/

int you=0;     /* gives a me number to each administrated task	*/
int nbt=0;     /* nb of tasks (administrated or not) existing	*/
int youarenew;
struct timeval t0;		/* Reference timestamp		*/
struct timezone *tz=NULL;	/* Temp timezone variable	*/
FILE *logfile=stderr;		/* Log file name		*/
char logname[256];
int nbtmax=1024;
int **tidstable,tidstableptr=0;

char *outfilenm=NULL;     /* optional filename			*/
char *prefixfilenm=NULL;  /* optional prefix filename		*/

int nbt_admin_max;
int *tab_lim_proc;        /* 1->No occupe, 0->No libre */
int *tab_lim_proc_tid;    /* tablo des derniers tids pour chaque No de tache */
int MAX_lim_proc=128;     /* limite de ParaGraph */
int tab_lim_proc_ind=0, nblipro=0, flagerror=1;

/************************************************************************/
#ifdef __STDC__
int search(int tid)
#else
int search(tid)
int tid;
#endif

{
int i;

for (i=0;i<tidstableptr;i++)
    if (tidstable[0][i]==tid) return (i);
return (-1);
}

/************************************************************************/
#ifdef __STDC__
void main(void)
#else
main()
#endif


{
    int n,i,j;
    struct timeval t1;
    int numt,siz, msg, go=1,searchrep;
    int bufid, info, bytes, msgtag, tidfrom,tidfromind, ntask;
    FILE *fd,*fout;
    int ent,sec,msec,tidme,tidyou,tag,lengh,sec2,msec2,tag2;
    int * tabletmp;
    char outfile[256];
    int let11=0;

    int f2;
    char buf[TRACEBUFSIZ];
    struct pvmtaskinfo **taskp;
    int mytid;


    mytid=pvm_mytid();
    gettimeofday(&t0,tz);

    pvm_recv(pvm_parent(),ADMINTID); 
    
    pvm_upkstr(outfile);
    pvm_upkint(&nbt_admin_max,1,1);

    if (strcmp("",outfile) == 0)
	sprintf(logname, "/tmp/pgfile.%d.pre",getuid());
    else
	sprintf(logname, "%s.pre",outfile);
    fd = fopen (logname,  "w+");
    if (fd!=0) 
	{
	    logfile=fd;
	    setvbuf(logfile, NULL, _IOFBF, 10240);
	}
    else 
	printf("pg_tids:unable to open logfile\n");
    fclose(fd);
    if ((f2 = open(logname,O_RDWR | O_APPEND, 0644)) == -1) 
	printf("pg_exit: can't reopen MAIN tracefile");
    

    tidstable=(int**)malloc(2*sizeof(int*));
    tidstable[0]=(int*)malloc(nbtmax*sizeof(int));
    tidstable[1]=(int*)malloc(nbtmax*sizeof(int));
    
    tidstable[0][0]=pvm_parent();
    tidstable[1][0]=-1;
    
    if (nbt_admin_max) 
    	{
	    tab_lim_proc=(int*)calloc(MAX_lim_proc,sizeof(int));
	    tab_lim_proc_tid=(int*)calloc(MAX_lim_proc,sizeof(int));
	}

    nbt++;
    tidstableptr++;
    msgtag=0;
    while(go)
	{
	    bufid=pvm_recv(-1,-1);
	    info=pvm_bufinfo(bufid,&bytes,&msgtag,&tidfrom);
	    tidfromind=search(tidfrom);
	    switch(msgtag)
		{
		case NEWTASKSNB :
		    pvm_upkint(&numt, 1, 1);
		    tabletmp=(int *)malloc(sizeof(int)*numt);
		    pvm_upkint(tabletmp, numt, 1);
		    nbt+=numt;
		    i=tidstableptr+numt;
		    j=0;
		    for(;tidstableptr<i;tidstableptr++)
			{
			    if (tidstableptr>=nbtmax)
				{
				    nbtmax+=1024;
				    tidstable[0]=(int*)realloc(tidstable[0],nbtmax*sizeof(int));
				    tidstable[1]=(int*)realloc(tidstable[1],nbtmax*sizeof(int));
				}
			    tidstable[0][tidstableptr]=tabletmp[j++];
			    tidstable[1][tidstableptr]=-1;
			}
		    free(tabletmp);
		    break;
		    
		case ADMINTAG :
		    if (nbt_admin_max) 
			{
			    nblipro++;
			    if (nblipro>nbt_admin_max)
				{
				    if (flagerror)
					{
					    fprintf(stderr,"Warning: nbt_admin_max Error: %d too small.",nbt_admin_max);
					    flagerror=0;
					}
				    nbt_admin_max++;
				}
			    if (nblipro>128)
				fprintf(stderr,"Warning: 128 nodes cannot be administrated by ParaGraph");
				/*le programme peut planter ici si on demande plus de 128 processus administres*/
			    
			    while (tab_lim_proc[tab_lim_proc_ind]==1)
				{
				    if (tab_lim_proc_ind==nbt_admin_max-1)
					tab_lim_proc_ind=0;
				    else tab_lim_proc_ind++;
				}
			    tab_lim_proc[tab_lim_proc_ind]=1;
			    tab_lim_proc_tid[tab_lim_proc_ind]=tidfrom;
			    tidstable[1][tidfromind]=tab_lim_proc_ind;
			    if (tab_lim_proc_ind==nbt_admin_max-1)
				tab_lim_proc_ind=0;
			    else tab_lim_proc_ind++;
			}
		    else tidstable[1][tidfromind]=1;
		    pvm_initsend(PvmDataDefault);
		    pvm_pklong(&t0.tv_sec,1,1);
		    pvm_pklong(&t0.tv_usec,1,1);
		    gettimeofday(&t1,tz);
		    pvm_pklong(&t1.tv_sec,1,1);
		    pvm_pklong(&t1.tv_usec,1,1);
		    pvm_send(tidfrom,ADMINTAG);
		    break;

		case TRACETAG :
		    pvm_upkint(&msg, 1, 1);
		    if (msg)    /* si c est un pg_exit (et pas un pg_close) */
		    	{
			    go=(--nbt);
			    if (nbt_admin_max) 
				{
				    nblipro--;
				    tab_lim_proc[tidstable[1][tidfromind]]=0;
				}
		    	}
		    pvm_recv (tidfrom, TRACETAG);
		    pvm_upkint(&n, 1, 1);
		    while (n != -1)
			{
			    pvm_upkbyte(buf, n, 1);
			    if (write(f2, buf, n) != n) 
				printf("pg_exit: write error while writing\n");
			    pvm_recv (tidfrom, TRACETAG);
			    pvm_upkint(&n, 1, 1);		
			}
		    break;
		case ENDPROG :
		    go=(--nbt);
		    if (nbt_admin_max) 
		    	{
			    nblipro--;
			    tab_lim_proc[tidstable[1][tidfromind]]=0;
		    	}
		    break;
		}
	} 
    close(f2);

/* task numbering for the tracefile */
    
    if (! nbt_admin_max) 
	    for (i=0;i<tidstableptr;i++)
		{
	    	if (tidstable[1][i] == 1 )
			tidstable[1][i]=you++;
		}

/* File modifications: replace tid by me */

    fd = fopen (logname,  "r");
    if (strcmp("",outfile) == 0)
	sprintf(logname, "/tmp/pgfile.%d",getuid());
    else
	sprintf(logname, "%s",outfile);

    fout=fopen (logname,  "w+");
    
    
    if (! nbt_admin_max)
	while (fscanf(fd,"%d",&ent)!=EOF)
	    {
		switch(ent)
		    {
		    case 1 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d ",&n);
			fprintf(fout,"1 %d %d %d 0 0 0\n",sec,msec,tidstable[1][search(tidme)]);
			break;
		    case 7 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d\n",&tag);
			
			fscanf(fd,"%d ",&ent);
			fscanf(fd,"%d ",&sec2);
			fscanf(fd,"%d ",&msec2);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&tidyou);
			fscanf(fd,"%d ",&tag2);
			fscanf(fd,"%d\n",&lengh);
			if ((searchrep=tidstable[1][search(tidyou)])== -1) break;
			fprintf(fout,"7 %d %d %d %d\n",sec,msec,tidstable[1][search(tidme)],tag);
			fprintf(fout,"8 %d %d %d %d %d %d\n",sec2,msec2,tidstable[1][search(tidme)],searchrep,tag2,lengh);
			break;
		    case 19 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d\n",&n);
			fprintf(fout,"19 %d %d %d 0\n",sec,msec,tidstable[1][search(tidme)]);
			break;
		    case 4 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&tidyou);
			fscanf(fd,"%d ",&tag);
			fscanf(fd,"%d\n",&lengh);
			if ((searchrep=tidstable[1][search(tidyou)])== -1)
			    break;
			fprintf(fout,"4 %d %d %d %d %d %d\n",sec,msec,tidstable[1][search(tidme)],searchrep,tag,lengh); 
			let11=1;
			break;
		    case 11 :
			
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d\n",&n);
			if (let11) fprintf(fout,"11 %d %d %d 0 0\n",sec,msec,tidstable[1][search(tidme)]);
			
			fscanf(fd,"%d ",&ent);
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d\n",&n);
			if (let11) fprintf(fout,"11 %d %d %d 0 0\n",sec,msec,tidstable[1][search(tidme)]);
			let11=0;
			break;
			
		    case 23 :
			fscanf(fd,"%d %d %d %d -1 0/*\n*/",&sec,&msec,&tidme,&n);
			fprintf(fout,"23 %d %d %d %d -1 0\n",sec,msec,tidstable[1][search(tidme)],n);
			break;
			
		    case 24 :
			fscanf(fd,"%d %d %d %d -1 0/*\n*/",&sec,&msec,&tidme,&n);
			fprintf(fout,"24 %d %d %d %d -1 0\n",sec,msec,tidstable[1][search(tidme)],n);
			break;
			
		    }
	    }
    
    if (nbt_admin_max)
	while (fscanf(fd,"%d",&ent)!=EOF)
	    {
		switch(ent)
		    {
		    case 1 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%*d ");
			fscanf(fd,"%*d ");
			fscanf(fd,"%*d ");
			tidfromind=search(tidme);
			if (tab_lim_proc[tidstable[1][tidfromind]]==0)
			    {
		    		tab_lim_proc[tidstable[1][tidfromind]]=1;
		    		fprintf(fout,"1 %d %d %d 0 0 0\n",sec,msec,tidstable[1][tidfromind]);
			    }
			break;
		    case 7 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d\n",&tag);
			
			fscanf(fd,"%d ",&ent);
			fscanf(fd,"%d ",&sec2);
			fscanf(fd,"%d ",&msec2);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&tidyou);
			fscanf(fd,"%d ",&tag2);
			fscanf(fd,"%d\n",&lengh);
			if ((searchrep=tidstable[1][search(tidyou)])== -1) break;
			fprintf(fout,"7 %d %d %d %d\n",sec,msec,tidstable[1][search(tidme)],tag);
			fprintf(fout,"8 %d %d %d %d %d %d\n",sec2,msec2,tidstable[1][search(tidme)],searchrep,tag2,lengh);
			break;
		    case 19 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%*d\n");
			tidfromind=search(tidme);
			if (tab_lim_proc_tid[tidstable[1][tidfromind]]==tidme)
			    fprintf(fout,"19 %d %d %d 0\n",sec,msec,tidstable[1][tidfromind]);
			break;
		    case 4 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&tidyou);
			fscanf(fd,"%d ",&tag);
			fscanf(fd,"%d\n",&lengh);
			if ((searchrep=tidstable[1][search(tidyou)])== -1)
			    break;
			fprintf(fout,"4 %d %d %d %d %d %d\n",sec,msec,tidstable[1][search(tidme)],searchrep,tag,lengh); 
			let11=1;
			break;
		    case 11 :
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d\n",&n);
			if (let11) fprintf(fout,"11 %d %d %d 0 0\n",sec,msec,tidstable[1][search(tidme)]);
			
			fscanf(fd,"%d ",&ent);
			fscanf(fd,"%d ",&sec);
			fscanf(fd,"%d ",&msec);
			fscanf(fd,"%d ",&tidme);
			fscanf(fd,"%d ",&n);
			fscanf(fd,"%d\n",&n);
			if (let11) fprintf(fout,"11 %d %d %d 0 0\n",sec,msec,tidstable[1][search(tidme)]);
			let11=0;
			break;
			
			
		    case 23 :
			fscanf(fd,"%d %d %d %d -1 0\n",&sec,&msec,&tidme,&n);
			fprintf(fout,"23 %d %d %d %d -1 0\n",sec,msec,tidstable[1][search(tidme)],n);
			break;
			
		    case 24 :
			fscanf(fd,"%d %d %d %d -1 0\n",&sec,&msec,&tidme,&n);
			fprintf(fout,"24 %d %d %d %d -1 0\n",sec,msec,tidstable[1][search(tidme)],n);
			break;
			
		    }
	    }
    
    fclose(fd); 

    if (strcmp("",outfile) == 0)
	sprintf(logname, "/tmp/pgfile.%d.pre",getuid());
    else
	sprintf(logname, "%s.pre",outfile);
    unlink(logname);
    pvm_exit();
}
