/****************************************************************************/
/* Copyright (c) 2011 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  : Driver task that gathers data on system resource use          */
/* Filename : SysData.cc                                                    */
/* Author   : Rich Henthorn                                                 */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 01/18/2011                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/

#include "PeriodicTask.h"
#include "Syslog.h"
#include "TimeP.h"
#include "SysData.h"

// Standard constructor
//
SysData::SysData(unsigned int frequency)
  : PeriodicTask("sysdata"), _freq(frequency), _pass(0), _verbose(False), _cpuusage(False),
    _memusage(False)
{
   Boolean debug = True;

   // Prepare for cpu by priority data
   //
   _prioTotals = (PrioTotalsT *)malloc(PrioTotalsS);
   _cpulog = new SysDataCpuPrio(this, DataLog::BinaryFormat);
   _memlog = new SysDataMemPrio(this, DataLog::BinaryFormat);
   _processlog = new SysDataProcess(this, DataLog::BinaryFormat);

   // Set up callback and interval
   //
   //addPeriodicCallback((1./_freq)*1000, (CallbackMethod)SysData::readData);

   for (int i = 0; i < 50; i++) {
     _processNames[i] = NULL;
     _process_cpu[i] = 0;
     _process_mem[i] = 0;
   }
}

// Destructor
//
SysData::~SysData()
{
   Syslog::write(" SysData Destructor Executing.");
   delete _cpulog;
   delete _memlog;
   delete _processlog;
}

// Set verbosity on or off
// Used for testing
//
void SysData::verbose(Boolean flag)
{
  _verbose = flag;
}

void SysData::cpu_usage(Boolean flag)
{
  _cpuusage = flag;
}

void SysData::mem_usage(Boolean flag)
{
  _memusage = flag;
}

// This function is called by the framework once before running the task
//
void SysData::startSampling()
{
  for (int i = 0; i < _processlog->num_processes(); i++)
    Syslog::write("SysData watching %s", _processNames[i]);

  initialize();
}

// One-time setup of the sysmon structures
//
void SysData::initialize()
{

  // Legacy setup routine from sysmon
  //
  initializeCpuData();
  cpuBackbone (1);
  initializeMemData();
  memBackbone (1);
  _pass = 0;
}

// Callback function called at the specified frequency
//
void SysData::readData()
{
  // Toggle the pass variable and call the sysmon function that
  // calculates the cpu usage of each process in the system,
  // including usage sorted by priority.
  //

  _pass = 1 - _pass;
  doTOPCPU(_pass+1);
  doTOPMEM(_pass+1);

  // Retrieve the up to date usage by priority and log the data
  //
  if (_cpuusage) {
    cpuPrioTotals(_prioTotals);
    _cpulog->write();
  }

  if (_memusage) {
    memPrioTotals(_prioTotals);
    _memlog->write();
  }

  for (int i = 0; i < _processlog->num_processes(); i++) {
    _process_cpu[i] = getProcessCpu(_processNames[i]);
    _process_mem[i] = getProcessMem(_processNames[i]);
  }

  if (_processlog->num_processes() > 0)
    _processlog->write();

  if (_verbose) {
    Syslog::write("Cpu usage for priority 0: %d", _prioTotals->cpuprio_totals[0]);
    Syslog::write("Cpu usage for process %s: %d\n", "idle", getProcessCpu("idle"));
  }
}


void SysData::frequency(unsigned int f)
{
  _freq = f;
   // Set up callback and interval
   //
   addPeriodicCallback((1./_freq)*1000, (CallbackMethod)SysData::readData);

}

void SysData::monitorProcess(char *processName)
{
  _processNames[_processlog->num_processes()] = strdup(processName);
  _processlog->addProcess(processName);
}
