diff -urN ../nagios.orig/base/nagios.c ./base/nagios.c
--- ../nagios.orig/base/nagios.c	2005-05-26 14:12:45.000000000 +0200
+++ ./base/nagios.c	2005-06-15 13:32:06.000000000 +0200
@@ -479,6 +479,7 @@
 
 			/* reset program variables */
 			reset_variables();
+			initialize_hash_data();
 
 			/* get program (re)start time and save as macro */
 			program_start=time(NULL);
diff -urN ../nagios.orig/base/utils.c ./base/utils.c
--- ../nagios.orig/base/utils.c	2005-06-13 14:41:57.000000000 +0200
+++ ./base/utils.c	2005-06-15 13:24:04.000000000 +0200
@@ -4244,69 +4244,6 @@
 	return encoded_url_string;
         }
 
-
-
-/******************************************************************/
-/************************* HASH FUNCTIONS *************************/
-/******************************************************************/
-
-/* single hash function */
-int hashfunc1(const char *name1,int hashslots){
-	unsigned int i,result;
-
-	result=0;
-
-	if(name1)
-		for(i=0;i<strlen(name1);i++)
-			result+=name1[i];
-
-	result=result%hashslots;
-
-	return result;
-        }
-
-
-/* dual hash function */
-int hashfunc2(const char *name1,const char *name2,int hashslots){
-	unsigned int i,result;
-
-	result=0;
-	if(name1)
-		for(i=0;i<strlen(name1);i++)
-			result+=name1[i];
-
-	if(name2)
-		for(i=0;i<strlen(name2);i++)
-			result+=name2[i];
-
-	result=result%hashslots;
-
-	return result;
-        }
-
-
-/* single hash data comparison */
-int compare_hashdata1(const char *val1, const char *val2){
-	
-	return strcmp(val1,val2);
-        }
-
-
-/* dual hash data comparison */
-int compare_hashdata2(const char *val1a, const char *val1b, const char *val2a, const char *val2b){
-	int result;
-
-	result=strcmp(val1a,val2a);
-	if(result>0)
-		return 1;
-	else if(result<0)
-		return -1;
-	else
-		return strcmp(val1b,val2b);
-        }
-
-
-
 /******************************************************************/
 /************************* FILE FUNCTIONS *************************/
 /******************************************************************/
@@ -5094,6 +5031,9 @@
 	/* free memory allocated to comments */
 	free_comment_data();
 
+	/* free memory allocated to hash-tables */
+	free_hash_data();
+
 	/* free memory for the high priority event list */
 	this_event=event_list_high;
 	while(this_event!=NULL){
diff -urN ../nagios.orig/cgi/cgiutils.c ./cgi/cgiutils.c
--- ../nagios.orig/cgi/cgiutils.c	2004-11-15 09:28:06.000000000 +0100
+++ ./cgi/cgiutils.c	2005-06-15 13:37:31.000000000 +0200
@@ -199,6 +199,15 @@
 	my_strtok_buffer=NULL;
 	original_my_strtok_buffer=NULL;
 
+	/*
+	 * This might not be the best place for this call, but reset_cgi_vars()
+	 * is called exactly once at the very beginning of each cgi, so it
+	 * seems like a logical place to do it.
+	 *
+	 * Perhaps cgi_init() should be cooked up?
+	 */
+	initialize_hash_data();
+
 	return;
         }
 
@@ -679,71 +688,6 @@
         }
 
 
-
-/**********************************************************
- *************** CHAINED HASH FUNCTIONS *******************
- **********************************************************/
-
-
-/* single hash function */
-int hashfunc1(const char *name1,int hashslots){
-	unsigned int i,result;
-
-	result=0;
-
-	if(name1)
-		for(i=0;i<strlen(name1);i++)
-			result+=name1[i];
-
-	result=result%hashslots;
-
-	return result;
-        }
-
-
-/* dual hash function */
-int hashfunc2(const char *name1,const char *name2,int hashslots){
-	unsigned int i,result;
-
-	result=0;
-	if(name1)
-		for(i=0;i<strlen(name1);i++)
-			result+=name1[i];
-
-	if(name2)
-		for(i=0;i<strlen(name2);i++)
-			result+=name2[i];
-
-	result=result%hashslots;
-
-	return result;
-        }
-
-
-/* single hash data comparison */
-int compare_hashdata1(const char *val1, const char *val2){
-	
-	return strcmp(val1,val2);
-        }
-
-
-/* dual hash data comparison */
-int compare_hashdata2(const char *val1a, const char *val1b, const char *val2a, const char *val2b){
-	int result;
-
-	result=strcmp(val1a,val2a);
-	if(result>0)
-		return 1;
-	else if(result<0)
-		return -1;
-	else
-		return strcmp(val1b,val2b);
-        }
-
-
-
-
-
 /**********************************************************
  ******************* LIFO FUNCTIONS ***********************
  **********************************************************/
