static char dqs_hash_rcsid[]="$Id: dqs_hash.c,v 1.1.1.1 1998/08/18 14:39:11 green Exp $";

/*----------------------------------------------------
 * dqs_hash.c Tom Green Mon Jan 31 10:42:45 1994
 *
 * Copyright 1993
 *
 * SUPER COMPUTER COMPUTATIONS RESEARCH INSTITUTE
 *            FLORIDA STATE UNIVERSITY
 *
 *
 * SCRI representatives make no claims about the
 * suitability of this software for any purpose.
 * It is provided "as is" without express or
 * implied warranty.
 *
 * $Log: dqs_hash.c,v $
 * Revision 1.1.1.1  1998/08/18 14:39:11  green
 * DQS 3.2.0.5 WIP Import
 *
 * Revision 1.1.1.1  1997/04/10 15:10:32  green
 * DQS 3.1.3.4.1 Distribution
 *
 * Revision 3.14  1996/11/20 23:03:49  nrl
 * Several fixes submitted by or as a result of investigations by
 * Ron Lee, Bodo Bechenback, Guntram Wolski and Frank Dwyyer.
 *
 * Revision 3.13  1996/03/22  04:20:30  nrl
 * Added error cataloguing number to all routines
 *
 * Revision 3.12  1996/03/14  03:16:13  nrl
 * merge in subordinate queues and consumable resource changes
 *
 * Revision 3.11  1995/07/12  18:47:51  nrl
 * Fixed numerous problmes with Irix 5.3 and 6.0 systems
 *
 * Revision 3.10  1995/05/28  16:44:37  nrl
 * Fixes for solaris2.3 and solaris 2.4 and mailer default recipients
 *
 * Revision 3.9  1995/02/24  23:36:21  nrl
 * Changed all Host lookups to use dqs_locate_host subroutine,
 * and changed that routine to look for the "registered host name"
 *
 * Revision 3.8  1995/02/23  23:13:49  nrl
 * Cleaned up some dangling pointers which were causing memory
 * corruption.
 *
 * Revision 3.7  1995/02/22  14:29:25  nrl
 * added "FREE" macro to make sure all freed pointers are NULL,
 * replaced all calls to free( ) with FREE.
 *
 * Revision 3.6  1994/06/19  18:39:29  green
 * ok, ok - now I really think I fixed dqs_free_hash()
 *
 * Revision 3.5  1994/06/19  14:39:26  green
 * fixed, (hopefully), dqs_free_hash()
 *
 * Revision 3.4  1994/06/16  20:24:12  green
 * got a bug in my dqs_free_hash() routine - commenting it out for now
 *
 * Revision 3.3  1994/06/15  21:01:53  green
 * minor type casting to prevent compiler warnings
 *
 * Revision 3.2  1994/06/15  19:18:40  green
 * uhh, what i said was "if (hptr)"
 *      what i meant was "if (!hptr)"...
 *
 * Revision 3.1  1994/06/15  15:29:19  green
 * support for using DQS trusted host list for dshd
 *
 * 	passing of Host_head -n dqs_c_dqs_execd.c
 * 	time stamp Host_head on deletion in dqs_c_qconf.c
 * 	ck trusted host list in dqs_dshd.c
 * 	grab Host_head at startup in dqs_execd.c
 * 	rebuild Host_head/Host_hash in dqs_execd_rebuild_host_hash.c
 * 	dqs_free_hash in dqs_hash.c
 * 	grab new Host_head in dqs_load_avg.c
 * 	error log/printing in dsh.c
 *
 * Bug in my syslog code(or certain vendors required nullifying use
 * of syslogd until I can track it down...
 *
 * Revision 3.0  1994/03/07  04:13:53  green
 * 3.0 freeze
 *
 * Revision 1.1.1.1  1994/02/01  17:57:41  green
 * DQS 3.0 ALPHA
 *
 *--------------------------------------------------*/


#include "h.h"
#include "def.h"
#include "dqs.h"
#include "struct.h"
#include "func.h"
#include "globals.h"
#include "dqs_errno.h"


/*******************************************************/
dqs_hash_type *dqs_hash_init()
     
