// This may look like C code, but it is really -*- C++ -*-
// permet d'obtenir des informations sur les ressources utilisees
//                                R. Ansari - Juillet 2002
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#ifndef RESUSAGE_H_SEEN
#define RESUSAGE_H_SEEN

#include "machdefs.h"
#include <iostream>

namespace SOPHYA {

//! Acces to information about resource usage (memory, CPU, ...)

class ResourceUsage
{
public:
/*!
  - RU_Self : Resource usage for the process itself
  - RU_Children : Resource usage for the child processes
  - RU_All : resource usage for the process itself and its child processes
*/
  enum RU_ProcGrp {RU_Self=0, RU_Children=1, RU_All=2};

  ResourceUsage(RU_ProcGrp pg=RU_Self);
  ~ResourceUsage();

  int Update();

  // Process Id
  //! Returns the process id.
  inline uint_8 getProcessId() { return cur_pid; }

  // Memory usage in kilo-bytes  
  // NOTE: getDataSize() getStackSize() retournent des valeurs bizarres
  //! Returns the current memory (Resident) size (in kilo-bytes) 
  inline uint_8 getMemorySize() { return cur_rss; }
  //! Returns the maximum allowed memory size: Min( \c MaxResidentSize , \c MaxDataSize ))
  inline uint_8 getMaxMemorySize() 
    { return((getMaxResidentSize()<getMaxDataSize()) ? 
	     getMaxResidentSize() :getMaxDataSize() ); }
  //! Returns the increase in memory usage since the previous call to \b Update()
  inline uint_8 getDeltaMemorySize() { return delta_rss; }

  //! Returns the maximum allowd data segment size (in kilo-bytes)
  inline uint_8 getMaxDataSize() { return((max_datasz>0)?max_datasz:1024); }
  //! Returns the current data segment size (in kilo-bytes)
  inline uint_8 getDataSize() { return cur_datasz; }  
  //! Returns the maximum allowed resident size (in kilo-bytes)
  inline uint_8 getMaxResidentSize() { return((max_rss>0)?max_rss:1024); }
  //! Returns the current resident memory size (in kilo-bytes)
  inline uint_8 getResidentSize() { return cur_rss; }
  //! Returns the maximum allowed stack size (in kilo-bytes)
  inline uint_8 getMaxStackSize() { return max_stack; }
  //! Returns the current stack size (in kilo-bytes)
  inline uint_8 getStackSize() { return cur_stack; }

  
  // Time in milli-second
  //! Returns the total CPU time used (in milli-second)
  inline uint_8 getCPUTime() { return cur_tottm; }
  //! Returns the total elapsed time (in milli-second)
  inline uint_8 getElapsedTime() { return elapsed_time; }
  //! Returns the average load ( CPU time / elapsed time)
  inline double  getAverageCPULoad() 
    { return ((elapsed_time>1) ? (double)cur_tottm/(double)elapsed_time: 1.);}

  //! Returns the CPU time used since the previous call to \b Update() (in milli-second)
  inline uint_8 getDeltaCPUTime() { return delta_tottm; }
  //! Returns the elapsed time since the previous call to \b Update() (in milli-second)
  inline uint_8 getDeltaElapsedTime() { return delta_elapsed_time; }
  //! Returns the CPU load since the previous call to \b Update()
  inline double  getCPULoad() 
    { return ((delta_elapsed_time>1) ? (double)delta_tottm/(double)delta_elapsed_time: 1.);}


  //! Returns the total CPU time (in milli-second)
  inline uint_8 getTotalCPUTime() { return cur_tottm; }
  //! Returns the CPU time in user mode (in milli-second)
  inline uint_8 getUserCPUTime() { return cur_usrtm; }
  //! Returns the CPU time in system mode (in milli-second)
  inline uint_8 getSysCPUTime() { return cur_systm; }


  void  Print(ostream& os, int lp=0, bool upd=true);
  //! Alias for the \b Print() method. 
  inline void print(ostream& os, int lp=0, bool upd=true){ Print(os,lp,upd); }

  void ReadLinuxMem();    // methode de lecture des infos memoire ss Linux - OPerdereau 
  void ReadLinuxTotMem(); // methode de lecture des infos memoire ss Linux - OPerdereau 

protected:
  RU_ProcGrp procgrp; // Process group: self, child, all
  uint_8 max_datasz;  // Max data segment size (KBytes)
  uint_8 max_rss;     // Max resident size
  uint_8 max_stack;   // Max stack size

  uint_8 cur_datasz;  // Current data segment size
  uint_8 cur_rss;     // Current resident size
  uint_8 cur_stack;   // Current stack size

  uint_8 cur_tottm;   // Current total CPU-Time - in milli-second
  uint_8 cur_usrtm;   // Current user CPU-Time - in milli-second 
  uint_8 cur_systm;   // Current system CPU-Time - in milli-second 
  uint_8 elapsed_time; // Elapsed time - in milli-second
  uint_8 t0_time;      // time T0 in seconds 

  // Delta_values : difference since last call to Update()
  uint_8 delta_rss;     // Max resident size
  uint_8 delta_tottm;   // Delta total CPU-Time - in milli-second
 
  uint_8 delta_elapsed_time; // Elapsed time - in milli-second
  uint_8 cur_pid ;          // process PID 
};

//! Prints the resource usage information on the output stream 
inline ostream& operator << (ostream& os, ResourceUsage& ru)
{ ru.Print(os,0,true); return(os); }

} // namespace SOPHYA

#endif

