/*               Main program for Test with two servers		    two_prog_c.c
**		 --------------------------------------
**
**
**  This program tests:
**
**	o   That a program can be a client to more than one server;
**	o   That explicit opening and closing work (more than once)
**	o   That closes do not have to be done in the opposite order to opens
**
**  See also:
**	The BIG suite, and the TIME suite, whose servers are used.
*/

#include <stdio.h>
#include <rpcrts.h>

/*	Types for BIG package:
**	---------------------
*/

#define	byte_type   rpc_byte
#define	char_type   rpc_char
#define	short_type  rpc_short
#define	long_type   rpc_long
#define	real_type   rpc_real32
typedef rpc_char    str_type[81];
typedef rpc_char    substr_type[80];
typedef rpc_char    array_type[11][8];
typedef	rpc_integer seq_type[80];

byte_type  my_byte,  his_byte;
char_type  my_char,  his_char;
short_type my_short, his_short;
long_type  my_long,  his_long;
real_type  my_real,  his_real;
str_type   my_str,   his_str;
array_type my_array, his_array;

substr_type a_my_substr, a_his_substr;
rpc_integer s_my_substr, s_his_substr,
	    l_my_substr, l_his_substr;

seq_type    a_my_seq, a_his_seq;
rpc_integer l_my_seq, l_his_seq;

int i, j;		/* loop counters */
int errors = 0;		/* global error count */

#include "big.ext"

/*	Types for "TIME" package:
**	------------------------
*/
#include <time.h>
#ifdef vms
#include <types.h>
#include <timeb.h>
#else
#include <sys/types.h>
#include <sys/timeb.h>
#endif
#include <math.h>      

#include "time.ext"

char		name[100],host_name[100];

typedef rpc_byte time_array[10000];

/*			Routines for BIG test
**			---------------------
*/


/*	String compare
**	--------------
*/
static strncmp(a, b, n)	/* compares a and b for up to n characters */

char *a, *b;
int n;
{	int i;
	for (i = 0; i < n && a[i] == b[i]; i++);
	return(a[i] - b[i]);
}

/*	Compare data
**	------------
*/

check()		/* check the two sets are the same */

{	if (his_byte != my_byte)
            printf("Error %d: bad byte %d -> %d\n", ++errors, (int)my_byte, (int)his_byte);
		
	if (his_char != my_char)
            printf("Error %d: bad char %c -> %c\n", ++errors, my_char, his_char);

	if (his_short != my_short)
            printf("Error %d: bad short %d -> %d\n", ++errors, my_short, his_short);

	if (his_long != my_long)
            printf("Error %d: bad long %lx -> %lx\n", ++errors, my_long, his_long);

	if (his_real != my_real)
            printf("Error %d: bad real %f (%lx) -> %f (%lx)\n",
		     ++errors, my_real, *(long *)&my_real, his_real,
						 *(long *)&his_real);

	if (strncmp(his_str, my_str, 80))
            printf("Error %d: bad string\n%s\n  ->\n%s\n",
		     ++errors, my_str, his_str);

	if (s_his_substr != s_my_substr)
            printf("Error %d: bad substring start %d -> %d\n",
		     ++errors, s_my_substr, s_his_substr);

	if (l_his_substr != l_my_substr)
            printf("Error %d: bad substring length %d -> %d\n",
		     ++errors, l_my_substr, l_his_substr);

	for (i=s_his_substr; i < s_his_substr+l_his_substr; i++)
	    if (a_my_substr[i-1] != a_his_substr[i-1])
		printf(
		"Error %d: Substring character `%c' (%x) should be `%c' (%x)\n",
			++errors, a_his_substr[i-1], a_his_substr[i-1],
			a_my_substr[i-1], a_my_substr[i-1]);

	for (i = 0; i < 11; i++) 
	    for (j = 0; j < 8; j++)
		if (his_array[i][j] != my_array[i][j])
                    printf("Error %d: bad array element [%d][%d] %c -> %c\n", ++errors, i, j, my_array[i][j], his_array[i][j]);

	if (l_his_seq != l_my_seq)
            printf("Error %d: bad sequence length %d -> %d\n", ++errors, l_my_seq, l_his_seq);

	for (i = 0; i < l_my_seq; i++) 
	    if (a_his_seq[i] != a_my_seq[i])
                printf("Error %d: bad sequence element [%d] %lx -> %lx\n", ++errors, i, a_my_seq[i], a_his_seq[i]);
        }


/*	Initialise Data
**	---------------
*/

set_my_data()	/* set up a test data set */

{	my_byte = 77;
	my_char = '#';
	my_short = 12345;
	my_long = -1001;
	my_real = 3.1415926;

	for (i = 0; i < 80; i++)
	{   my_str[i] = (char)(i+49);
	    a_my_substr[i] = (char)(i+33);
	    a_my_seq[i] = (i+1)*(i+1)*(i+1);
	    }
	my_str[80] = '\0';
	s_my_substr = 11;	/* substring start PLUS ONE */
	l_my_substr = 25;	/* substring length   */
	l_my_seq = 80;

	for (i = 0; i < 11; i++)
	    for (j = 0; j < 8; j++)
		my_array[i][j] = (char)( ((j-i) < 0 ? i-j : j-i) % 128);
	}


	/* modify the parameters in a standard way */

