/*
 * hash.c
 * Process hashing functions for gmemusage.
 *
 * Copyright (C) 1997, 1998 by Raju Mathur (raju@sgi.com)
 *
 * See file COPYING (included in this distribution) for copyright information.
 */
#include <stdio.h>
#include <malloc.h>
#include "common.h"

/*
{
*/
   const int
      minProcs = 16 ;
   static struct ProcInfo
      *procs = NULL ;
   static struct ProcInfo
      *nextproc = NULL ;
   static int
      nProcs = 0 ;
   static int
      lastallocated ;
/*
}
*/
/*
 * Find a process with matching name in the process array.
 * Currently using linear search, enhance to any method you
 * choose. Hash may not be a bad idea.
 */
struct ProcInfo
*LookupProc ( char *name )
{
   register struct ProcInfo
      *pi ;

   for ( pi = procs ; pi - procs < nProcs ; pi++ )
   {
      if ( !strcmp ( pi -> procname , name ) )
      {
	 return ( pi ) ;
      }
   }
   return NULL ;
}
/*
 * Update existing process entry, or add a process to the
 * process array.
 */
void
addProc ( char *procname , int mem , int rss )
{
   register struct ProcInfo
      *thisproc ;
/*
 * is the array empty?
 */
   if ( !procs )
   {
      lastallocated = minProcs ;
      if ( ( procs = calloc ( minProcs , sizeof ( struct ProcInfo ) ) )
	   == NULL )
      {
	 fprintf ( stderr , "%s: cannot alloc %d processes" , progname ,
		   minProcs ) ;
	 perror ( "" ) ;
	 exit ( 1 ) ;
      }
/* printf("allocated %d procs\n",lastallocated); */
      thisproc = nextproc = procs ;
      strcpy ( thisproc -> procname , procname ) ;
      thisproc -> totMem = mem ;
      thisproc -> totRSS = rss ;
      thisproc -> nProcs = 1 ;
      nProcs = 1 ;
   }
/*
 * if a process with that name doesn't already exist in the
 * array, make a new entry. Allocate more space if necessary.
 */
   else if ( !( thisproc = LookupProc ( procname ) ) )
   {
      if ( nProcs == lastallocated )	/* no more space */
      {
	 lastallocated *= 2 ;
	 if ( ( procs = realloc
		( procs , lastallocated * sizeof ( struct ProcInfo) ) )
	      == NULL )
	 {
	    fprintf ( stderr , "%s: cannot alloc %d processes" ,
		      progname , lastallocated ) ;
	    perror ( "" ) ;
	    exit ( 1 ) ;
	 }
/* printf("allocated %d procs\n",lastallocated); */
      }
      thisproc = procs + nProcs ;
      strcpy ( thisproc -> procname , procname ) ;
      thisproc -> totMem = mem ;
      thisproc -> totRSS = rss ;
      thisproc -> nProcs = 1 ;
      nProcs++ ;
   }
   else
   {
      thisproc -> totMem += mem ;
      thisproc -> totRSS += rss ;
      thisproc -> nProcs++ ;
   }
}
/*
 * Return the next process linearly from the process
 * array, or NULL if no more.
 */
struct ProcInfo
*NextProc ( void )
{
   if ( nextproc - procs == nProcs )
   {
      return NULL ;
   }
   else
   {
      return nextproc++ ;
   }
}
struct ProcInfo
*AllProcs ( int *n )
{
   *n = nProcs ;
   return procs ;
}
/*
 * Clear out and deallocate the process list and
 * associated variables.
 */
void
ClearProcs ( void )
{
   if ( procs )
   {
      free ( procs ) ;
      procs = NULL ;
      lastallocated = nProcs = 0 ;
      nextproc = NULL ;
   }
}
