OSDN Git Service

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