/***************************************************************************/
/* Circwrite.c, circular buffer example and test program between processes. 
 *
 * Usage: Circwrite <key-name> <event-lenght> <repeat-count>
 */
/***************************************************************************/
static char Usage[] = "\
Usage: Circwrite <key-name> <event-lenght> <repeat-count>\
";
#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 GO_ON   0
#define STOP_IT 1
#define MAGIC 0x31071965

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

  double real_time, cpu_time, cpu_usage;

#ifndef DO_YIELD
  struct timeval delay = {0, 1}; /* Note: the lowest value is one tick */
#endif
/*......................................................................... */

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

  /*  evtsize &= ~(0x3); */
  data = (int *) malloc (evtsize);

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

  printf ("%s> Circular buffer opened for write: key=%s, id=%d\n",
	  argv[0], key, cid);
  printf ("%s> write %d events of size %d\n", argv[0], repeat, evtsize);
  printf ("%s> Circular buffers base address: 0x%x and size: %d\n",
	  argv[0], CircGetAddress (cid), CircGetSize (cid));

  last       = evtsize / sizeof (int) - 1;
  data[0]    = GO_ON;
  data[last] = MAGIC;

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

  timing_start ();
  for (i = 1; i <= repeat; i++)
    {
      while ( (ptr = (int*)CircReserve (cid, i, evtsize)) 
	      == (int*)-1)
	{
	  full++;
#ifdef DO_YIELD
	  sched_yield ();
#else
	  select (1, (int *) 0, (int *) 0, (int *) 0, &delay);
#endif
	}
      if (i < repeat)
	ptr[0] = GO_ON;
      else
	ptr[0] = STOP_IT; /* mark end of test */
#ifdef DO_CHECKS
      ptr[last] = MAGIC;
#endif
      (void) CircValidate (cid, i, (char *) ptr, evtsize);
    }
  timing_stop (&real_time, &cpu_time, &cpu_usage);

  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 full: %d\n", argv[0], full);

  sleep (5);

  /* Test 2: CircPut with moving data (memcpy)
  ********************************************/
  printf ("%s> Test #2: CircPut with moving data (memcpy)\n", argv[0]);
  timing_start ();
  for (i = 1; i <= repeat; i++)
    {
      if (i == repeat)
	data[0] = STOP_IT; /* mark end of test */

      while (CircPut (cid, i, (char *) data, evtsize) < 0)
	{
	  full++;
#ifdef DO_YIELD
	  sched_yield ();
#else
	  select (1, (int *) 0, (int *) 0, (int *) 0, &delay);
#endif
	}
    }
  timing_stop (&real_time, &cpu_time, &cpu_usage);

  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 full: %d\n", argv[0], full);

  /* Close circular buffer */
  (void) CircClose (cid);
}