
#include "cpumonfetcher.h"

cCpuMonFetcher::cCpuMonFetcher(cParameters *pparms): cThread("CPU Monitor Values Fetcher")
{
  // reset the index
  parms = pparms;
  // reset all values
  
  tMeasured *h = NULL;
  measurements[0].val[USER]   = 0;
  measurements[0].val[NICE]   = 0;
  measurements[0].val[SYSTEM] = 0;
  measurements[0].val[IDLE]   = 0;

  measurements[1].val[USER]   = 0;
  measurements[1].val[NICE]   = 0;
  measurements[1].val[SYSTEM] = 0;
  measurements[1].val[IDLE]   = 0;
    
  for(unsigned int a = 0; a < VAL_COUNT; a++)
  {

    if(a == 0)
    {
      values_head = new tMeasured();
      h = values_head;
      h->next = new tMeasured();
    }
    else
    {
      if(a == VAL_COUNT - 1)
        h->next = values_head;
      else
        h->next = new tMeasured();
    }
    
    h->index = a;
    h->val[USER]   = 0;
    h->val[NICE]   = 0;
    h->val[SYSTEM] = 0;
    h->val[IDLE]   = 0;
    
    h->order[0].val    = 0;
    h->order[1].val    = 0;
    h->order[2].val    = 0;
    h->order[3].val    = 0;
    
    h->order[0].func   = 0;
    h->order[1].func   = 0;
    h->order[2].func   = 0;
    h->order[3].func   = 0;
    h = h->next;
  }
  act_values = values_head;
  int_act_values = values_head;
};

cCpuMonFetcher::~cCpuMonFetcher()
{
  if( Running() )
    Cancel(3);
    
  delete measurements;
};

void cCpuMonFetcher::reset_values()
{  
  measurements[0].val[USER]   = 0;
  measurements[0].val[NICE]   = 0;
  measurements[0].val[SYSTEM] = 0;
  measurements[0].val[IDLE]   = 0;

  measurements[1].val[USER]   = 0;
  measurements[1].val[NICE]   = 0;
  measurements[1].val[SYSTEM] = 0;
  measurements[1].val[IDLE]   = 0;
    
  tMeasured *h = get_head();
  
  for(unsigned int a = 0; a < VAL_COUNT; a++)
  {

    h->val[USER]   = 0;
    h->val[NICE]   = 0;
    h->val[SYSTEM] = 0;
    h->val[IDLE]   = 0;
    
    h->order[0].val    = 0;
    h->order[1].val    = 0;
    h->order[2].val    = 0;
    h->order[3].val    = 0;
    
    h->order[0].func   = 0;
    h->order[1].func   = 0;
    h->order[2].func   = 0;
    h->order[3].func   = 0;
    h = h->next;
  }
};


tMeasured* cCpuMonFetcher::get_head()
{
  return values_head;
}

unsigned int cCpuMonFetcher::round(float x)
{
  unsigned int ax = (unsigned int) x;
  if ((ax - x) < 0.5)
    return x;
  else
    return x + 1;
};

int cCpuMonFetcher::fetch_values()
{
  Datei = fopen(DName, "r");  
  
  if(Datei)
  {
          
    // read the jiffies from the system file
    fscanf(Datei,
           "%s %u %u %u %u",
	   name,
	   &(measurements[1].val[USER]),
	   &(measurements[1].val[NICE]),
	   &(measurements[1].val[SYSTEM]),
	   &(measurements[1].val[IDLE])
	  );
			      
    fclose(Datei);
    
    int_act_values->val[USER]   = measurements[1].val[USER]   - measurements[0].val[USER];
    int_act_values->val[NICE]   = measurements[1].val[NICE]   - measurements[0].val[NICE];
    int_act_values->val[SYSTEM] = measurements[1].val[SYSTEM] - measurements[0].val[SYSTEM];
    int_act_values->val[IDLE]   = measurements[1].val[IDLE]   - measurements[0].val[IDLE];
    
    measurements[0].val[USER]   = measurements[1].val[USER];
    measurements[0].val[NICE]   = measurements[1].val[NICE];
    measurements[0].val[SYSTEM] = measurements[1].val[SYSTEM];
    measurements[0].val[IDLE]   = measurements[1].val[IDLE];

    int_act_values->sum    = int_act_values->val[USER]   + 
                             int_act_values->val[NICE]   +
		             int_act_values->val[SYSTEM] +
		             int_act_values->val[IDLE];

    float helper = 0;

    helper = 100 * (float) (int_act_values->val[USER]);
    helper /= (float) (int_act_values->sum);
    int_act_values->val[USER] = round(helper);
  
    helper = 100 * (float) (int_act_values->val[NICE]);
    helper /= (float) (int_act_values->sum);
    int_act_values->val[NICE] = round(helper);

    helper = 100 * (float)(int_act_values->val[SYSTEM]);
    helper /= (float) (int_act_values->sum);
    int_act_values->val[SYSTEM] = round(helper);
  
    helper = 100 * (float)(int_act_values->val[IDLE]);
    helper /= (float) (int_act_values->sum);
    int_act_values->val[IDLE] = round(helper);
			       
    int_act_values->sum       = int_act_values->val[USER]   + 
                                int_act_values->val[NICE]   +
 		                int_act_values->val[SYSTEM] +
		                int_act_values->val[IDLE];
				
    // determine the function ordering to display the highest values first,
    // then lower values
    for(unsigned int b = 0; b < 4; b++)
    {
      int_act_values->order[b].val  = int_act_values->val[b];
      int_act_values->order[b].func = b;
    }
    
    bool change = false;
    s_order ord_hlp;
    int a = 0;
    while(true)
    {
      change = false;
      for(a = 0;a < 3; a++)
      {
        if(int_act_values->order[a+1].val > int_act_values->order[a].val)
	{
	  ord_hlp  = int_act_values->order[a];	  
	  int_act_values->order[a]   = int_act_values->order[a+1];
	  int_act_values->order[a+1] = ord_hlp;
	  change = true;
	}
      }
      if(change == false)
        break;
    }
    
    /*
    dsyslog("values: (%i/%i), (%i/%i), (%i/%i), (%i/%i)\n", int_act_values->order[0].val, int_act_values->order[0].func,
                                                            int_act_values->order[1].val, int_act_values->order[1].func,
							    int_act_values->order[2].val, int_act_values->order[2].func,
							    int_act_values->order[3].val, int_act_values->order[3].func);
    */
    // -------------------------------------------    
    
    act_values = int_act_values;
    int_act_values = int_act_values->next;
    return 0;
  }
  else
  {
    esyslog("ERROR: cCpuMonFetcher::fetch_values(): Opening of %s FAILED!\n", DName);
    return -1;
  }    
};

tMeasured* cCpuMonFetcher::get_act_val()
{
  return act_values;
}

void cCpuMonFetcher::Action(void)
{  
  while( Running() )
  {
    fetch_values();    

    switch(parms->pi_unit())
    {
      case 0: // millsecs
        timer.Wait(parms->polling());
        break;
      case 1: // secs
        timer.Wait(parms->polling() * 1000);
        break;
      case 2: // minutes
        timer.Wait(parms->polling() * 60000);
        break;
      default:
        break;
    };
  };
  dsyslog("cCpuMonFetcher()::Action(): check parms->pi_unit\n");
};

void cCpuMonFetcher::Stop(void)
{
  Cancel(3);
};
