*** innd/his.c.orig	Tue Dec 17 09:40:40 1996
--- innd/his.c	Mon Jul 21 20:32:45 1997
***************
*** 1,4 ****
! /*  $Revision: 1.23 $
  **
  **  History file routines.
  */
--- 1,4 ----
! /*  $Revision: 1.2+histcache$
  **
  **  History file routines.
  */
***************
*** 9,14 ****
--- 9,25 ----
  #include "innd.h"
  #include "dbz.h"
  
+ /*
+  * history lookup cache
+  */
+ #define HISCACHESIZE  (64 * 1024L)    /* num elements in lookup cache array */
+ typedef struct {
+     long              MessageIDHash;
+     BOOL              Found;
+ } _HIScache;
+ STATIC _HIScache      HIScache[HISCACHESIZE];
+ unsigned long         HIScachehits;
+ unsigned long         HIScachelookups;
  
  STATIC char	HIShistpath[] = _PATH_HISTORY;
  STATIC FILE	*HISwritefp;
***************
*** 46,51 ****
--- 57,65 ----
  	    exit(1);
  	}
      }
+     /* initialize history lookup cache data */
+     memset((void *)&HIScache, 0, sizeof(HIScache));
+     HIScachehits = HIScachelookups = 0;
  }
  
  
***************
*** 84,89 ****
--- 98,107 ----
  	    syslog(L_ERROR, "%s cant close history %m", LogName);
  	HISreadfd = -1;
      }
+ 
+     if (HIScachelookups > 0)
+         syslog(L_NOTICE, "SERVER history cache final: %lu lookups, %lu hits",
+        	       HIScachelookups, HIScachehits);
  }
  
  
***************
*** 198,206 ****
--- 216,244 ----
  {
      datum	key;
      datum	val;
+     long	hash_pos, hash_val;
+ 
+ 
+     /* hash msg id */
+     hash_val = dbzhash(MessageID, strlen(MessageID));
+     hash_pos = hash_val % HISCACHESIZE;
+ 
+     /* check history lookup cache for hashed msg id */
+     HIScachelookups++;
+     if (HIScache[hash_pos].MessageIDHash == hash_val) {
+         HIScachehits++;
+         return HIScache[hash_pos].Found;
+     }
  
+     /* check dbz history for msg id */
      HISsetkey(MessageID, &key);
      val = dbzfetch(key);
+ 
+     /* store hashed msg id, lookup result in history lookup cache */
+     HIScache[hash_pos].MessageIDHash = hash_val;
+     HIScache[hash_pos].Found = (char)(val.dptr != NULL);
+ 
+     /* return result of lookup */
      return val.dptr != NULL;
  }
  
***************
*** 237,243 ****
      char		*paths;
  {
      static char		NOPATHS[] = "";
!     long		offset;
      datum		key;
      datum		val;
      int			i;
--- 275,281 ----
      char		*paths;
  {
      static char		NOPATHS[] = "";
!     long		offset, hash_val, hash_pos;
      datum		key;
      datum		val;
      int			i;
***************
*** 278,283 ****
--- 316,326 ----
  	IOError("history database", i);
  	return FALSE;
      }
+     /* store hashed message id value in history lookup cache */
+     hash_val = dbzhash(Data->MessageID, strlen(Data->MessageID));
+     hash_pos = hash_val % HISCACHESIZE;
+     HIScache[hash_pos].MessageIDHash = hash_val;
+     HIScache[hash_pos].Found = TRUE;
  
      if (++HISdirty >= ICD_SYNC_COUNT)
  	HISsync();
*** dbz/dbz.c.orig	Tue Dec 17 09:40:40 1996
--- dbz/dbz.c	Mon Jul 21 20:24:56 1997
***************
*** 355,361 ****
  extern void CloseOnExec();
  
  /* misc. forwards */
- static long hash();
  static void crcinit();
  static char *cipoint();
  static char *mapcase();
--- 355,360 ----
***************
*** 1426,1432 ****
  {
  	register long h;
  
! 	h = hash(kp->dptr, kp->dsize);
  	if (osp != FRESH && osp->hash == h) {
  		if (sp != osp)
  			*sp = *osp;
--- 1425,1431 ----
  {
  	register long h;
  
! 	h = dbzhash(kp->dptr, kp->dsize);
  	if (osp != FRESH && osp->hash == h) {
  		if (sp != osp)
  			*sp = *osp;
***************
*** 1716,1725 ****
  }
  
  /*
!  - hash - Honeyman's nice hashing function
   */
! static long
! hash(name, size)
  register char *name;
  register int size;
  {
--- 1715,1724 ----
  }
  
  /*
!  - dbzhash - Honeyman's nice hashing function
   */
! long
! dbzhash(name, size)
  register char *name;
  register int size;
  {
*** dbz/dbz.h.orig	Tue Dec 17 09:40:40 1996
--- dbz/dbz.h	Mon Jul 21 20:24:55 1997
***************
*** 24,29 ****
--- 24,30 ----
  extern int dbzcancel();
  extern int dbzdebug();
  extern int dbzwritethrough();
+ extern long dbzhash();
  
  /*
   * In principle we could handle unlimited-length keys by operating a chunk
