17c478bd9Sstevel@tonic-gate /*-
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
37c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
67c478bd9Sstevel@tonic-gate  * Margo Seltzer.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
97c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
107c478bd9Sstevel@tonic-gate  * are met:
117c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
127c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
137c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
147c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
157c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
167c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
177c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
187c478bd9Sstevel@tonic-gate  *	This product includes software developed by the University of
197c478bd9Sstevel@tonic-gate  *	California, Berkeley and its contributors.
207c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor the names of its contributors
217c478bd9Sstevel@tonic-gate  *    may be used to endorse or promote products derived from this software
227c478bd9Sstevel@tonic-gate  *    without specific prior written permission.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
257c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
287c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
297c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
307c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include "db-int.h"
407c478bd9Sstevel@tonic-gate #include "hash.h"
417c478bd9Sstevel@tonic-gate #include "page.h"
427c478bd9Sstevel@tonic-gate #include "extern.h"
437c478bd9Sstevel@tonic-gate 
4456a424ccSmp #if 0
457c478bd9Sstevel@tonic-gate static u_int32_t hash1 __P((const void *, size_t));
467c478bd9Sstevel@tonic-gate static u_int32_t hash2 __P((const void *, size_t));
477c478bd9Sstevel@tonic-gate static u_int32_t hash3 __P((const void *, size_t));
4856a424ccSmp #endif
497c478bd9Sstevel@tonic-gate static u_int32_t hash4 __P((const void *, size_t));
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /* Default hash function. */
527c478bd9Sstevel@tonic-gate u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Assume that we've already split the bucket to which this key hashes,
567c478bd9Sstevel@tonic-gate  * calculate that bucket, and check that in fact we did already split it.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * EJB's original hsearch hash.
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate #define PRIME1		37
617c478bd9Sstevel@tonic-gate #define PRIME2		1048583
627c478bd9Sstevel@tonic-gate 
6356a424ccSmp #if 0
647c478bd9Sstevel@tonic-gate static u_int32_t
657c478bd9Sstevel@tonic-gate hash1(key, len)
667c478bd9Sstevel@tonic-gate 	const void *key;
677c478bd9Sstevel@tonic-gate 	size_t len;
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	u_int32_t h;
707c478bd9Sstevel@tonic-gate 	u_int8_t *k;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	h = 0;
737c478bd9Sstevel@tonic-gate 	k = (u_int8_t *)key;
747c478bd9Sstevel@tonic-gate 	/* Convert string to integer */
757c478bd9Sstevel@tonic-gate 	while (len--)
767c478bd9Sstevel@tonic-gate 		h = h * PRIME1 ^ (*k++ - ' ');
777c478bd9Sstevel@tonic-gate 	h %= PRIME2;
787c478bd9Sstevel@tonic-gate 	return (h);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Phong Vo's linear congruential hash
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate #define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static u_int32_t
877c478bd9Sstevel@tonic-gate hash2(key, len)
887c478bd9Sstevel@tonic-gate 	const void *key;
897c478bd9Sstevel@tonic-gate 	size_t len;
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	u_int32_t h;
927c478bd9Sstevel@tonic-gate 	u_int8_t *e, c, *k;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	k = (u_int8_t *)key;
957c478bd9Sstevel@tonic-gate 	e = k + len;
967c478bd9Sstevel@tonic-gate 	for (h = 0; k != e;) {
977c478bd9Sstevel@tonic-gate 		c = *k++;
987c478bd9Sstevel@tonic-gate 		if (!c && k > e)
997c478bd9Sstevel@tonic-gate 			break;
1007c478bd9Sstevel@tonic-gate 		dcharhash(h, c);
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 	return (h);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
1077c478bd9Sstevel@tonic-gate  * units.  On the first time through the loop we get the "leftover bytes"
1087c478bd9Sstevel@tonic-gate  * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
1097c478bd9Sstevel@tonic-gate  * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
1107c478bd9Sstevel@tonic-gate  * this routine is heavily used enough, it's worth the ugly coding.
1117c478bd9Sstevel@tonic-gate  *
1127c478bd9Sstevel@tonic-gate  * Ozan Yigit's original sdbm hash.
1137c478bd9Sstevel@tonic-gate  */
1147c478bd9Sstevel@tonic-gate static u_int32_t
1157c478bd9Sstevel@tonic-gate hash3(key, len)
1167c478bd9Sstevel@tonic-gate 	const void *key;
1177c478bd9Sstevel@tonic-gate 	size_t len;
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	u_int32_t n, loop;
1207c478bd9Sstevel@tonic-gate 	u_int8_t *k;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate #define HASHC   n = *k++ + 65599 * n
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	n = 0;
1257c478bd9Sstevel@tonic-gate 	k = (u_int8_t *)key;
1267c478bd9Sstevel@tonic-gate 	if (len > 0) {
1277c478bd9Sstevel@tonic-gate 		loop = (len + 8 - 1) >> 3;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 		switch (len & (8 - 1)) {
1307c478bd9Sstevel@tonic-gate 		case 0:
1317c478bd9Sstevel@tonic-gate 			do {	/* All fall throughs */
1327c478bd9Sstevel@tonic-gate 				HASHC;
1337c478bd9Sstevel@tonic-gate 		case 7:
1347c478bd9Sstevel@tonic-gate 				HASHC;
1357c478bd9Sstevel@tonic-gate 		case 6:
1367c478bd9Sstevel@tonic-gate 				HASHC;
1377c478bd9Sstevel@tonic-gate 		case 5:
1387c478bd9Sstevel@tonic-gate 				HASHC;
1397c478bd9Sstevel@tonic-gate 		case 4:
1407c478bd9Sstevel@tonic-gate 				HASHC;
1417c478bd9Sstevel@tonic-gate 		case 3:
1427c478bd9Sstevel@tonic-gate 				HASHC;
1437c478bd9Sstevel@tonic-gate 		case 2:
1447c478bd9Sstevel@tonic-gate 				HASHC;
1457c478bd9Sstevel@tonic-gate 		case 1:
1467c478bd9Sstevel@tonic-gate 				HASHC;
1477c478bd9Sstevel@tonic-gate 			} while (--loop);
1487c478bd9Sstevel@tonic-gate 		}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 	return (n);
1527c478bd9Sstevel@tonic-gate }
15356a424ccSmp #endif
15456a424ccSmp 
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /* Chris Torek's hash function. */
1577c478bd9Sstevel@tonic-gate static u_int32_t
hash4(const void * key,size_t len)158*0b16192fSToomas Soome hash4(const void *key, size_t len)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	u_int32_t h, loop;
16156a424ccSmp 	const u_int8_t *k;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate #define HASH4a   h = (h << 5) - h + *k++;
1647c478bd9Sstevel@tonic-gate #define HASH4b   h = (h << 5) + h + *k++;
1657c478bd9Sstevel@tonic-gate #define HASH4 HASH4b
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	h = 0;
16856a424ccSmp 	k = (const u_int8_t *)key;
1697c478bd9Sstevel@tonic-gate 	if (len > 0) {
1707c478bd9Sstevel@tonic-gate 		loop = (len + 8 - 1) >> 3;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 		switch (len & (8 - 1)) {
1737c478bd9Sstevel@tonic-gate 		case 0:
1747c478bd9Sstevel@tonic-gate 			do {	/* All fall throughs */
1757c478bd9Sstevel@tonic-gate 				HASH4;
176*0b16192fSToomas Soome 				/* FALLTHROUGH */
1777c478bd9Sstevel@tonic-gate 		case 7:
1787c478bd9Sstevel@tonic-gate 				HASH4;
179*0b16192fSToomas Soome 				/* FALLTHROUGH */
1807c478bd9Sstevel@tonic-gate 		case 6:
1817c478bd9Sstevel@tonic-gate 				HASH4;
182*0b16192fSToomas Soome 				/* FALLTHROUGH */
1837c478bd9Sstevel@tonic-gate 		case 5:
1847c478bd9Sstevel@tonic-gate 				HASH4;
185*0b16192fSToomas Soome 				/* FALLTHROUGH */
1867c478bd9Sstevel@tonic-gate 		case 4:
1877c478bd9Sstevel@tonic-gate 				HASH4;
188*0b16192fSToomas Soome 				/* FALLTHROUGH */
1897c478bd9Sstevel@tonic-gate 		case 3:
1907c478bd9Sstevel@tonic-gate 				HASH4;
191*0b16192fSToomas Soome 				/* FALLTHROUGH */
1927c478bd9Sstevel@tonic-gate 		case 2:
1937c478bd9Sstevel@tonic-gate 				HASH4;
194*0b16192fSToomas Soome 				/* FALLTHROUGH */
1957c478bd9Sstevel@tonic-gate 		case 1:
1967c478bd9Sstevel@tonic-gate 				HASH4;
1977c478bd9Sstevel@tonic-gate 			} while (--loop);
1987c478bd9Sstevel@tonic-gate 		}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 	return (h);
2027c478bd9Sstevel@tonic-gate }
203