//  Manager.cpp:
//     Implementation of the class manager
//

#include "stdio.h"
#include "Manager.h"

extern unsigned server_num;
extern unsigned client_num;

Manager::Manager()
{
  int i;

  maplist = NULL;

  for (i = 0 ; i < MAXSERVERNUM ; i ++)
    {
      reference[i] = 0;  // it means this device is empty or no access yet
      amount[i] = 0.0;
    } // end of for

  for (i = 0 ; i < MAXCLIENTNUM ; i ++)
    clientact[i] = 0;
}

Manager::~Manager()
{
  struct Devicemap * dm;

  dm = maplist;
  while (dm)
    {
      maplist = dm->next;
      delete dm;
      dm = maplist;
    }
}

int Manager::GetCap(unsigned cid, unsigned idev, unsigned inode, unsigned b_begin, unsigned b_count)
{
  /*  the trace guarantee device 0 ~ 7
  struct Devicemap * dm;
  unsigned idisk;
  unsigned lowest;
  
  dm = maplist;
  while (dm)
    {
      if (dm->i_dev == idev)
	{
	  idisk = dm->i_disk;
	  break;
	}

      dm = dm->next;
    } // end of while

  if (dm) // found
    {
      reference[idisk] += 1;
      amount[idisk] += b_count;
      return idisk;
    }

  // find the lowest referenced device
  lowest = reference[0];
  idisk = 0;
  for (int i = 1 ; i < NASDSERVERNUM ; i ++)
    {
      if (lowest > reference[i])
	{
	  lowest = reference[i];
	  idisk = i;
	}
    }

  dm = new Devicemap;
  dm->i_dev = idev;
  dm->i_disk = idisk;

  // insert to the maplist
  dm->next = maplist;
  maplist = dm;

  reference[idisk] += 1;
  return idisk;
  */
  
  reference[idev] += 1;
  clientact[cid] += 1;
  amount[idev] += b_count;
  return idev;
}

int Manager::WhoIsIdle(unsigned sid)
{
  unsigned lowest;
  unsigned idisk;

  // find the lowest referenced device
  lowest = reference[0];
  idisk = 0;

  for (int i = 1 ; i < server_num ; i ++)
    {
      if (lowest > reference[i])
	{
	  lowest = reference[i];
	  idisk = i;
	}
    }

  if (reference[sid] - lowest > WORKLOADTHREHOLD) // somehow idle
    //  if (amount[sid] - lowest > WORKLOADTHREHOLD) // somehow idle
    {
      reference[idisk] += 1;
      return idisk;
    }
  else  // actually no difference
    return -1; 
}

int Manager::IdleClient(unsigned cid)
{
  unsigned lowest;
  unsigned iclient;

  // find the lowest referenced device
  lowest = clientact[0];
  iclient = 0;

  for (int i = 1 ; i < client_num ; i ++)
    {
      if (lowest > clientact[i])
	{
	  lowest = clientact[i];
	  iclient = i;
	}
    }

  if (clientact[cid] - lowest > WORKLOADTHREHOLD) // somehow idle
    //  if (amount[sid] - lowest > WORKLOADTHREHOLD) // somehow idle
    {
      clientact[iclient] += 1;
      return iclient;
    }
  else  // actually no difference
    return -1; 
}
