/* Copyright (C) 2021-2025 Free Software Foundation, Inc.
   Contributed by Oracle.

   This file is part of GNU Binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

#include "config.h"
//#include <search.h>     //  For the tsearch stuff
#include <assert.h>
//#include <stdlib.h>
#include "Table.h"
#include "Sample.h"
#include "Stats_data.h"
#include "util.h"
#include "i18n.h"

//XXX:	The fundamental problem with this package of routines is that
//XXX:	they should look a lot more like overview data. The result
//XXX:	is that it is not possible to share as much code as would
//XXX:	otherwise be possible.

int
Stats_data::size ()
{
  // Return the number of Stats_item values associated with "this".
  if (stats_items == NULL)
    return 0;
  return stats_items->size ();
}

Stats_data::Stats_item
Stats_data::fetch (int index)
{
  // Routine will return the "index"'th Stats_item associated with "this".
  assert (index >= 0 && index < stats_items->size ());
  return *(stats_items->fetch (index));
}

Stats_data::Stats_data ()
{
  // this constructor for use with sum()
  packets = NULL;
  stats_items = NULL;
}

Stats_data::Stats_data (DataView *_packets)
{
  packets = _packets;
  stats_items = NULL;
  compute_data ();  // reads all data
}

Stats_data::~Stats_data ()
{
  if (stats_items)
    {
      stats_items->destroy ();
      delete stats_items;
    }
}

void
Stats_data::sum (Stats_data *data)
{
  int index;
  Stats_item *stats_item, *data_item;
  if (stats_items == NULL)
    {
      stats_items = new Vector<Stats_item*>;
      Vec_loop (Stats_item*, data->stats_items, index, data_item)
      {
	stats_item = create_stats_item (data_item->value.ll, data_item->label);
	stats_items->append (stats_item);
      }
    }
  else
    {
      Vec_loop (Stats_item*, data->stats_items, index, data_item)
      {
	stats_items->fetch (index)->value.ll += data_item->value.ll;
      }
    }
}

Stats_data::Stats_item *
Stats_data::create_stats_item (long long v, char *l)
{
  Stats_data::Stats_item *st_it;
  st_it = new Stats_data::Stats_item;
  st_it->label = l;
  st_it->value.sign = false;
  st_it->value.ll = v;
  st_it->value.tag = VT_LLONG;
  return st_it;
}

PrUsage *
Stats_data::fetchPrUsage (long index)
{
  // Return the data values corresponding to the "index"'th sample.
  PrUsage *prusage;
  if (packets->getSize () > 0)
    {
      Sample* sample = (Sample*) packets->getObjValue (PROP_SMPLOBJ, index);
      prusage = sample->get_usage ();
      if (prusage != NULL)
	return prusage;
    }
  return new PrUsage;
}

void
Stats_data::compute_data ()
{
  Stats_data::Stats_item *stats_item;
  PrUsage *tots, *temp;
  stats_items = new Vector<Stats_data::Stats_item*>;

  // Precomputation is needed.
  long size = packets->getSize ();
  tots = new PrUsage ();
  for (long index = 0; index < size; index++)
    {
      temp = fetchPrUsage (index);
      tots->pr_tstamp += temp->pr_tstamp;
      tots->pr_create += temp->pr_create;
      tots->pr_term += temp->pr_term;
      tots->pr_rtime += temp->pr_rtime;
      tots->pr_utime += temp->pr_utime;
      tots->pr_stime += temp->pr_stime;
      tots->pr_ttime += temp->pr_ttime;
      tots->pr_tftime += temp->pr_tftime;
      tots->pr_dftime += temp->pr_dftime;
      tots->pr_kftime += temp->pr_kftime;
      tots->pr_slptime += temp->pr_slptime;
      tots->pr_ltime += temp->pr_ltime;
      tots->pr_wtime += temp->pr_wtime;
      tots->pr_stoptime += temp->pr_stoptime;
      tots->pr_minf += temp->pr_minf;
      tots->pr_majf += temp->pr_majf;
      tots->pr_nswap += temp->pr_nswap;
      tots->pr_inblk += temp->pr_inblk;
      tots->pr_oublk += temp->pr_oublk;
      tots->pr_msnd += temp->pr_msnd;
      tots->pr_mrcv += temp->pr_mrcv;
      tots->pr_sigs += temp->pr_sigs;
      tots->pr_vctx += temp->pr_vctx;
      tots->pr_ictx += temp->pr_ictx;
      tots->pr_sysc += temp->pr_sysc;
      tots->pr_ioch += temp->pr_ioch;
    }
  stats_item = create_stats_item ((long long) tots->pr_minf,
				  GTXT ("Minor Page Faults"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_majf,
				  GTXT ("Major Page Faults"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_nswap,
				  GTXT ("Process swaps"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_inblk,
				  GTXT ("Input blocks"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_oublk,
				  GTXT ("Output blocks"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_msnd,
				  GTXT ("Messages sent"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_mrcv,
				  GTXT ("Messages received"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_sigs,
				  GTXT ("Signals handled"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_vctx,
				  GTXT ("Voluntary context switches"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_ictx,
				  GTXT ("Involuntary context switches"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_sysc,
				  GTXT ("System calls"));
  stats_items->append (stats_item);
  stats_item = create_stats_item ((long long) tots->pr_ioch,
				  GTXT ("Characters of I/O"));
  stats_items->append (stats_item);
  delete tots;
}