diff -urN ../nagios.orig/common/comments.c ./common/comments.c
--- ../nagios.orig/common/comments.c	2005-06-13 14:41:57.000000000 +0200
+++ ./common/comments.c	2005-06-15 11:29:36.000000000 +0200
@@ -27,6 +27,7 @@
 #include "../include/common.h"
 #include "../include/comments.h"
 #include "../include/objects.h"
+#include "../include/hash.h"
 
 /***** IMPLEMENTATION-SPECIFIC INCLUDES *****/
 
diff -urN ../nagios.orig/common/objects.c ./common/objects.c
--- ../nagios.orig/common/objects.c	2005-06-13 14:41:57.000000000 +0200
+++ ./common/objects.c	2005-06-15 13:34:16.000000000 +0200
@@ -26,6 +26,8 @@
 #include "../include/config.h"
 #include "../include/common.h"
 #include "../include/objects.h"
+#include "../include/statusdata.h" /* for hoststatus and servicestatus types */
+#include "../include/hash.h"
 
 #ifdef NSCORE
 #include "../include/nagios.h"
@@ -109,6 +111,71 @@
 /****************** CHAINED HASH FUNCTIONS ************************/
 /******************************************************************/
 
+/*
+ * hoist the conditional initialization out of the add_*_to_hashlist
+ * functions (it makes for terrible branch-prediction as the hashlists
+ * are always NULL at first pass, but never on subsequent ones).
+ * 
+ * Return -1 on errors (we *MUST* bail out if that happens)
+ */
+struct table_of_hashlists {
+	void **list;
+	int buckets;
+};
+
+extern struct hoststatus_struct **hoststatus_hashlist;
+extern struct servicestatus_struct **servicestatus_hashlist;
+
+int hash_init(int destroy)
+{
+	int i, mojo = 0;
+
+	struct table_of_hashlists nhash[] = {
+		{ (void **)host_hashlist, HOST_HASHSLOTS },
+		{ (void **)hostgroup_hashlist, HOSTGROUP_HASHSLOTS },
+		{ (void **)hostextinfo_hashlist, HOSTEXTINFO_HASHSLOTS },
+		{ (void **)hostescalation_hashlist, HOSTESCALATION_HASHSLOTS },
+		{ (void **)hostdependency_hashlist, HOSTDEPENDENCY_HASHSLOTS },
+
+		{ (void **)contact_hashlist, CONTACT_HASHSLOTS },
+		{ (void **)contactgroup_hashlist, CONTACTGROUP_HASHSLOTS },
+
+		{ (void **)command_hashlist, COMMAND_HASHSLOTS },
+		{ (void **)timeperiod_hashlist, TIMEPERIOD_HASHSLOTS },
+
+		{ (void **)service_hashlist, SERVICE_HASHSLOTS },
+		{ (void **)servicegroup_hashlist, SERVICEGROUP_HASHSLOTS },
+		{ (void **)serviceextinfo_hashlist, SERVICEEXTINFO_HASHSLOTS },
+		{ (void **)servicedependency_hashlist, SERVICEDEPENDENCY_HASHSLOTS },
+#ifdef NSCGI
+		{ (void **)hoststatus_hashlist, HOSTSTATUS_HASHSLOTS },
+		{ (void **)servicestatus_hashlist, SERVICESTATUS_HASHSLOTS },
+#endif
+		{ NULL, -1 },
+	};
+
+	if(!destroy) {
+		for(i = 0; nhash[i].buckets != -1; i++) {
+			if(!nhash[i].list)
+				nhash[i].list = calloc(nhash[i].buckets, sizeof(void *));
+			/* up the counter if this failed */
+			mojo += (nhash[i].list == NULL);
+		}
+
+		return mojo;
+	}
+
+	/* set to destroy */
+	for(i = 0; nhash[i].buckets != -1; i++) {
+		if(nhash[i].list) {
+			free(nhash[i].list);
+			nhash[i].list = NULL;
+		}
+	}
+
+	return 0;
+}
+
 /* adds host to hash list in memory */
 int add_host_to_hashlist(host *new_host){
 	host *temp_host, *lastpointer;
@@ -117,18 +184,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(host_hashlist==NULL){
-		int i;
-
-		host_hashlist=(host **)malloc(sizeof(host *)*HOST_HASHSLOTS);
-		if(host_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOST_HASHSLOTS;i++)
-			host_hashlist[i]=NULL;
-	        }
-
 	if(!new_host)
 		return 0;
 
@@ -164,18 +219,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(service_hashlist==NULL){
-		int i;
-
-		service_hashlist=(service **)malloc(sizeof(service *)*SERVICE_HASHSLOTS);
-		if(service_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i< SERVICE_HASHSLOTS;i++)
-			service_hashlist[i]=NULL;
-	        }
-
 	if(!new_service)
 		return 0;
 
@@ -212,18 +255,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(command_hashlist==NULL){
-		int i;
-
-		command_hashlist=(command **)malloc(sizeof(command *)*COMMAND_HASHSLOTS);
-		if(command_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<COMMAND_HASHSLOTS;i++)
-			command_hashlist[i]=NULL;
-	        }
-
 	if(!new_command)
 		return 0;
 
@@ -259,18 +290,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(timeperiod_hashlist==NULL){
-		int i;
-
-		timeperiod_hashlist=(timeperiod **)malloc(sizeof(timeperiod *)*TIMEPERIOD_HASHSLOTS);
-		if(timeperiod_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<TIMEPERIOD_HASHSLOTS;i++)
-			timeperiod_hashlist[i]=NULL;
-	        }
-
 	if(!new_timeperiod)
 		return 0;
 
@@ -306,18 +325,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(contact_hashlist==NULL){
-		int i;
-
-		contact_hashlist=(contact **)malloc(sizeof(contact *)*CONTACT_HASHSLOTS);
-		if(contact_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<CONTACT_HASHSLOTS;i++)
-			contact_hashlist[i]=NULL;
-	        }
-
 	if(!new_contact)
 		return 0;
 
@@ -353,18 +360,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(contactgroup_hashlist==NULL){
-		int i;
-
-		contactgroup_hashlist=(contactgroup **)malloc(sizeof(contactgroup *)*CONTACTGROUP_HASHSLOTS);
-		if(contactgroup_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<CONTACTGROUP_HASHSLOTS;i++)
-			contactgroup_hashlist[i]=NULL;
-	        }
-
 	if(!new_contactgroup)
 		return 0;
 
@@ -400,18 +395,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(hostgroup_hashlist==NULL){
-		int i;
-
-		hostgroup_hashlist=(hostgroup **)malloc(sizeof(hostgroup *)*HOSTGROUP_HASHSLOTS);
-		if(hostgroup_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOSTGROUP_HASHSLOTS;i++)
-			hostgroup_hashlist[i]=NULL;
-	        }
-
 	if(!new_hostgroup)
 		return 0;
 
@@ -447,18 +430,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(servicegroup_hashlist==NULL){
-		int i;
-
-		servicegroup_hashlist=(servicegroup **)malloc(sizeof(servicegroup *)*SERVICEGROUP_HASHSLOTS);
-		if(servicegroup_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<SERVICEGROUP_HASHSLOTS;i++)
-			servicegroup_hashlist[i]=NULL;
-	        }
-
 	if(!new_servicegroup)
 		return 0;
 
@@ -495,18 +466,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(hostextinfo_hashlist==NULL){
-		int i;
-
-		hostextinfo_hashlist=(hostextinfo **)malloc(sizeof(hostextinfo *)*HOSTEXTINFO_HASHSLOTS);
-		if(hostextinfo_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOSTEXTINFO_HASHSLOTS;i++)
-			hostextinfo_hashlist[i]=NULL;
-	        }
-
 	if(!new_hostextinfo)
 		return 0;
 
@@ -542,18 +501,6 @@
 	char temp_buffer[MAX_INPUT_BUFFER];
 #endif
 
-	/* initialize hash list */
-	if(serviceextinfo_hashlist==NULL){
-		int i;
-
-		serviceextinfo_hashlist=(serviceextinfo **)malloc(sizeof(serviceextinfo *)*SERVICEEXTINFO_HASHSLOTS);
-		if(serviceextinfo_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i< SERVICEEXTINFO_HASHSLOTS;i++)
-			serviceextinfo_hashlist[i]=NULL;
-	        }
-
 	if(!new_serviceextinfo)
 		return 0;
 
@@ -588,18 +535,6 @@
 	hostdependency *temp_hostdependency, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(hostdependency_hashlist==NULL){
-		int i;
-
-		hostdependency_hashlist=(hostdependency **)malloc(sizeof(hostdependency *)*HOSTDEPENDENCY_HASHSLOTS);
-		if(hostdependency_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOSTDEPENDENCY_HASHSLOTS;i++)
-			hostdependency_hashlist[i]=NULL;
-	        }
-
 	if(!new_hostdependency)
 		return 0;
 
@@ -623,18 +558,6 @@
 	servicedependency *temp_servicedependency, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(servicedependency_hashlist==NULL){
-		int i;
-
-		servicedependency_hashlist=(servicedependency **)malloc(sizeof(servicedependency *)*SERVICEDEPENDENCY_HASHSLOTS);
-		if(servicedependency_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i< SERVICEDEPENDENCY_HASHSLOTS;i++)
-			servicedependency_hashlist[i]=NULL;
-	        }
-
 	if(!new_servicedependency)
 		return 0;
 
@@ -659,18 +582,6 @@
 	hostescalation *temp_hostescalation, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(hostescalation_hashlist==NULL){
-		int i;
-
-		hostescalation_hashlist=(hostescalation **)malloc(sizeof(hostescalation *)*HOSTESCALATION_HASHSLOTS);
-		if(hostescalation_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOSTESCALATION_HASHSLOTS;i++)
-			hostescalation_hashlist[i]=NULL;
-	        }
-
 	if(!new_hostescalation)
 		return 0;
 
@@ -694,18 +605,6 @@
 	serviceescalation *temp_serviceescalation, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(serviceescalation_hashlist==NULL){
-		int i;
-
-		serviceescalation_hashlist=(serviceescalation **)malloc(sizeof(serviceescalation *)*SERVICEESCALATION_HASHSLOTS);
-		if(serviceescalation_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i< SERVICEESCALATION_HASHSLOTS;i++)
-			serviceescalation_hashlist[i]=NULL;
-	        }
-
 	if(!new_serviceescalation)
 		return 0;
 
diff -urN ../nagios.orig/common/statusdata.c ./common/statusdata.c
--- ../nagios.orig/common/statusdata.c	2005-06-13 14:41:57.000000000 +0200
+++ ./common/statusdata.c	2005-06-15 13:44:21.000000000 +0200
@@ -29,6 +29,7 @@
 #include "../include/common.h"
 #include "../include/objects.h"
 #include "../include/statusdata.h"
+#include "../include/hash.h"
 
 #ifdef NSCORE
 #include "../include/nagios.h"
@@ -207,18 +208,6 @@
 	hoststatus *temp_hoststatus, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(hoststatus_hashlist==NULL){
-		int i;
-
-		hoststatus_hashlist=(hoststatus **)malloc(sizeof(hoststatus *)*HOSTSTATUS_HASHSLOTS);
-		if(hoststatus_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i<HOSTSTATUS_HASHSLOTS;i++)
-			hoststatus_hashlist[i]=NULL;
-	        }
-
 	if(!new_hoststatus)
 		return 0;
 
@@ -246,18 +235,6 @@
 	servicestatus *temp_servicestatus, *lastpointer;
 	int hashslot;
 
-	/* initialize hash list */
-	if(servicestatus_hashlist==NULL){
-		int i;
-
-		servicestatus_hashlist=(servicestatus **)malloc(sizeof(servicestatus *)*SERVICESTATUS_HASHSLOTS);
-		if(servicestatus_hashlist==NULL)
-			return 0;
-		
-		for(i=0;i< SERVICESTATUS_HASHSLOTS;i++)
-			servicestatus_hashlist[i]=NULL;
-	        }
-
 	if(!new_servicestatus)
 		return 0;
 
diff -urN ../nagios.orig/include/cgiutils.h.in ./include/cgiutils.h.in
--- ../nagios.orig/include/cgiutils.h.in	2004-11-15 09:28:06.000000000 +0100
+++ ./include/cgiutils.h.in	2005-06-15 11:31:53.000000000 +0200
@@ -447,11 +447,6 @@
 int read_all_object_configuration_data(char *,int);
 int read_all_status_data(char *,int);
 
-int hashfunc1(const char *name1, int hashslots);
-int hashfunc2(const char *name1, const char *name2, int hashslots);
-int compare_hashdata1(const char *,const char *);
-int compare_hashdata2(const char *,const char *,const char *,const char *);
-
 void strip(char *);                                		/* strips newlines, carriage returns, and spaces from end of buffer */
 void sanitize_plugin_output(char *);                            /* strips HTML and bad characters from plugin output */
 
diff -urN ../nagios.orig/include/common.h ./include/common.h
--- ../nagios.orig/include/common.h	2005-05-26 14:12:45.000000000 +0200
+++ ./include/common.h	2005-06-15 13:37:09.000000000 +0200
@@ -37,6 +37,16 @@
 #undef USE_MEMORY_PERFORMANCE_TWEAKS
 
 
+/*
+ * hash functions are now in hash.h, except hash_init which is global.
+ * initialize_hash_data() is called from cgiutils.c, so the macro and
+ * the prototypes must either be here or in nagios.h and cgiutils.c.
+ */
+int hash_init(int destroy);
+#define initialize_hash_data() hash_init(0)
+#define free_hash_data() hash_init(1)
+
+
 
 /***************************** COMMANDS *********************************/
 
diff -urN ../nagios.orig/include/hash.h ./include/hash.h
--- ../nagios.orig/include/hash.h	1970-01-01 01:00:00.000000000 +0100
+++ ./include/hash.h	2005-06-15 14:04:41.000000000 +0200
@@ -0,0 +1,197 @@
+/*
+ * $Id: $
+ *
+ * lazy hash-functions for Nagios.
+ * Lazy because they don't require the string length to be known.
+ *
+ * Author: Andreas Ericsson <ae@op5.se>
+ *
+ * The functions in this file are supposed to be drop-in replacements for
+ * the current additive hashes, which use this semantic;
+ *
+ * hashfunc1(char *key, int buckets);
+ * hashfunc2(char *key1, char *key2, int buckets);
+ *
+ * Both those functions are *ALWAYS* called with 'buckets' being a macro
+ * and defined as a power of 2, making (buckets - 1) the preferred bitmask.
+ *
+ * Therefore those two functions are nowadays macros so that a (sane)
+ * preprocessor can consign the dec instruction to oblivion, making them
+ * half a cycle faster (significant with 20000 lookups, which is normal).
+ *
+ * That also means that we can only use linear hashes that work byte-wise.
+ * This isn't exactly optimal, and we'll be punished for it somewhat on
+ * multipiped CPU's as the internal state is always dependent on the next
+ * parsed byte. It's still roughly 40% faster than calling strlen() once
+ * for each key.
+ *
+ *
+ *  * Assumptions;
+ *    and is cheaper than modulo.
+ *    all tables hold a number of buckets that are a power of 2.
+ *    bitmask equals modulo, collision-wise (no xor-folding)
+ *    there is no spoon.
+ *
+ *
+ * Note that I (Andreas Ericsson) didn't invent any of the algorithms in
+ * here. I just implemented them. For licensing issues, see LICENSE.hash
+ * in the base directory of the Nagios distribution.
+ */
+
+/*
+ * General purpose hash-functions are inside this file to force them to
+ * reside in the same PTE as the callers. It also makes it possible to
+ * inline the functions, which won't work if they are referenced by address
+ * (as they would be if they reside in a non-local PTE)
+ */
+
+#ifndef NAGIOS_HASH_H
+#include "../include/config.h"  /* for types and such */
+
+/* close enough to accurate. Since we mask off the bits we need it doesn't
+ * matter if this is actually a 64 bit value. */
+typedef unsigned int u32;
+
+
+/***************** CHAINED HASH LIMITS ****************/
+/*
+ * All table-sizes *MUST* be powers of 2. This is so we can use a
+ * bitmask to extract the precision we want rather than a modulo op.
+ * Bitmasks use 0.5 latency cycles, while modulo range from 4 to 260.
+ */
+#define SERVICE_HASHSLOTS              8192
+#define HOST_HASHSLOTS                 8192
+#define COMMAND_HASHSLOTS              512
+#define TIMEPERIOD_HASHSLOTS           64
+#define CONTACT_HASHSLOTS              128
+#define CONTACTGROUP_HASHSLOTS         64
+#define HOSTGROUP_HASHSLOTS            128
+#define SERVICEGROUP_HASHSLOTS         128
+#define HOSTEXTINFO_HASHSLOTS          1024
+#define SERVICEEXTINFO_HASHSLOTS       1024
+
+#define HOSTDEPENDENCY_HASHSLOTS       1024
+#define SERVICEDEPENDENCY_HASHSLOTS    1024
+#define HOSTESCALATION_HASHSLOTS       1024
+#define SERVICEESCALATION_HASHSLOTS    1024
+
+#ifdef NSCGI
+/* these should only be used when compiling the CGI's, so trigger a
+ * compiler error if they're referenced somewhere in the core */
+# define SERVICESTATUS_HASHSLOTS        8192
+# define HOSTSTATUS_HASHSLOTS           8192
+#endif
+
+
+/* use Kiem-Phong Vo's linear congruential hash per default */
+#define USE_HASH_PHONG_VO1 1
+
+#if defined(USE_HASH_PHONG_VO1)
+/*
+ * lhash_phong_vo - Berkely License, The Regents of California
+ *
+ * Phong Vo's linear congruential hash.
+ */
+
+# define hash_func(key) lhash_phong_vo_lc1(key)
+# define DCHARHASH(h, c) ((h) = 0x63c63cd9 * (h) + 0x9c39c33d + ((unsigned char)c))
+static inline u32
+lhash_phong_vo_lc1(char *k)
+{
+	register u32 h = 0;
+
+	while(*k) DCHARHASH(h, *k++);
+	return h;
+}
+
+
+#elif defined(USE_HASH_PHONG_VO2)
+/*
+ * lhash_phong_vo_2 - Common Public License 1.0, AT & T Corp.
+ *
+ * Another linear congruential hash from the same author.
+ */
+# define hash_func(key) lhash_phong_vo_lc2(key)
+#define dtcharhash(h, c) (((h) << 4) + (h) + ((unsigned char)c) + 97531)
+static inline u32
+lhash_phong_vo_lc2(char *k)
+{
+	register u32 h = 0;
+
+	while(*k) h = dtcharhash(h, *k++);
+	return h;
+}
+#else
+/*
+ * lhash_gstr - GPL or Public Domain
+ *
+ * glib's g_str_hash(), with minor modifications.
+ *
+ * It produces a 31-bit hash, but that's OK since we won't use more than 16.
+ *
+ * Do a web search for "g_str_hash X31_HASH" if you want to know more.
+ * This is the same function as that described in Kernighan and Pike,
+ * "The Practice of Programming", section 2.9.
+ *
+ * This performs worse than the two above on P4, PentiumM and Athlon XP
+ * but is included anyways because of its loose and easily determined
+ * license.
+ */
+#define hash_func(key) lhash_gstr(key)
+static inline u32
+lhash_gstr(register char *k)
+{
+	register u32 h = 0;
+
+	while(*k)
+		h = (h << 5) - h + (unsigned char)*k++;       /* h * 31 + *key */
+
+	return h;
+}
+#endif /* hashtype selection */
+
+/* this assumes hash-table sizes are always powers of two */
+#define hashfunc1(key, buckets) hash_func(key) & (buckets - 1)
+#define hashfunc2(key1, key2, buckets) hash_dual_keys(key1, key2) & (buckets - 1)
+#define compare_hashdata1(k1, k2) strcmp(k1, k2)
+
+/*
+ * This must be a function because of the folding concat of the two hashes.
+ * With gcc >= 3.1 it can be replaced with a macro, but it would make a
+ * very small difference, if any.
+ */
+static inline u32
+hash_dual_keys(char *k1, char *k2)
+{
+	register u32 h1, h2;
+
+	/* get 32-bit hashes for this since we have to do some
+	 * entropy-preserving magic on the result */
+	h1 = hash_func(k1);
+	h2 = hash_func(k2);
+
+	/* This concatenation method was suggested by Paul Hsieh.
+	 * It prevents bits from cancelling if hashes are equal or there are
+	 * very few 1 bits set in h1. It's good enough for our purposes. */
+	return (h1 + (h2 >> 16)) ^ (h2 << 16);
+}
+
+/*
+ * This must also be a function, because of the variable needed to
+ * prevent double strcmp()'s.
+ */
+static inline u32
+compare_hashdata2(const char *k1a, const char *k1b, const char *k2a, const char *k2b)
+{
+	int result;
+
+	/* branch for collision. Faster on large networks but slower on small
+	 * ones. Large networks need the optimizations more. This enables the
+	 * calling function to make use of a few cycles *before* this function
+	 * actually returns (it's inline, remember?) */
+	if((result = strcmp(k1a, k2a)) != 0)
+		return result;
+
+	return strcmp(k1b, k2b);
+}
+#endif /* NAGIOS_HASH_H */
diff -urN ../nagios.orig/include/nagios.h.in ./include/nagios.h.in
--- ../nagios.orig/include/nagios.h.in	2005-06-07 17:58:24.000000000 +0200
+++ ./include/nagios.h.in	2005-06-15 14:05:28.000000000 +0200
@@ -595,13 +595,6 @@
 void free_notification_list(void);		     	/* frees all memory allocated to the notification list */
 
 
-/**** Hash Functions ****/
-int hashfunc1(const char *name1, int hashslots);
-int hashfunc2(const char *name1, const char *name2, int hashslots);
-int compare_hashdata1(const char *,const char *);
-int compare_hashdata2(const char *,const char *,const char *,const char *);
-
-
 /**** Miscellaneous Functions ****/
 void sighandler(int);                                	/* handles signals */
 void service_check_sighandler(int);                     /* handles timeouts when executing service checks */
diff -urN ../nagios.orig/include/objects.h ./include/objects.h
--- ../nagios.orig/include/objects.h	2004-11-15 09:28:06.000000000 +0100
+++ ./include/objects.h	2005-06-15 12:10:51.000000000 +0200
@@ -31,7 +31,6 @@
 #include "common.h"
 
 
-
 #define MAX_HOSTNAME_LENGTH            		64	/* max. host name length */
 #define MAX_SERVICEDESC_LENGTH			64	/* max. service description length */
 #define MAX_PLUGINOUTPUT_LENGTH			348	/* max. length of plugin output */
@@ -41,26 +40,6 @@
 #define MAX_CONTACT_ADDRESSES                   6       /* max number of custom addresses a contact can have */
 
 
-/***************** CHAINED HASH LIMITS ****************/
-
-#define SERVICE_HASHSLOTS                      1024
-#define HOST_HASHSLOTS                         1024
-#define COMMAND_HASHSLOTS                      256
-#define TIMEPERIOD_HASHSLOTS                   64
-#define CONTACT_HASHSLOTS                      128
-#define CONTACTGROUP_HASHSLOTS                 64
-#define HOSTGROUP_HASHSLOTS                    128
-#define SERVICEGROUP_HASHSLOTS                 128
-#define HOSTEXTINFO_HASHSLOTS                  1024
-#define SERVICEEXTINFO_HASHSLOTS               1024
-
-#define HOSTDEPENDENCY_HASHSLOTS               1024
-#define SERVICEDEPENDENCY_HASHSLOTS            1024
-#define HOSTESCALATION_HASHSLOTS               1024
-#define SERVICEESCALATION_HASHSLOTS            1024
-
-
-
 /****************** DATA STRUCTURES *******************/
 
 /* TIMERANGE structure */
diff -urN ../nagios.orig/include/statusdata.h ./include/statusdata.h
--- ../nagios.orig/include/statusdata.h	2004-11-05 15:18:52.000000000 +0100
+++ ./include/statusdata.h	2005-06-15 12:09:16.000000000 +0200
@@ -40,13 +40,6 @@
 #define READ_ALL_STATUS_DATA    READ_PROGRAM_STATUS | READ_HOST_STATUS | READ_SERVICE_STATUS
 
 
-
-/*************************** CHAINED HASH LIMITS ***************************/
-
-#define SERVICESTATUS_HASHSLOTS      1024
-#define HOSTSTATUS_HASHSLOTS         1024
-
-
 /**************************** DATA STRUCTURES ******************************/
 
 