{
  
  int           i;
  dqs_hash_type *tmp;
  dqs_hash_type *hash_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash_init"));
  
  hash_ptr=(dqs_hash_type *)calloc(hash_bucket_size+2,sizeof(dqs_hash_type));
  
  if (!hash_ptr)
    {
      CRITICAL((DQS_EVENT,"DQS_ERROR_0235 calloc() failure"));
      DEXITE;
      abort();
    }
  
  tmp=hash_ptr;
  for (i=0;i<hash_bucket_size+2;i++)
    {
      tmp->cp=NULL;
      tmp->vp=dqs_malloc(sizeof(char *));
      tmp->load_avg_ptr=(u_long32 *)dqs_malloc(sizeof(u_long32 *));
      tmp->lt_heard_from_ptr=(u_long32 *)dqs_malloc(sizeof(u_long32 *));
      tmp->next=NULL;
      tmp++;
    }
  
  DEXIT;
  return(hash_ptr);
  
}

/*******************************************************/
dqs_hash_type *dqs_free_hash(hptr)
     dqs_hash_type *hptr;
     
{
  
  int           i;
  dqs_hash_type *tmp;
  
  DENTER((DQS_EVENT,"dqs_free_hash"));
  
  if (!hptr)
    {
      DEXITE;
      return(NULL);
    }
  
  tmp=hptr;
  for (i=0;i<hash_bucket_size+2;i++)
    {
      FREE(tmp->cp);
      FREE(tmp->vp);
      FREE(tmp->load_avg_ptr);
      FREE(tmp->lt_heard_from_ptr);
      /* Note: small memory leak - need to run next list tpg */
      tmp++;
    }
  FREE(hptr);
  
  DEXIT;
  return((dqs_hash_type *)NULL);
  
}

/*******************************************************/
int dqs_hash(str)
     char *str;
     
{
  
  int h=0;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash"));
  
  if(!str) 
    {
      DEXITE;
      return(0);
    }
  
  h = *str++;
  while (*str)
    h = (h * 128 + *str++) % hash_bucket_size;
  if (h>=hash_bucket_size)
    h=hash_bucket_size;
  DPRINTF((DQS_EVENT,"hash_bucket_size %d returning %d",
	   hash_bucket_size,h));
  DEXIT;
  return(h);
  
}

/*******************************************************/
dqs_hash_type *dqs_hash_lookup(str,h_table)
     char *str;
     dqs_hash_type *h_table;
     
{
  int           hindex;
  dqs_hash_type *hash_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash_lookup"));
  DPRINTF((DQS_EVENT,"========>looking for >%s<",str));
  
  if (!str)
    {
      DEXIT;
      return(NULL);
    }
  
  if (!h_table)
    {
      DEXIT;
      return(h_table);
    }
  
  hindex=dqs_hash(str);
  hash_ptr=h_table;
  hash_ptr+=hindex;
  
  
  /*     while ((hash_ptr)&&(hash_ptr->cp))*/
  while (hash_ptr) 
    {
      if (!hash_ptr->cp)
	{
	  hash_ptr=hash_ptr->next;
	  break;
	}
      if (!dqs_strcasecmp(hash_ptr->cp,str)) 
	{
	  DEXIT;
	  return(hash_ptr);
	}
      hash_ptr=hash_ptr->next;
    }
  
  DEXITE;
  return((dqs_hash_type *)NULL);
  
}

/*******************************************************/
int dqs_hash_add(str,h_table)
     char *str;
     dqs_hash_type *h_table;
     
{
  
  char *cp;
  char   *buffer=NULL;
  int hindex;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash_add"));
  
  if (!str)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0236 error: NULL string passed to dqs_hash_add()"));
      DEXITE;
      return(-1);
    }
  
  if (!h_table)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0237 error: NULL hash_table passed to dqs_hash_add()"));
      DEXITE;
      return(-1);
    }
  
  if (dqs_hash_lookup(str,h_table)) 
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0238 error: element already exists"));
      DEXITE;
      return(-1);
    }
  
  if (str)
    {
      buffer=dqs_malloc(strlen(str)+1);
      DQS_ASSERT((strcpy(buffer,str)!=NULL));
    }
  
  hindex=dqs_hash(str);
  h_table+=hindex;
  
  if (!h_table->cp)
    {
      h_table->cp=buffer;
      h_table->vp=NULL;
      *h_table->load_avg_ptr=0;
      *h_table->lt_heard_from_ptr=0;
      DEXIT;
      return(0);
    }
  else
    {
      while (h_table->next) h_table=h_table->next;   /* find end of hashes in this bucket */
      
      h_table->next=(struct hashel *)dqs_malloc(sizeof(struct hashel));
      h_table->next->cp=buffer;
      h_table->next->load_avg_ptr=(u_long32 *)dqs_malloc(sizeof(u_long32));
      h_table->next->lt_heard_from_ptr=(u_long32 *)dqs_malloc(sizeof(u_long32));
      *h_table->next->load_avg_ptr=0;
      *h_table->next->lt_heard_from_ptr=0;
      h_table->next->next=NULL;
      h_table->next->vp=NULL;
    }
  
  DEXIT;
  return(0);
  
}