#include "bigmod.h"

/*		    Routines for PERFORANCE TEST
**		    ----------------------------
*/


/*  Performance Test
**  ----------------
*/

int performance_test(passes,data,steps)
int passes,data,steps;
{


/*  Time & statistic variables    */

  int            time_pass[10000];
  int            count_pass,count_rate;
  struct timeb   *time_pointer_init, *time_pointer_end;

  FILE           *fd;
  time_array     ary;
  int		 rate;
  char           *name_file="PERFORMANCE.LOG";
  char           *time_now;
  rate = data/steps;

  time_now = (char *) malloc(100);
  time_pointer_init = (struct timeb *) malloc(sizeof(struct timeb));
  time_pointer_end  = (struct timeb *) malloc(sizeof(struct timeb));

  if ((fd=fopen(name_file,"a"))==NULL) {
    fprintf(stderr,"Can't open file %s\n", name_file);
    exit(1);
  }  

/* Read the current time  */            
  ftime (time_pointer_init);                 
  time_now = ctime(&time_pointer_init->time);

  fprintf(fd,"\n\n\nPERFORMANCE TEST (OC-RPC) FROM %s TO %s AT %s\n",host_name,name,time_now);
  fprintf(fd,"Passes: %4d   Data: %4d   Rate: %d   Steps: %d\n\n",
		passes,data,rate,steps);
  printf("\n\n\nPERFORMANCE TEST (OC-RPC) FROM %s TO %s AT %s\n",host_name,name,time_now);
  printf("Passes: %4d  -  Data: %4d  -  Rate: %d  -  Steps: %d\n\n",
		passes,data,rate,steps);
 

  for (count_pass=0; count_pass<data; count_pass++) ary[count_pass] = ' ';

  for (count_rate=0; count_rate<=data; count_rate+=rate)  {

    for (count_pass=0; count_pass<passes; count_pass+=1 )  {

      ftime (time_pointer_init);

      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
      test (ary,count_rate);  
 
      ftime (time_pointer_end);

      time_pass[count_pass] = (time_pointer_end->time*1000
        	              + time_pointer_end->millitm 
			      - time_pointer_init->time*1000 
			      - time_pointer_init->millitm) / 10;
  
      }

    statistic_pass (fd,time_pass,passes,count_rate);

  }

  fclose(fd);

}


/*	Statistics Pass
**	---------------
*/

statistic_pass(fd,time_pass,passes,rate)
FILE *fd;
int time_pass[];
int passes,rate;
{
  int     count_pass,min=0,max=0;
  float   means = 0,meansqr=0;

  for (count_pass=0; count_pass<passes; count_pass+=1) {
     if (min > time_pass[count_pass] || min==0) min = time_pass[count_pass];   
     if (max < time_pass[count_pass]) max = time_pass[count_pass];
     means = means + time_pass[count_pass];   
     meansqr = meansqr + time_pass[count_pass]*time_pass[count_pass];
  }

  means = means/passes;
  meansqr = meansqr/passes;
  meansqr = sqrt(meansqr-means*means);

  fprintf(fd,"Performance at %dbytes\n",rate);
  fprintf(fd,"Min       :%6dms    \nMax       :%6dms\n",min,max);
  fprintf(fd,"Mean      :%6.0fms    \nDeviation :%6.0fms\n",means,meansqr);
  fprintf(fd,"\n\n");

  printf("Performance at %dbytes\n",rate);
  printf("Min       :%6dms    \nMax       :%6dms\n",min,max);
  printf("Mean      :%6.0fms    \nDeviation :%6.0fms\n",means,meansqr);
  printf("\n\n");

}



/*	MAIN PROGRAM
**	------------
*/
int main (argc,argv)
int argc;
char *argv[];
{
    int passes,data,steps;

    passes = 10;    /* Number of calls in loop */
    data =  1000;   /* Size of largest call */
    steps = 1;	    /* Number of steps */
 
   {    extern char rpc_trace;   /* Trace flag */
/*
	rpc_init();
	printf("rpc init has been done\n");
*/
	open_timesub();
	printf("open_timesub has been done\n");	    /* TIME open */

	open_bigsub();				    /* Both open */
	printf("open_bigsub has been done\n");

	close_timesub();			    /* BIG open */
	printf("close_timesub has been done\n");

	close_bigsub();				    /* Both closed */
	printf("close_bigsub has been done\n");

	open_bigsub();				    /* Big open */
	printf("open_bigsub has been done\n");

	open_timesub();				    /* Both open again */
	printf("open_timesub has been done\n");

/*  Quick test that BIG is working:
*/
	{   int	x = 7;
	    int	y = 11;
	    int z = 13;

	    int	r = bigsub1(&x, &y, &z);
	    if (y !=18 || z != x*3 || r != x*x) {
	        printf("bigsub1 failed: bigsub1(%d, %d, %d) == %d\n",
						 x,  y,  z,     r);
		sys$exit(2);
	    } else
		 printf("passed bigsub1() call...\n");
	}

/*  Test that TIME is working:
*/
	performance_test(passes,data,steps);

    } /* scope */

    close_timesub();			    /* BIG open */
    printf("close_timesub has been done\n");

    close_bigsub();				    /* Both closed */
    printf("close_bigsub has been done\n");

} /*main*/