static char dqs_hash_rcsid[]="$Id: dqs_hash.c,v 1.1.1.1 1997/04/10 15:10:32 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  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);

}

