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