/***************************************************************************/
/* Circread.c, circular buffer example and test program between processes. 
 *
 * Usage: Circread <key-name> <buffer-size>
 */
/***************************************************************************/
static char Usage[] = "\
Usage: Circread <key-name> <buffer-size>\
";
#define USAGE printf("%s\n",Usage), exit(1)

#include <stdio.h>
#include<sys/types.h>
#include<sys/time.h>

/*#define DO_YIELD*/    /* fast switch to next process */
#define DO_CHECK    /* do data consistency checks  */

#ifdef DO_YIELD
#include <sched.h>
#endif

/* Circ */
#include "Circ.h"

/* timing */
void  timing_start(void);
void  timing_stop(double*, double*, double*);

#define MAX_EVTSIZE 65536*2
#define MAGIC 0x31071965
#define GO_ON   0
#define STOP_IT 1

/***************************************************************************/
main (int argc, char *argv[])
/*---------------------------
*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
{
  char *key;
  int *data, *ptr;
  int cid, bufsize, evtsize, repeat = 0, empty = 0;
  int number;

  double real_time, cpu_time, cpu_usage;

#ifndef DO_YIELD
  struct timeval delay = {0, 1}; /* Note: the lowest value is one tick */
  struct timeval delayt= {0, 100};
  fd_set fdset;
  bzero((char *)(&fdset), sizeof(*(&fdset)));
#endif

/*......................................................................... */

  /* Get parameters form the command line */
  if (argc != 3)
    USAGE;
  key     = argv[1];
  bufsize = atoi (argv[2]);

  data = (int *) malloc (MAX_EVTSIZE);

  /* Open the circular buffer */
  if ((cid = CircOpen (NULL, key, bufsize)) < 0)
    {
      fprintf (stderr, "%s> Circular buffer open failed !\n", argv[0]);
      exit (1);
    }
  printf ("%s> Circular buffer opened for read: key=%s, id=%d\n",
	  argv[0], key, cid);


  /* Test 1: CircLocate/CircRelease without memcpy
  ************************************************/
  printf ("%s> Test #1: CircLocate/CircRelease without moving data\n",
	  argv[0]);

  repeat  = 0;
  data[0] = GO_ON;
  while (data[0] == GO_ON)
    {
      while ( (ptr = (int*)CircLocate (cid, &number, &evtsize))
	      == (int*)-1 )
	{
	  empty++;
#ifdef DO_YIELD
	  sched_yield ();
#else
	  /*	  select (1, (int *) 0, (int *) 0, (int *) 0, &delay); */
#if defined (_HPUX_SOURCE) && defined (V9)
	select (1, (int *) &fdset, (int *) 0, (int *) 0, &delay);
#else
	select (1, &fdset, 0, 0, &delay);
#endif

#endif
	}
      if (repeat++ == 0)
	timing_start ();
#ifdef DO_CHECKS
      if (ptr[evtsize / sizeof (int) - 1] != MAGIC)
	{
	  printf("%s> Invalid MAGIC number %x found for event #%d !\n",argv[0],
		  ptr[evtsize / sizeof (int) - 1], repeat);
	  exit (1);
	}
      if (repeat != number)
	{
	  printf("%s> Invalid event number %d found instead of %d !\n",argv[0],
		  number, repeat);
	  exit (1);
	}
#endif
      /*      printf (" Circread> Per debug number= %d \n",number);*/
      data[0] = ptr[0];
      (void) CircRelease (cid);


     /* per test di monitor */
#if defined (_HPUX_SOURCE) && defined (V9)
	select (1, (int *) &fdset, (int *) 0, (int *) 0, &delayt);
#else
	select (1, &fdset, 0, 0, &delayt);
#endif

    }
  timing_stop (&real_time, &cpu_time, &cpu_usage);

  sleep (1);
  printf ("%s> Real-time: %.2fs, CPU-time: %.2fs, CPU-usage: %.1f%%\n",
	  argv[0], real_time, cpu_time, cpu_usage);
  printf ("%s> Events: %d, %.0f per sec\n", argv[0],
	  repeat, (double) repeat / real_time);
  printf ("%s> Bytes : %.0f, %.1f MB /sec\n", argv[0],
	  (double) repeat * evtsize,
	  (double) repeat * evtsize / 1024. / 1024. / real_time);
  printf ("%s> Buffer empty: %d\n", argv[0], empty);

  /* Test 2: CircGet with moving data (memcpy)
  ********************************************/
  printf ("%s> Test #2: CircGet and moving data (memcpy)\n", argv[0]);

  repeat  = 0;
  data[0] = GO_ON;
  while (data[0] == GO_ON)
    {
      while ( (evtsize = CircGet (cid, &number, (char*)data, MAX_EVTSIZE)) 
	      < 0 )
	{
	  empty++;
#ifdef DO_YIELD
	  sched_yield ();
#else
	  /* 	  select (1, (int *) 0, (int *) 0, (int *) 0, &delay); */

#if defined (_HPUX_SOURCE) && defined (V9)
	select (1, (int *) &fdset, (int *) 0, (int *) 0, &delay);
#else
	select (1, &fdset, 0, 0, &delay);
#endif
#endif
	}
      if (repeat++ == 0)
	timing_start ();
#ifdef DO_CHECKS
      if (data[evtsize / sizeof (int) - 1] != MAGIC)
	{
	  printf ("%s> Invalid MAGIC number %x found for event number %d !\n",
		  argv[0], data[evtsize / sizeof (int) - 1], repeat);
	  exit (1);
	}
      if (repeat != number)
	{
	  printf ("%s> Invalid event number %d found instead of %d !\n",
		  argv[0], number, repeat);
	  exit (1);
	}
#endif
    }
  timing_stop (&real_time, &cpu_time, &cpu_usage);

  sleep (1);
  printf ("%s> Real-time: %.2fs, CPU-time: %.2fs, CPU-usage: %.1f%%\n",
	  argv[0], real_time, cpu_time, cpu_usage);
  printf ("%s> Events: %d, %.0f per sec\n", argv[0],
	  repeat, (double) repeat / real_time);
  printf ("%s> Bytes : %.0f, %.1f MB /sec\n", argv[0],
	  (double) repeat * evtsize,
	  (double) repeat * evtsize / 1024. / 1024. / real_time);
  printf ("%s> Buffer empty: %d\n", argv[0], empty);

  (void) CircClose (cid);

}