xref: /csrg-svn/lib/libc/db/hash/hash_page.c (revision 51055)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Margo Seltzer.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)hash_page.c	5.15 (Berkeley) 09/08/91";
13 #endif /* LIBC_SCCS and not lint */
14 
15 /*
16  * PACKAGE:  hashing
17  *
18  * DESCRIPTION:
19  *	Page manipulation for hashing package.
20  *
21  * ROUTINES:
22  *
23  * External
24  *	__get_page
25  *	__add_ovflpage
26  * Internal
27  *	overflow_page
28  *	open_temp
29  */
30 
31 #include <sys/param.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <errno.h>
35 #include <db.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #ifdef DEBUG
41 #include <assert.h>
42 #endif
43 #include "hash.h"
44 #include "page.h"
45 #include "extern.h"
46 
47 static u_long	*fetch_bitmap __P((int));
48 static u_long	 first_free __P((u_long));
49 static int	 open_temp __P((void));
50 static u_short	 overflow_page __P((void));
51 static void	 putpair __P((char *, const DBT *, const DBT *));
52 static void	 squeeze_key __P((u_short *, const DBT *, const DBT *));
53 static int	 ugly_split __P((u_int, BUFHEAD *, BUFHEAD *, int, int));
54 
55 #define	PAGE_INIT(P) { \
56 	((u_short *)(P))[0] = 0; \
57 	((u_short *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_short); \
58 	((u_short *)(P))[2] = hashp->BSIZE; \
59 }
60 
61 /*
62  * This is called AFTER we have verified that there is room on the page for
63  * the pair (PAIRFITS has returned true) so we go right ahead and start moving
64  * stuff on.
65  */
66 static void
67 putpair(p, key, val)
68 	char *p;
69 	const DBT *key, *val;
70 {
71 	register u_short *bp, n, off;
72 
73 	bp = (u_short *)p;
74 
75 	/* Enter the key first. */
76 	n = bp[0];
77 
78 	off = OFFSET(bp) - key->size;
79 	bcopy(key->data, p + off, key->size);
80 	bp[++n] = off;
81 
82 	/* Now the data. */
83 	off -= val->size;
84 	bcopy(val->data, p + off, val->size);
85 	bp[++n] = off;
86 
87 	/* Adjust page info. */
88 	bp[0] = n;
89 	bp[n + 1] = off - ((n + 3) * sizeof(u_short));
90 	bp[n + 2] = off;
91 }
92 
93 /*
94  * Returns:
95  *	 0 OK
96  *	-1 error
97  */
98 extern int
99 __delpair(bufp, ndx)
100 	BUFHEAD *bufp;
101 	register int ndx;
102 {
103 	register u_short *bp, newoff;
104 	register int n;
105 	u_short pairlen;
106 
107 	bp = (u_short *)bufp->page;
108 	n = bp[0];
109 
110 	if (bp[ndx + 1] < REAL_KEY)
111 		return (__big_delete(bufp));
112 	if (ndx != 1)
113 		newoff = bp[ndx - 1];
114 	else
115 		newoff = hashp->BSIZE;
116 	pairlen = newoff - bp[ndx + 1];
117 
118 	if (ndx != (n - 1)) {
119 		/* Hard Case -- need to shuffle keys */
120 		register int i;
121 		register char *src = bufp->page + (int)OFFSET(bp);
122 		register char *dst = src + (int)pairlen;
123 		bcopy(src, dst, bp[ndx + 1] - OFFSET(bp));
124 
125 		/* Now adjust the pointers */
126 		for (i = ndx + 2; i <= n; i += 2) {
127 			if (bp[i + 1] == OVFLPAGE) {
128 				bp[i - 2] = bp[i];
129 				bp[i - 1] = bp[i + 1];
130 			} else {
131 				bp[i - 2] = bp[i] + pairlen;
132 				bp[i - 1] = bp[i + 1] + pairlen;
133 			}
134 		}
135 	}
136 	/* Finally adjust the page data */
137 	bp[n] = OFFSET(bp) + pairlen;
138 	bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_short);
139 	bp[0] = n - 2;
140 	hashp->NKEYS--;
141 
142 	bufp->flags |= BUF_MOD;
143 	return (0);
144 }
145 /*
146  * Returns:
147  *	 0 ==> OK
148  *	-1 ==> Error
149  */
150 extern int
151 __split_page(obucket, nbucket)
152 	u_int obucket, nbucket;
153 {
154 	register BUFHEAD *new_bufp, *old_bufp;
155 	register u_short *ino;
156 	register char *np;
157 	DBT key, val;
158 	int n, ndx, retval;
159 	u_short copyto, diff, off, moved;
160 	char *op;
161 
162 	copyto = (u_short)hashp->BSIZE;
163 	off = (u_short)hashp->BSIZE;
164 	old_bufp = __get_buf(obucket, NULL, 0);
165 	new_bufp = __get_buf(nbucket, NULL, 0);
166 
167 	old_bufp->flags |= (BUF_MOD | BUF_PIN);
168 	new_bufp->flags |= (BUF_MOD | BUF_PIN);
169 
170 	ino = (u_short *)(op = old_bufp->page);
171 	np = new_bufp->page;
172 
173 	moved = 0;
174 
175 	for (n = 1, ndx = 1; n < ino[0]; n += 2) {
176 		if (ino[n + 1] < REAL_KEY) {
177 			retval = ugly_split(obucket, old_bufp, new_bufp,
178 			    (int)copyto, (int)moved);
179 			old_bufp->flags &= ~BUF_PIN;
180 			new_bufp->flags &= ~BUF_PIN;
181 			return (retval);
182 
183 		}
184 		key.data = (u_char *)op + ino[n];
185 		key.size = off - ino[n];
186 
187 		if (__call_hash(key.data, key.size) == obucket) {
188 			/* Don't switch page */
189 			diff = copyto - off;
190 			if (diff) {
191 				copyto = ino[n + 1] + diff;
192 				bcopy(op + ino[n + 1], op + copyto,
193 				    off - ino[n + 1]);
194 				ino[ndx] = copyto + ino[n] - ino[n + 1];
195 				ino[ndx + 1] = copyto;
196 			} else
197 				copyto = ino[n + 1];
198 			ndx += 2;
199 		} else {
200 			/* Switch page */
201 			val.data = (u_char *)op + ino[n + 1];
202 			val.size = ino[n] - ino[n + 1];
203 			putpair(np, &key, &val);
204 			moved += 2;
205 		}
206 
207 		off = ino[n + 1];
208 	}
209 
210 	/* Now clean up the page */
211 	ino[0] -= moved;
212 	FREESPACE(ino) = copyto - sizeof(u_short) * (ino[0] + 3);
213 	OFFSET(ino) = copyto;
214 
215 #ifdef DEBUG3
216 	(void)fprintf(stderr, "split %d/%d\n",
217 	    ((u_short *)np)[0] / 2,
218 	    ((u_short *)op)[0] / 2);
219 #endif
220 	/* unpin both pages */
221 	old_bufp->flags &= ~BUF_PIN;
222 	new_bufp->flags &= ~BUF_PIN;
223 	return (0);
224 }
225 
226 /*
227  * Called when we encounter an overflow or big key/data page during split
228  * handling.  This is special cased since we have to begin checking whether
229  * the key/data pairs fit on their respective pages and because we may need
230  * overflow pages for both the old and new pages.
231  *
232  * The first page might be a page with regular key/data pairs in which case
233  * we have a regular overflow condition and just need to go on to the next
234  * page or it might be a big key/data pair in which case we need to fix the
235  * big key/data pair.
236  *
237  * Returns:
238  *	 0 ==> success
239  *	-1 ==> failure
240  */
241 static int
242 ugly_split(obucket, old_bufp, new_bufp, copyto, moved)
243 	u_int obucket;	/* Same as __split_page. */
244 	BUFHEAD *old_bufp, *new_bufp;
245 	int copyto;	/* First byte on page which contains key/data values. */
246 	int moved;	/* Number of pairs moved to new page. */
247 {
248 	register BUFHEAD *bufp;	/* Buffer header for ino */
249 	register u_short *ino;	/* Page keys come off of */
250 	register u_short *np;	/* New page */
251 	register u_short *op;	/* Page keys go on to if they aren't moving */
252 
253 	BUFHEAD *last_bfp;	/* Last buf header OVFL needing to be freed */
254 	DBT key, val;
255 	SPLIT_RETURN ret;
256 	u_short n, off, ov_addr, scopyto;
257 	char *cino;		/* Character value of ino */
258 
259 	bufp = old_bufp;
260 	ino = (u_short *)old_bufp->page;
261 	np = (u_short *)new_bufp->page;
262 	op = (u_short *)old_bufp->page;
263 	last_bfp = NULL;
264 	scopyto = (u_short)copyto;	/* ANSI */
265 
266 	n = ino[0] - 1;
267 	while (n < ino[0]) {
268 		if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
269 			/*
270 			 * Ov_addr gets set before reaching this point; there's
271 			 * always an overflow page before a big key/data page.
272 			 */
273 			if (__big_split(old_bufp,
274 			    new_bufp, bufp, ov_addr, obucket, &ret))
275 				return (-1);
276 			old_bufp = ret.oldp;
277 			if (!old_bufp)
278 				return (-1);
279 			op = (u_short *)old_bufp->page;
280 			new_bufp = ret.newp;
281 			if (!new_bufp)
282 				return (-1);
283 			np = (u_short *)new_bufp->page;
284 			bufp = ret.nextp;
285 			if (!bufp)
286 				return (0);
287 			cino = (char *)bufp->page;
288 			ino = (u_short *)cino;
289 			last_bfp = ret.nextp;
290 		} else if (ino[n + 1] == OVFLPAGE) {
291 			ov_addr = ino[n];
292 			/*
293 			 * Fix up the old page -- the extra 2 are the fields
294 			 * which contained the overflow information.
295 			 */
296 			ino[0] -= (moved + 2);
297 			FREESPACE(ino) =
298 			    scopyto - sizeof(u_short) * (ino[0] + 3);
299 			OFFSET(ino) = scopyto;
300 
301 			bufp = __get_buf(ov_addr, bufp, 0);
302 			if (!bufp)
303 				return (-1);
304 
305 			ino = (u_short *)bufp->page;
306 			n = 1;
307 			scopyto = hashp->BSIZE;
308 			moved = 0;
309 
310 			if (last_bfp)
311 				__free_ovflpage(last_bfp);
312 			last_bfp = bufp;
313 		}
314 		/* Move regular sized pairs of there are any */
315 		off = hashp->BSIZE;
316 		for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
317 			cino = (char *)ino;
318 			key.data = (u_char *)cino + ino[n];
319 			key.size = off - ino[n];
320 			val.data = (u_char *)cino + ino[n + 1];
321 			val.size = ino[n] - ino[n + 1];
322 			off = ino[n + 1];
323 
324 			if (__call_hash(key.data, key.size) == obucket) {
325 				/* Keep on old page */
326 				if (PAIRFITS(op, (&key), (&val)))
327 					putpair((char *)op, &key, &val);
328 				else {
329 					old_bufp = __add_ovflpage(old_bufp);
330 					if (!old_bufp)
331 						return (-1);
332 					op = (u_short *)old_bufp->page;
333 					putpair((char *)op, &key, &val);
334 				}
335 				old_bufp->flags |= BUF_MOD;
336 			} else {
337 				/* Move to new page */
338 				if (PAIRFITS(np, (&key), (&val)))
339 					putpair((char *)np, &key, &val);
340 				else {
341 					new_bufp = __add_ovflpage(new_bufp);
342 					if (!new_bufp)
343 						return (-1);
344 					np = (u_short *)new_bufp->page;
345 					putpair((char *)np, &key, &val);
346 				}
347 				new_bufp->flags |= BUF_MOD;
348 			}
349 		}
350 	}
351 	if (last_bfp)
352 		__free_ovflpage(last_bfp);
353 	return (0);
354 }
355 
356 /*
357  * Add the given pair to the page
358  *
359  * Returns:
360  *	0 ==> OK
361  *	1 ==> failure
362  */
363 extern int
364 __addel(bufp, key, val)
365 	BUFHEAD *bufp;
366 	const DBT *key, *val;
367 {
368 	register u_short *bp, *sop;
369 	int do_expand;
370 
371 	bp = (u_short *)bufp->page;
372 	do_expand = 0;
373 	while (bp[0] && (bp[bp[0]] < REAL_KEY))
374 		/* Exception case */
375 		if (bp[2] < REAL_KEY) {
376 			/* This is a big-keydata pair */
377 			bufp = __add_ovflpage(bufp);
378 			if (!bufp)
379 				return (-1);
380 			bp = (u_short *)bufp->page;
381 		} else
382 			/* Try to squeeze key on this page */
383 			if (FREESPACE(bp) > PAIRSIZE(key, val)) {
384 				squeeze_key(bp, key, val);
385 				return (0);
386 			} else {
387 				bufp = __get_buf(bp[bp[0] - 1], bufp, 0);
388 				if (!bufp)
389 					return (-1);
390 				bp = (u_short *)bufp->page;
391 			}
392 
393 	if (PAIRFITS(bp, key, val))
394 		putpair(bufp->page, key, val);
395 	else {
396 		do_expand = 1;
397 		bufp = __add_ovflpage(bufp);
398 		if (!bufp)
399 			return (-1);
400 		sop = (u_short *)bufp->page;
401 
402 		if (PAIRFITS(sop, key, val))
403 			putpair((char *)sop, key, val);
404 		else
405 			if (__big_insert(bufp, key, val))
406 				return (-1);
407 	}
408 	bufp->flags |= BUF_MOD;
409 	/*
410 	 * If the average number of keys per bucket exceeds the fill factor,
411 	 * expand the table.
412 	 */
413 	hashp->NKEYS++;
414 	if (do_expand ||
415 	    (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
416 		return (__expand_table());
417 	return (0);
418 }
419 
420 /*
421  *
422  * Returns:
423  *	pointer on success
424  *	NULL on error
425  */
426 extern BUFHEAD *
427 __add_ovflpage(bufp)
428 	BUFHEAD *bufp;
429 {
430 	register u_short *sp;
431 	u_short ndx, ovfl_num;
432 #ifdef DEBUG1
433 	int tmp1, tmp2;
434 #endif
435 	sp = (u_short *)bufp->page;
436 	bufp->flags |= BUF_MOD;
437 	ovfl_num = overflow_page();
438 #ifdef DEBUG1
439 	tmp1 = bufp->addr;
440 	tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
441 #endif
442 	if (!ovfl_num || !(bufp->ovfl = __get_buf(ovfl_num, bufp, 1)))
443 		return (NULL);
444 	bufp->ovfl->flags |= BUF_MOD;
445 #ifdef DEBUG1
446 	(void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
447 	    tmp1, tmp2, bufp->ovfl->addr);
448 #endif
449 	ndx = sp[0];
450 	/*
451 	 * Since a pair is allocated on a page only if there's room to add
452 	 * an overflow page, we know that the OVFL information will fit on
453 	 * the page.
454 	 */
455 	sp[ndx + 4] = OFFSET(sp);
456 	sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
457 	sp[ndx + 1] = ovfl_num;
458 	sp[ndx + 2] = OVFLPAGE;
459 	sp[0] = ndx + 2;
460 #ifdef HASH_STATISTICS
461 	hash_overflows++;
462 #endif
463 	return (bufp->ovfl);
464 }
465 
466 /*
467  * Returns:
468  *	 0 indicates SUCCESS
469  *	-1 indicates FAILURE
470  */
471 extern int
472 __get_page(p, bucket, is_bucket, is_disk, is_bitmap)
473 	char *p;
474 	u_int bucket;
475 	int is_bucket, is_disk, is_bitmap;
476 {
477 	register int fd, page, size;
478 	int rsize;
479 	u_short *bp;
480 
481 	fd = hashp->fp;
482 	size = hashp->BSIZE;
483 
484 	if ((fd == -1) || !is_disk) {
485 		PAGE_INIT(p);
486 		return (0);
487 	}
488 	if (is_bucket)
489 		page = BUCKET_TO_PAGE(bucket);
490 	else
491 		page = OADDR_TO_PAGE(bucket);
492 	if ((lseek(fd, page << hashp->BSHIFT, SEEK_SET) == -1) ||
493 	    ((rsize = read(fd, p, size)) == -1))
494 		return (-1);
495 	bp = (u_short *)p;
496 	if (!rsize)
497 		bp[0] = 0;	/* We hit the EOF, so initialize a new page */
498 	else
499 		if (rsize != size) {
500 			errno = EFTYPE;
501 			return (-1);
502 		}
503 	if (!bp[0]) {
504 		PAGE_INIT(p);
505 	} else
506 		if (hashp->LORDER != BYTE_ORDER) {
507 			register int i, max;
508 
509 			if (is_bitmap) {
510 				max = hashp->BSIZE >> 2; /* divide by 4 */
511 				for (i = 0; i < max; i++)
512 					BLSWAP(((long *)p)[i]);
513 			} else {
514 				BSSWAP(bp[0]);
515 				max = bp[0] + 2;
516 				for (i = 1; i <= max; i++)
517 					BSSWAP(bp[i]);
518 			}
519 		}
520 	return (0);
521 }
522 
523 /*
524  * Write page p to disk
525  *
526  * Returns:
527  *	 0 ==> OK
528  *	-1 ==>failure
529  */
530 extern int
531 __put_page(p, bucket, is_bucket, is_bitmap)
532 	char *p;
533 	u_int bucket;
534 	int is_bucket, is_bitmap;
535 {
536 	register int fd, page, size;
537 	int wsize;
538 
539 	size = hashp->BSIZE;
540 	if ((hashp->fp == -1) && open_temp())
541 		return (1);
542 	fd = hashp->fp;
543 
544 	if (hashp->LORDER != BYTE_ORDER) {
545 		register int i;
546 		register int max;
547 
548 		if (is_bitmap) {
549 			max = hashp->BSIZE >> 2;	/* divide by 4 */
550 			for (i = 0; i < max; i++)
551 				BLSWAP(((long *)p)[i]);
552 		} else {
553 			max = ((u_short *)p)[0] + 2;
554 			for (i = 0; i <= max; i++)
555 				BSSWAP(((u_short *)p)[i]);
556 		}
557 	}
558 	if (is_bucket)
559 		page = BUCKET_TO_PAGE(bucket);
560 	else
561 		page = OADDR_TO_PAGE(bucket);
562 	if ((lseek(fd, page << hashp->BSHIFT, SEEK_SET) == -1) ||
563 	    ((wsize = write(fd, p, size)) == -1))
564 		/* Errno is set */
565 		return (-1);
566 	if (wsize != size) {
567 		errno = EFTYPE;
568 		return (-1);
569 	}
570 	return (0);
571 }
572 
573 #define BYTE_MASK	((1 << INT_BYTE_SHIFT) -1)
574 /*
575  * Initialize a new bitmap page.  Bitmap pages are left in memory
576  * once they are read in.
577  */
578 extern int
579 __init_bitmap(pnum, nbits, ndx)
580 	int pnum, nbits, ndx;
581 {
582 	u_long *ip;
583 	int clearbytes, clearints;
584 
585 	if (!(ip = malloc(hashp->BSIZE)))
586 		return (1);
587 	hashp->nmaps++;
588 	clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
589 	clearbytes = clearints << INT_TO_BYTE;
590 	(void)memset((char *)ip, 0, clearbytes);
591 	(void)memset(((char *)ip) + clearbytes, 0xFF,
592 	    hashp->BSIZE - clearbytes);
593 	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
594 	SETBIT(ip, 0);
595 	hashp->BITMAPS[ndx] = (u_short)pnum;
596 	hashp->mapp[ndx] = ip;
597 	return (0);
598 }
599 
600 static u_long
601 first_free(map)
602 	u_long map;
603 {
604 	register u_long i, mask;
605 
606 	mask = 0x1;
607 	for (i = 0; i < BITS_PER_MAP; i++) {
608 		if (!(mask & map))
609 			return (i);
610 		mask = mask << 1;
611 	}
612 	return (i);
613 }
614 
615 static  u_short
616 overflow_page()
617 {
618 	register u_long *freep;
619 	register int max_free, offset, splitnum;
620 	u_short addr;
621 	int bit, free_bit, free_page, i, in_use_bits, j;
622 #ifdef DEBUG2
623 	int tmp1, tmp2;
624 #endif
625 	splitnum = __log2(hashp->MAX_BUCKET);
626 	max_free = hashp->SPARES[splitnum];
627 
628 	free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
629 	free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
630 
631 	/* Look through all the free maps to find the first free block */
632 	for (i = 0; i <= free_page; i++) {
633 		if (!(freep = (u_long *)hashp->mapp[i]) &&
634 		    !(freep = fetch_bitmap(i)))
635 			return (NULL);
636 		if (i == free_page)
637 			in_use_bits = free_bit;
638 		else
639 			in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
640 
641 		for (j = 0, bit = 0; bit <= in_use_bits;
642 		    j++, bit += BITS_PER_MAP)
643 			if (freep[j] != ALL_SET)
644 				goto found;
645 	}
646 
647 	/* No Free Page Found */
648 	hashp->SPARES[splitnum]++;
649 	offset = hashp->SPARES[splitnum] -
650 	    (splitnum ? hashp->SPARES[splitnum - 1] : 0);
651 
652 	/* Check if we need to allocate a new bitmap page */
653 	if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
654 		free_page++;
655 #define	OVMSG	"hash: out of overflow pages; increase page size\n"
656 		if (free_page >= NCACHED) {
657 			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
658 			return (NULL);
659 		}
660 		/*
661 		 * This is tricky.  The 1 indicates that you want the new page
662 		 * allocated with 1 clear bit.  Actually, you are going to
663 		 * allocate 2 pages from this map.  The first is going to be
664 		 * the map page, the second is the overflow page we were
665 		 * looking for.  The init_bitmap routine automatically, sets
666 		 * the first bit of itself to indicate that the bitmap itself
667 		 * is in use.  We would explicitly set the second bit, but
668 		 * don't have to if we tell init_bitmap not to leave it clear
669 		 * in the first place.
670 		 */
671 		if (__init_bitmap((int)OADDR_OF(splitnum, offset),
672 		    1, free_page))
673 			return (NULL);
674 		hashp->SPARES[splitnum]++;
675 #ifdef DEBUG2
676 		free_bit = 2;
677 #endif
678 		offset++;
679 	} else {
680 		/*
681 		 * Free_bit addresses the last used bit.  Bump it to address
682 		 * the first available bit.
683 		 */
684 		free_bit++;
685 		SETBIT(freep, free_bit);
686 	}
687 
688 	/* Calculate address of the new overflow page */
689 	if (offset > SPLITMASK) {
690 		(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
691 		return (NULL);
692 	}
693 	addr = OADDR_OF(splitnum, offset);
694 #ifdef DEBUG2
695 	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
696 	    addr, free_bit, free_page);
697 #endif
698 	return (addr);
699 
700 found:
701 	bit = bit + first_free(freep[j]);
702 	SETBIT(freep, bit);
703 #ifdef DEBUG2
704 	tmp1 = bit;
705 	tmp2 = i;
706 #endif
707 	/*
708 	 * Bits are addressed starting with 0, but overflow pages are addressed
709 	 * beginning at 1. Bit is a bit addressnumber, so we need to increment
710 	 * it to convert it to a page number.
711 	 */
712 	bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
713 
714 	/* Calculate the split number for this page */
715 	for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
716 	offset = (i ? bit - hashp->SPARES[i - 1] : bit);
717 	if (offset >= SPLITMASK)
718 		return (NULL);	/* Out of overflow pages */
719 	addr = OADDR_OF(i, offset);
720 #ifdef DEBUG2
721 	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
722 	    addr, tmp1, tmp2);
723 #endif
724 
725 	/* Allocate and return the overflow page */
726 	return (addr);
727 }
728 
729 /*
730  * Mark this overflow page as free.
731  */
732 extern void
733 __free_ovflpage(obufp)
734 	BUFHEAD *obufp;
735 {
736 	register u_short addr;
737 	u_long *freep;
738 	int bit_address, free_page, free_bit;
739 	u_short ndx;
740 
741 	addr = obufp->addr;
742 #ifdef DEBUG1
743 	(void)fprintf(stderr, "Freeing %d\n", addr);
744 #endif
745 	ndx = (((u_short)addr) >> SPLITSHIFT);
746 	bit_address =
747 	    (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
748 	free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
749 	free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
750 
751 	if (!(freep = hashp->mapp[free_page]))
752 		freep = fetch_bitmap(free_page);
753 #ifdef DEBUG
754 	/*
755 	 * This had better never happen.  It means we tried to read a bitmap
756 	 * that has already had overflow pages allocated off it, and we
757 	 * failed to read it from the file.
758 	 */
759 	if (!freep)
760 		assert(0);
761 #endif
762 	CLRBIT(freep, free_bit);
763 #ifdef DEBUG2
764 	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
765 	    obufp->addr, free_bit, free_page);
766 #endif
767 	__reclaim_buf(obufp);
768 }
769 
770 /*
771  * Returns:
772  *	 0 success
773  *	-1 failure
774  */
775 static int
776 open_temp()
777 {
778 	sigset_t set, oset;
779 	static char namestr[] = "_hashXXXXXX";
780 
781 	/* Block signals; make sure file goes away at process exit. */
782 	sigfillset(&set);
783 	(void)sigprocmask(SIG_BLOCK, &set, &oset);
784 	if ((hashp->fp = mkstemp(namestr)) != -1) {
785 		(void)unlink(namestr);
786 		(void)fcntl(hashp->fp, F_SETFD, 1);
787 	}
788 	(void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
789 	return (hashp->fp != -1 ? 0 : -1);
790 }
791 
792 /*
793  * We have to know that the key will fit, but the last entry on the page is
794  * an overflow pair, so we need to shift things.
795  */
796 static void
797 squeeze_key(sp, key, val)
798 	u_short *sp;
799 	const DBT *key, *val;
800 {
801 	register char *p;
802 	u_short free_space, n, off, pageno;
803 
804 	p = (char *)sp;
805 	n = sp[0];
806 	free_space = FREESPACE(sp);
807 	off = OFFSET(sp);
808 
809 	pageno = sp[n - 1];
810 	off -= key->size;
811 	sp[n - 1] = off;
812 	bcopy(key->data, p + off, key->size);
813 	off -= val->size;
814 	sp[n] = off;
815 	bcopy(val->data, p + off, val->size);
816 	sp[0] = n + 2;
817 	sp[n + 1] = pageno;
818 	sp[n + 2] = OVFLPAGE;
819 	FREESPACE(sp) = free_space - PAIRSIZE(key, val);
820 	OFFSET(sp) = off;
821 }
822 
823 static u_long *
824 fetch_bitmap(ndx)
825 	int ndx;
826 {
827 	if (ndx >= hashp->nmaps ||
828 	    !(hashp->mapp[ndx] = malloc(hashp->BSIZE)) ||
829 	    __get_page((char *)hashp->mapp[ndx],
830 	    hashp->BITMAPS[ndx], 0, 1, 1))
831 		return (NULL);
832 	return (hashp->mapp[ndx]);
833 }
834 
835 #ifdef DEBUG4
836 int
837 print_chain(addr)
838 	int addr;
839 {
840 	BUFHEAD *bufp;
841 	short *bp, oaddr;
842 
843 	(void)fprintf(stderr, "%d ", addr);
844 	bufp = __get_buf(addr, NULL, 0);
845 	bp = (short *)bufp->page;
846 	while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
847 		((bp[0] > 2) && bp[2] < REAL_KEY))) {
848 		oaddr = bp[bp[0] - 1];
849 		(void)fprintf(stderr, "%d ", (int)oaddr);
850 		bufp = __get_buf((int)oaddr, bufp, 0);
851 		bp = (short *)bufp->page;
852 	}
853 	(void)fprintf(stderr, "\n");
854 }
855 #endif
856