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