// $Id: pdinrs_watch.c,v 1.1.1.1 2005/01/10 18:47:02 pdi Exp $
//*****************************************************************************/
// Copyright 1998-2022 Stonie R. Cooper, Licensed under the auspices of GPLv3,
// See top-level copyright disclaimer (COPYRIGHT) and license (LICENSE)
//                    Marietta, Georgia.
// File:            <this file name>
// Author:          <your full name>, <your full title>, PDI
// Documentation:   NA
// Revision Record: (as follows)
//         Rewritten: 20050114 by Stonie R. Cooper
//                  Established initial file for <this file name>.
// Dependencies: 
//*****************************************************************************/

#include <pdinrs_watch.h>

char *cutSeg(char *, char *, int);

void pdinrs_watch(void)
{
  char                    main_path[] = { "/dev/shm/pdinrs/.proc/pdinrs.stats" };
  char                    channel_path[128];

  int                     main_open_handle = -1;

  char                    channel_array[MAX_CHANNELS][80];
  channel_stats_type      channel_stats[MAX_CHANNELS];
  char                    incoming_bucket[256];
  char                    temp_bucket[256];
  char                    channel_line[256];
  char                    *temp_ptr;
  time_t                  seconds_up = 1;
  time_t                  current_time = 0;
  unsigned char           number_of_channels;
  int                     count = 0;
  
  unsigned int       frames = 0;
  
  double                  float_frames = 0.0;
  double                  float_missing = 0.0;
  double                  float_bytes = 0.0;
  double                  float_percent = 0.0;
  struct tm timeSegment;

  memset((void *)channel_array, 0, sizeof(channel_array));
  memset((void *)channel_stats, 0, sizeof(channel_stats));
// open up the main fifo - the big daddy for the program (not the channels) 
  if ((main_open_handle = open(main_path, O_RDONLY)) < 3)
  {
    printf("Couldn't open main stats pipe.\n");	  
    exit(0);
  }

  memset((void *)incoming_bucket, 0, sizeof(incoming_bucket));

// Now, read from our main fifo.
  if ((read(main_open_handle, (void *)incoming_bucket, sizeof(incoming_bucket))) == -1)
  {
    printf("Couldn't read from main stats pipe.\n");	  
    exit(0);
  }
  
  close(main_open_handle);
  main_open_handle = -1;

// Gotta a little parsing to do - number of channels and such.
  temp_ptr = incoming_bucket;
  memset((void *)temp_bucket, 0, sizeof(temp_bucket));
  number_of_channels = atoi(cutSeg(temp_bucket, temp_ptr, 5));
  temp_ptr = &temp_ptr[5];
  memset((void *)temp_bucket, 0, sizeof(temp_bucket));
  seconds_up = atol(cutSeg(temp_bucket, temp_ptr, 14));
  temp_ptr = &temp_ptr[14];
  for (count = 0; count < number_of_channels; count++)
  {
    memset((void *)temp_bucket, 0, sizeof(temp_bucket));
    strcpy(channel_array[count], cutSeg(temp_bucket, temp_ptr, 13));
    temp_ptr = &temp_ptr[13];
    sprintf(channel_path, "/dev/shm/pdinrs/.proc/%s.stats", channel_array[count]);
    if ((main_open_handle = open(channel_path, O_RDONLY)) < 3)
    {
      printf("Couldn't open %s stats pipe.\n", channel_array[count]);	  
      exit(0);
    }
    memset((void *)channel_line, 0, sizeof(channel_line));
    if ((read(main_open_handle, (void *)channel_line, sizeof(channel_line))) < 0)
    {
      printf("Couldn't read from %s stats pipe.\n", channel_array[count]);	  
      exit(0);
    }
  
    close(main_open_handle);
    main_open_handle = -1;

    sscanf(channel_line, "%13u %13u %13u %13u %13u %13u %13u %13u %13u %13d %13u %13u %13d %13u %8s %8s %8s",
           (unsigned int *)&channel_stats[count].resetTime, &channel_stats[count].firstFrame,
	   &channel_stats[count].currentFrame, &channel_stats[count].frameRollOver,
	   &channel_stats[count].missingFrames, &channel_stats[count].missingRollOver,
	   &channel_stats[count].totalBytes, &channel_stats[count].totalGigaBytes,
		 &channel_stats[count].LongTransit, &channel_stats[count].CurTransit,
		 &channel_stats[count].AveTransit, &channel_stats[count].LongNCFWait,
		 &channel_stats[count].CurNCFWait, &channel_stats[count].AveNCFWait, channel_stats[count].LongNCFWaitWmoTTAAii,
		 channel_stats[count].LongNCFWaitWmoCCCC, channel_stats[count].LongNCFWaitWmoDDGGgg);
  }
  
  printf("-------------------------------------------------------------------------------\n");
  memset((void *)channel_line, 0, sizeof(channel_line));
  memset((void *)&timeSegment, 0, sizeof(timeSegment));
  strftime(channel_line, (sizeof(channel_line)-1), "%a, %d %b %Y, %H:%M GMT", gmtime_r(&seconds_up, &timeSegment));
  time(&current_time);
  printf("PDINRS: Running since %s, Up for %.3f days -\n",
    channel_line, (((double)(current_time - seconds_up)) / 86400.0));
  memset((void *)channel_line, 0, sizeof(channel_line));
  memset((void *)&timeSegment, 0, sizeof(timeSegment));
  strftime(channel_line, (sizeof(channel_line)-1), "%a, %d %b %Y, %H:%M GMT", gmtime_r(&channel_stats[0].resetTime, &timeSegment));
  printf("   channel stats reset on %s\n", channel_line);
  printf("-------------------------------------------------------------------------------\n");
  printf("   Channel | Frames Processed | Frames Dropped | Percent Loss | Total MB Frames \n");
  printf("-------------------------------------------------------------------------------\n");
  for (count = 0; count < number_of_channels; count++)
  {
    frames = channel_stats[count].currentFrame - channel_stats[count].firstFrame;
    if (frames < 0)
    {
      frames = 999999999 + frames;
      if (frames < 0)
	      frames = 0 - frames;
      else if (channel_stats[count].frameRollOver > 0)
	      channel_stats[count].frameRollOver--;
    }
    frames += channel_stats[count].missingFrames;
    if (frames > 999999999)
    {
      frames = frames - 999999999;
      channel_stats[count].frameRollOver++;
    }
    channel_stats[count].frameRollOver += channel_stats[count].missingRollOver;
    float_frames = (double)channel_stats[count].frameRollOver * 1000000000.0;
    float_frames = float_frames + (double)frames;
    float_missing = (double)channel_stats[count].missingRollOver * 1000000000.0;
    float_missing = float_missing + (double)channel_stats[count].missingFrames;
    float_percent = float_missing / float_frames * 100.0;
    float_bytes = (double)channel_stats[count].totalGigaBytes * 1000000000.0;
    float_bytes = float_bytes + (double)channel_stats[count].totalBytes;
    float_bytes = float_bytes / 1000000.0;
    printf("%10s", channel_array[count]);
    if (channel_stats[count].frameRollOver > 0)
    {
      printf("%10u", channel_stats[count].frameRollOver);
      printf("%09u", frames);
    }
    else
      printf("%19u", frames);
    if (channel_stats[count].missingRollOver > 0)
    {
      printf("%8u", channel_stats[count].missingRollOver);
      printf("%09u", channel_stats[count].missingFrames);
    }
    else
      printf("%17u", channel_stats[count].missingFrames);
    printf("%15.6f", float_percent);
    printf("%18.3f\n", float_bytes);
  }  
  printf("-------------------------------------------------------------------------------\n");
  printf("  Time on Queue Statistics - Units are in seconds, for both NCF and local.     \n");
  printf("-------------------------------------------------------------------------------\n");
  printf("   Channel      | NCF Max | NCF Ave | NCF Max WMO       | local Max | local Ave\n");
  printf("-------------------------------------------------------------------------------\n");
  for (count = 0; count < number_of_channels; count++)
  {
    printf("%10s Queue", channel_array[count]);
		printf("%10u", channel_stats[count].LongNCFWait);
		printf("%10u", channel_stats[count].AveNCFWait);
		printf("%8s", channel_stats[count].LongNCFWaitWmoTTAAii);
		printf("%5s", channel_stats[count].LongNCFWaitWmoCCCC);
		printf("%7s", channel_stats[count].LongNCFWaitWmoDDGGgg);
		printf("%12u", channel_stats[count].LongTransit);
		printf("%11u\n", channel_stats[count].AveTransit);
	}
  printf("-------------------------------------------------------------------------------\n");
  return;
}

char *cutSeg(char *stay, char *flex, int number)
{
  char *func_ptr;
  int loop = 0;
  memcpy((void *)stay, flex, number);
  func_ptr = stay;
  while (func_ptr[0] == ' ') func_ptr++;
  while (func_ptr[0] != ' ' && func_ptr[0] != '\n' && func_ptr[0] != '\r' && func_ptr[0] != '\0')
  {
    stay[loop++] = func_ptr[0];
    func_ptr++;
  }
  stay[loop] = '\0';
  return stay;
}