#ifdef FLIP
/*******************************************************/
int dqs_hash_add_queue(q)
     dqs_queue_type *q;
     
     /*
       
       dqs_hash_add_queue - adds a queue to Host_hash
       
       returns    -1  if queue already exist;
       0  if successful
       1  other recoverable error
       abort() non-recoverable error
     */
     
{
  
  int           hindex;
  char          *buffer=NULL;
  dqs_list_type *lp;
  dqs_hash_type *h_table;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash_add_queue"));
  
  if (!q)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0239 error: NULL queue passed to dqs_hash_add_queue()s"));
      DEXITE;
      return(1);
    }
  
  if (!q->qname)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0240 error: NULL queue->name passed to dqs_hash_add_queue()s"));
      DEXITE;
      return(1);
    }
  
  
  if (dqs_hash_lookup(q->qname,Queue_hash))
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0241 error: the queue \"%s\" already exists",q->qname));
      DEXITE;
      return(-1);
    }
  
  buffer=dqs_malloc(strlen(q->qname)+1);
  DQS_ASSERT((strcpy(buffer,q->qname)!=NULL));
  
  lp=Queue_head;
  while (lp)
    {
      if (!strcmp(lp->str0,q->qname))
	break;
      lp=lp->next;
    }
  
  if (!lp)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0242 error: could not resolve \"%s\"",
	     q->qname));
      abort();
    }
  
  if (!lp->queue)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0243 error: Queue_list is screwed"));
      abort();
    }
  
  h_table=Queue_hash;
  
  hindex=dqs_hash(buffer);
  h_table+=hindex;
  
  if (!h_table->cp)
    {
      h_table->cp=buffer;
      h_table->vp=(char *)lp->queue;
    }
  else
    {
      while (h_table->next)
	h_table=h_table->next;
      h_table->next=(struct hashel *)dqs_malloc(sizeof(struct hashel));
      h_table->next->cp=buffer;
      h_table->next->vp=(char *)lp->queue;
      h_table->next->next=NULL;
    }
  
  DEXIT;
  return(0);
  
}
#endif

/*******************************************************/
int dqs_hash_del(str,h_table)
     char *str;
     dqs_hash_type *h_table;
     
{
  int           hindex;
  struct hashel *freeptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_hash_del"));
  
  if (!str)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0244 error: NULL string passed to dqs_hash_del()"));
      DEXITE;
      return(-1);
    }
  
  if (!h_table)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0245 error: NULL hash_table passed to dqs_hash_del()"));
      DEXITE;
      return(-1);
    }
  
  hindex=dqs_hash(str);
  h_table+=hindex;
  
  if (!h_table->cp)
    {
      ERROR((DQS_EVENT,"DQS_ERROR_0246 error: hash table is screwed"));
      abort();
    }
  
  if (!dqs_strcasecmp(h_table->cp,str)) 
    {
      FREE(h_table->cp);
      
      /* we're gonna leave the other fields JIC I screwed up elsewhere */
      if (h_table->next)
	{
	  h_table->cp=h_table->next->cp;
	  h_table->vp=h_table->next->vp;
	  h_table->load_avg_ptr=h_table->next->load_avg_ptr;
	  h_table->lt_heard_from_ptr=h_table->next->lt_heard_from_ptr;
	  freeptr=h_table->next;
	  h_table->next=h_table->next->next;
	  FREE(freeptr);
	}
      DEXIT;
      return(0);
    }
  
  while(h_table->next) 
    {
      if (!h_table->next->cp)
	{
	  CRITICAL((DQS_EVENT,"DQS_ERROR_0247 error: hash table screwed"));
	  DEXITE;
	  abort();
	}
      
      if (!dqs_strcasecmp(h_table->next->cp,str)) 
	{
	  freeptr=h_table->next;
	  
	  h_table->next=h_table->next->next;
	  FREE(freeptr->cp);
	  FREE(freeptr);
	  DEXIT;
	  return(0);
	}
      h_table=h_table->next;
    }
  
  DEXITE;
  return(-1);
  
}

/*******************************************************/
dqs_job_type *dqs_locate_job(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER((DQS_EVENT,"dqs_locate_job"));
  
  hashel_ptr=dqs_hash_lookup(cp,Job_hash);
  
  if (!hashel_ptr)
    {
      DEXITE;
      return(NULL);
    }
  
  if (!hashel_ptr->vp)
    {
      CRITICAL((DQS_EVENT,"DQS_ERROR_0248 error: Job_hash is screwed"));
      abort();
    }
  
  DEXIT;
  return((dqs_job_type *)hashel_ptr->vp);
  
}

/*******************************************************/
dqs_queue_type *dqs_locate_queue(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_queue"));
  
  if (!cp)
    {
      DEXITE;
      return(NULL);
    }
  
  
  hashel_ptr=dqs_hash_lookup(cp,Queue_hash);
  
  if (!hashel_ptr)
    {
      DPRINTF((DQS_EVENT,"I'M RETURNING NULL!!"));
      DEXITE;
      return(NULL);
    }
  
  if (!hashel_ptr->vp)
    {
      CRITICAL((DQS_EVENT,"DQS_ERROR_0249 error: Queue_hash is screwed"));
      abort();
    }
  
  DEXIT;
  return((dqs_queue_type *)hashel_ptr->vp);
  
}

/*******************************************************/
dqs_list_type *dqs_locate_complex(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_complex"));
  
  hashel_ptr=dqs_hash_lookup(cp,Complex_hash);
  
  if (!hashel_ptr)
    {
      DPRINTF((DQS_EVENT,"I'M RETURNING NULL!!"));
      DEXITE;
      return(NULL);
    }
  
  if (!hashel_ptr->vp)
    {
      CRITICAL((DQS_EVENT,"DQS_ERROR_0250 error: Complex_hash is screwed"));
      abort();
    }
  
  DEXIT;
  return((dqs_list_type *)hashel_ptr->vp);
  
}

/*******************************************************/
dqs_hash_type *dqs_locate_host(cp)
     char *cp;
     
{
  
  
  
  
  dqs_hash_type *hashel_ptr;
  struct hostent *hp;
  char local[256];
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_host"));
  
  if(!cp){
    DEXITE;
    return(NULL);
  }
  strcpy(local,cp);              /* save locally to avoid recursion error */
  hp=gethostbyname(local);          /* get official name   */
  
  if(!hp) {
    DEXITE;
    return(NULL);
  }
  
  hashel_ptr=dqs_hash_lookup(hp->h_name,Host_hash);
  
  if (!hashel_ptr)
    {
      DEXITE;
      return(NULL);
    }
  
  DEXIT;
  return(hashel_ptr);
  
}

/*******************************************************/
dqs_hash_type *dqs_locate_manager(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_manager"));
  
  hashel_ptr=dqs_hash_lookup(cp,Man_hash);
  
  if (!hashel_ptr)
    {
      DEXITE;
      return(NULL);
    }
  
  DEXIT;
  return(hashel_ptr);
  
}

/*******************************************************/
dqs_hash_type *dqs_locate_operator(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_operator"));
  
  hashel_ptr=dqs_hash_lookup(cp,Op_hash);
  if (hashel_ptr)
    {
      DEXIT;
      return(hashel_ptr);
    }
  
  hashel_ptr=dqs_hash_lookup(cp,Op_hash);
  if (hashel_ptr)
    {
      DEXIT;
      return(hashel_ptr);
    }
  
  DEXITE;
  return(NULL);
  
}

/*******************************************************/
dqs_hash_type *dqs_locate_acl(cp)
     char *cp;
     
{
  
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_acl"));
  
  hashel_ptr=dqs_hash_lookup(cp,Acl_hash);
  
  if (!hashel_ptr)
    {
      DEXITE;
      return(NULL);
    }
  
  DEXIT;
  return(hashel_ptr);
  
}

/*******************************************************/
dqs_list_type *dqs_locate_consumable(cp)
     char *cp;
     
{
  dqs_hash_type *hashel_ptr;
  
  DENTER_EXT((DQS_EVENT,"dqs_locate_consumable"));
  
  hashel_ptr=dqs_hash_lookup(cp,Consumable_hash);
  
  if (!hashel_ptr)
    {
      DPRINTF((DQS_EVENT,"I'M RETURNING NULL!!"));
      DEXITE;
      return(NULL);
    }
  
  if (!hashel_ptr->vp)
    {
      CRITICAL((DQS_EVENT,"DQS_ERROR_0251 error: Consumable_hash is screwed"));
      abort();
    }
  
  DEXIT;
  return((dqs_list_type *)hashel_ptr->vp);
  
}

