Remove _THREAD_SAFE depenendancies. Create weakly associated stubs for
[dragonfly.git] / lib / libc / db / hash / hash.c
1 /*-
2  * Copyright (c) 1990, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Margo Seltzer.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * $FreeBSD: src/lib/libc/db/hash/hash.c,v 1.8 2000/01/27 23:06:08 jasone Exp $
37  * $DragonFly: src/lib/libc/db/hash/hash.c,v 1.5 2005/01/31 22:29:09 dillon Exp $
38  *
39  * @(#)hash.c   8.9 (Berkeley) 6/16/94
40  */
41
42 #include "namespace.h"
43 #include <sys/param.h>
44 #include <sys/stat.h>
45
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #ifdef DEBUG
53 #include <assert.h>
54 #endif
55 #include "un-namespace.h"
56
57 #include <db.h>
58 #include "hash.h"
59 #include "page.h"
60 #include "extern.h"
61
62 static int   alloc_segs (HTAB *, int);
63 static int   flush_meta (HTAB *);
64 static int   hash_access (HTAB *, ACTION, DBT *, DBT *);
65 static int   hash_close (DB *);
66 static int   hash_delete (const DB *, const DBT *, u_int32_t);
67 static int   hash_fd (const DB *);
68 static int   hash_get (const DB *, const DBT *, DBT *, u_int32_t);
69 static int   hash_put (const DB *, DBT *, const DBT *, u_int32_t);
70 static void *hash_realloc (SEGMENT **, int, int);
71 static int   hash_seq (const DB *, DBT *, DBT *, u_int32_t);
72 static int   hash_sync (const DB *, u_int32_t);
73 static int   hdestroy (HTAB *);
74 static HTAB *init_hash (HTAB *, const char *, HASHINFO *);
75 static int   init_htab (HTAB *, int);
76 #if BYTE_ORDER == LITTLE_ENDIAN
77 static void  swap_header (HTAB *);
78 static void  swap_header_copy (HASHHDR *, HASHHDR *);
79 #endif
80
81 /* Fast arithmetic, relying on powers of 2, */
82 #define MOD(x, y)               ((x) & ((y) - 1))
83
84 #define RETURN_ERROR(ERR, LOC)  { save_errno = ERR; goto LOC; }
85
86 /* Return values */
87 #define SUCCESS  (0)
88 #define ERROR   (-1)
89 #define ABNORMAL (1)
90
91 #ifdef HASH_STATISTICS
92 int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
93 #endif
94
95 /************************** INTERFACE ROUTINES ***************************/
96 /* OPEN/CLOSE */
97
98 extern DB *
99 __hash_open(file, flags, mode, info, dflags)
100         const char *file;
101         int flags, mode, dflags;
102         const HASHINFO *info;   /* Special directives for create */
103 {
104         HTAB *hashp;
105         struct stat statbuf;
106         DB *dbp;
107         int bpages, hdrsize, new_table, nsegs, save_errno;
108
109         if ((flags & O_ACCMODE) == O_WRONLY) {
110                 errno = EINVAL;
111                 return (NULL);
112         }
113
114         if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
115                 return (NULL);
116         hashp->fp = -1;
117
118         /*
119          * Even if user wants write only, we need to be able to read
120          * the actual file, so we need to open it read/write. But, the
121          * field in the hashp structure needs to be accurate so that
122          * we can check accesses.
123          */
124         hashp->flags = flags;
125
126         new_table = 0;
127         if (!file || (flags & O_TRUNC) ||
128             (stat(file, &statbuf) && (errno == ENOENT))) {
129                 if (errno == ENOENT)
130                         errno = 0; /* Just in case someone looks at errno */
131                 new_table = 1;
132         }
133         if (file) {
134                 if ((hashp->fp = _open(file, flags, mode)) == -1)
135                         RETURN_ERROR(errno, error0);
136
137                 /* if the .db file is empty, and we had permission to create
138                    a new .db file, then reinitialize the database */
139                 if ((flags & O_CREAT) &&
140                      _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
141                         new_table = 1;
142
143                 (void)_fcntl(hashp->fp, F_SETFD, 1);
144         }
145         if (new_table) {
146                 if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
147                         RETURN_ERROR(errno, error1);
148         } else {
149                 /* Table already exists */
150                 if (info && info->hash)
151                         hashp->hash = info->hash;
152                 else
153                         hashp->hash = __default_hash;
154
155                 hdrsize = _read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
156 #if BYTE_ORDER == LITTLE_ENDIAN
157                 swap_header(hashp);
158 #endif
159                 if (hdrsize == -1)
160                         RETURN_ERROR(errno, error1);
161                 if (hdrsize != sizeof(HASHHDR))
162                         RETURN_ERROR(EFTYPE, error1);
163                 /* Verify file type, versions and hash function */
164                 if (hashp->MAGIC != HASHMAGIC)
165                         RETURN_ERROR(EFTYPE, error1);
166 #define OLDHASHVERSION  1
167                 if (hashp->VERSION != HASHVERSION &&
168                     hashp->VERSION != OLDHASHVERSION)
169                         RETURN_ERROR(EFTYPE, error1);
170                 if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
171                         RETURN_ERROR(EFTYPE, error1);
172                 /*
173                  * Figure out how many segments we need.  Max_Bucket is the
174                  * maximum bucket number, so the number of buckets is
175                  * max_bucket + 1.
176                  */
177                 nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
178                          hashp->SGSIZE;
179                 hashp->nsegs = 0;
180                 if (alloc_segs(hashp, nsegs))
181                         /*
182                          * If alloc_segs fails, table will have been destroyed
183                          * and errno will have been set.
184                          */
185                         return (NULL);
186                 /* Read in bitmaps */
187                 bpages = (hashp->SPARES[hashp->OVFL_POINT] +
188                     (hashp->BSIZE << BYTE_SHIFT) - 1) >>
189                     (hashp->BSHIFT + BYTE_SHIFT);
190
191                 hashp->nmaps = bpages;
192                 (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
193         }
194
195         /* Initialize Buffer Manager */
196         if (info && info->cachesize)
197                 __buf_init(hashp, info->cachesize);
198         else
199                 __buf_init(hashp, DEF_BUFSIZE);
200
201         hashp->new_file = new_table;
202         hashp->save_file = file && (hashp->flags & O_RDWR);
203         hashp->cbucket = -1;
204         if (!(dbp = (DB *)malloc(sizeof(DB)))) {
205                 save_errno = errno;
206                 hdestroy(hashp);
207                 errno = save_errno;
208                 return (NULL);
209         }
210         dbp->internal = hashp;
211         dbp->close = hash_close;
212         dbp->del = hash_delete;
213         dbp->fd = hash_fd;
214         dbp->get = hash_get;
215         dbp->put = hash_put;
216         dbp->seq = hash_seq;
217         dbp->sync = hash_sync;
218         dbp->type = DB_HASH;
219
220 #ifdef DEBUG
221         (void)fprintf(stderr,
222 "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
223             "init_htab:",
224             "TABLE POINTER   ", hashp,
225             "BUCKET SIZE     ", hashp->BSIZE,
226             "BUCKET SHIFT    ", hashp->BSHIFT,
227             "DIRECTORY SIZE  ", hashp->DSIZE,
228             "SEGMENT SIZE    ", hashp->SGSIZE,
229             "SEGMENT SHIFT   ", hashp->SSHIFT,
230             "FILL FACTOR     ", hashp->FFACTOR,
231             "MAX BUCKET      ", hashp->MAX_BUCKET,
232             "OVFL POINT      ", hashp->OVFL_POINT,
233             "LAST FREED      ", hashp->LAST_FREED,
234             "HIGH MASK       ", hashp->HIGH_MASK,
235             "LOW  MASK       ", hashp->LOW_MASK,
236             "NSEGS           ", hashp->nsegs,
237             "NKEYS           ", hashp->NKEYS);
238 #endif
239 #ifdef HASH_STATISTICS
240         hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
241 #endif
242         return (dbp);
243
244 error1:
245         if (hashp != NULL)
246                 (void)_close(hashp->fp);
247
248 error0:
249         free(hashp);
250         errno = save_errno;
251         return (NULL);
252 }
253
254 static int
255 hash_close(dbp)
256         DB *dbp;
257 {
258         HTAB *hashp;
259         int retval;
260
261         if (!dbp)
262                 return (ERROR);
263
264         hashp = (HTAB *)dbp->internal;
265         retval = hdestroy(hashp);
266         free(dbp);
267         return (retval);
268 }
269
270 static int
271 hash_fd(dbp)
272         const DB *dbp;
273 {
274         HTAB *hashp;
275
276         if (!dbp)
277                 return (ERROR);
278
279         hashp = (HTAB *)dbp->internal;
280         if (hashp->fp == -1) {
281                 errno = ENOENT;
282                 return (-1);
283         }
284         return (hashp->fp);
285 }
286
287 /************************** LOCAL CREATION ROUTINES **********************/
288 static HTAB *
289 init_hash(hashp, file, info)
290         HTAB *hashp;
291         const char *file;
292         HASHINFO *info;
293 {
294         struct stat statbuf;
295         int nelem;
296
297         nelem = 1;
298         hashp->NKEYS = 0;
299         hashp->LORDER = BYTE_ORDER;
300         hashp->BSIZE = DEF_BUCKET_SIZE;
301         hashp->BSHIFT = DEF_BUCKET_SHIFT;
302         hashp->SGSIZE = DEF_SEGSIZE;
303         hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
304         hashp->DSIZE = DEF_DIRSIZE;
305         hashp->FFACTOR = DEF_FFACTOR;
306         hashp->hash = __default_hash;
307         memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
308         memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
309
310         /* Fix bucket size to be optimal for file system */
311         if (file != NULL) {
312                 if (stat(file, &statbuf))
313                         return (NULL);
314                 hashp->BSIZE = statbuf.st_blksize;
315                 hashp->BSHIFT = __log2(hashp->BSIZE);
316         }
317
318         if (info) {
319                 if (info->bsize) {
320                         /* Round pagesize up to power of 2 */
321                         hashp->BSHIFT = __log2(info->bsize);
322                         hashp->BSIZE = 1 << hashp->BSHIFT;
323                         if (hashp->BSIZE > MAX_BSIZE) {
324                                 errno = EINVAL;
325                                 return (NULL);
326                         }
327                 }
328                 if (info->ffactor)
329                         hashp->FFACTOR = info->ffactor;
330                 if (info->hash)
331                         hashp->hash = info->hash;
332                 if (info->nelem)
333                         nelem = info->nelem;
334                 if (info->lorder) {
335                         if (info->lorder != BIG_ENDIAN &&
336                             info->lorder != LITTLE_ENDIAN) {
337                                 errno = EINVAL;
338                                 return (NULL);
339                         }
340                         hashp->LORDER = info->lorder;
341                 }
342         }
343         /* init_htab should destroy the table and set errno if it fails */
344         if (init_htab(hashp, nelem))
345                 return (NULL);
346         else
347                 return (hashp);
348 }
349 /*
350  * This calls alloc_segs which may run out of memory.  Alloc_segs will destroy
351  * the table and set errno, so we just pass the error information along.
352  *
353  * Returns 0 on No Error
354  */
355 static int
356 init_htab(hashp, nelem)
357         HTAB *hashp;
358         int nelem;
359 {
360         int nbuckets, nsegs;
361         int l2;
362
363         /*
364          * Divide number of elements by the fill factor and determine a
365          * desired number of buckets.  Allocate space for the next greater
366          * power of two number of buckets.
367          */
368         nelem = (nelem - 1) / hashp->FFACTOR + 1;
369
370         l2 = __log2(MAX(nelem, 2));
371         nbuckets = 1 << l2;
372
373         hashp->SPARES[l2] = l2 + 1;
374         hashp->SPARES[l2 + 1] = l2 + 1;
375         hashp->OVFL_POINT = l2;
376         hashp->LAST_FREED = 2;
377
378         /* First bitmap page is at: splitpoint l2 page offset 1 */
379         if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
380                 return (-1);
381
382         hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
383         hashp->HIGH_MASK = (nbuckets << 1) - 1;
384         hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
385             hashp->BSHIFT) + 1;
386
387         nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
388         nsegs = 1 << __log2(nsegs);
389
390         if (nsegs > hashp->DSIZE)
391                 hashp->DSIZE = nsegs;
392         return (alloc_segs(hashp, nsegs));
393 }
394
395 /********************** DESTROY/CLOSE ROUTINES ************************/
396
397 /*
398  * Flushes any changes to the file if necessary and destroys the hashp
399  * structure, freeing all allocated space.
400  */
401 static int
402 hdestroy(hashp)
403         HTAB *hashp;
404 {
405         int i, save_errno;
406
407         save_errno = 0;
408
409 #ifdef HASH_STATISTICS
410         (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
411             hash_accesses, hash_collisions);
412         (void)fprintf(stderr, "hdestroy: expansions %ld\n",
413             hash_expansions);
414         (void)fprintf(stderr, "hdestroy: overflows %ld\n",
415             hash_overflows);
416         (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
417             hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
418
419         for (i = 0; i < NCACHED; i++)
420                 (void)fprintf(stderr,
421                     "spares[%d] = %d\n", i, hashp->SPARES[i]);
422 #endif
423         /*
424          * Call on buffer manager to free buffers, and if required,
425          * write them to disk.
426          */
427         if (__buf_free(hashp, 1, hashp->save_file))
428                 save_errno = errno;
429         if (hashp->dir) {
430                 free(*hashp->dir);      /* Free initial segments */
431                 /* Free extra segments */
432                 while (hashp->exsegs--)
433                         free(hashp->dir[--hashp->nsegs]);
434                 free(hashp->dir);
435         }
436         if (flush_meta(hashp) && !save_errno)
437                 save_errno = errno;
438         /* Free Bigmaps */
439         for (i = 0; i < hashp->nmaps; i++)
440                 if (hashp->mapp[i])
441                         free(hashp->mapp[i]);
442
443         if (hashp->fp != -1)
444                 (void)_close(hashp->fp);
445
446         free(hashp);
447
448         if (save_errno) {
449                 errno = save_errno;
450                 return (ERROR);
451         }
452         return (SUCCESS);
453 }
454 /*
455  * Write modified pages to disk
456  *
457  * Returns:
458  *       0 == OK
459  *      -1 ERROR
460  */
461 static int
462 hash_sync(dbp, flags)
463         const DB *dbp;
464         u_int32_t flags;
465 {
466         HTAB *hashp;
467
468         if (flags != 0) {
469                 errno = EINVAL;
470                 return (ERROR);
471         }
472
473         if (!dbp)
474                 return (ERROR);
475
476         hashp = (HTAB *)dbp->internal;
477         if (!hashp->save_file)
478                 return (0);
479         if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
480                 return (ERROR);
481         hashp->new_file = 0;
482         return (0);
483 }
484
485 /*
486  * Returns:
487  *       0 == OK
488  *      -1 indicates that errno should be set
489  */
490 static int
491 flush_meta(hashp)
492         HTAB *hashp;
493 {
494         HASHHDR *whdrp;
495 #if BYTE_ORDER == LITTLE_ENDIAN
496         HASHHDR whdr;
497 #endif
498         int fp, i, wsize;
499
500         if (!hashp->save_file)
501                 return (0);
502         hashp->MAGIC = HASHMAGIC;
503         hashp->VERSION = HASHVERSION;
504         hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
505
506         fp = hashp->fp;
507         whdrp = &hashp->hdr;
508 #if BYTE_ORDER == LITTLE_ENDIAN
509         whdrp = &whdr;
510         swap_header_copy(&hashp->hdr, whdrp);
511 #endif
512         if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
513             ((wsize = _write(fp, whdrp, sizeof(HASHHDR))) == -1))
514                 return (-1);
515         else
516                 if (wsize != sizeof(HASHHDR)) {
517                         errno = EFTYPE;
518                         hashp->error = errno;
519                         return (-1);
520                 }
521         for (i = 0; i < NCACHED; i++)
522                 if (hashp->mapp[i])
523                         if (__put_page(hashp, (char *)hashp->mapp[i],
524                                 hashp->BITMAPS[i], 0, 1))
525                                 return (-1);
526         return (0);
527 }
528
529 /*******************************SEARCH ROUTINES *****************************/
530 /*
531  * All the access routines return
532  *
533  * Returns:
534  *       0 on SUCCESS
535  *       1 to indicate an external ERROR (i.e. key not found, etc)
536  *      -1 to indicate an internal ERROR (i.e. out of memory, etc)
537  */
538 static int
539 hash_get(dbp, key, data, flag)
540         const DB *dbp;
541         const DBT *key;
542         DBT *data;
543         u_int32_t flag;
544 {
545         HTAB *hashp;
546
547         hashp = (HTAB *)dbp->internal;
548         if (flag) {
549                 hashp->error = EINVAL;
550                 errno = EINVAL;
551                 return (ERROR);
552         }
553         return (hash_access(hashp, HASH_GET, (DBT *)key, data));
554 }
555
556 static int
557 hash_put(dbp, key, data, flag)
558         const DB *dbp;
559         DBT *key;
560         const DBT *data;
561         u_int32_t flag;
562 {
563         HTAB *hashp;
564
565         hashp = (HTAB *)dbp->internal;
566         if (flag && flag != R_NOOVERWRITE) {
567                 hashp->error = errno = EINVAL;
568                 return (ERROR);
569         }
570         if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
571                 hashp->error = errno = EPERM;
572                 return (ERROR);
573         }
574         return (hash_access(hashp, flag == R_NOOVERWRITE ?
575             HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
576 }
577
578 static int
579 hash_delete(dbp, key, flag)
580         const DB *dbp;
581         const DBT *key;
582         u_int32_t flag;         /* Ignored */
583 {
584         HTAB *hashp;
585
586         hashp = (HTAB *)dbp->internal;
587         if (flag && flag != R_CURSOR) {
588                 hashp->error = errno = EINVAL;
589                 return (ERROR);
590         }
591         if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
592                 hashp->error = errno = EPERM;
593                 return (ERROR);
594         }
595         return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
596 }
597
598 /*
599  * Assume that hashp has been set in wrapper routine.
600  */
601 static int
602 hash_access(hashp, action, key, val)
603         HTAB *hashp;
604         ACTION action;
605         DBT *key, *val;
606 {
607         BUFHEAD *rbufp;
608         BUFHEAD *bufp, *save_bufp;
609         u_int16_t *bp;
610         int n, ndx, off, size;
611         char *kp;
612         u_int16_t pageno;
613
614 #ifdef HASH_STATISTICS
615         hash_accesses++;
616 #endif
617
618         off = hashp->BSIZE;
619         size = key->size;
620         kp = (char *)key->data;
621         rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
622         if (!rbufp)
623                 return (ERROR);
624         save_bufp = rbufp;
625
626         /* Pin the bucket chain */
627         rbufp->flags |= BUF_PIN;
628         for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
629                 if (bp[1] >= REAL_KEY) {
630                         /* Real key/data pair */
631                         if (size == off - *bp &&
632                             memcmp(kp, rbufp->page + *bp, size) == 0)
633                                 goto found;
634                         off = bp[1];
635 #ifdef HASH_STATISTICS
636                         hash_collisions++;
637 #endif
638                         bp += 2;
639                         ndx += 2;
640                 } else if (bp[1] == OVFLPAGE) {
641                         rbufp = __get_buf(hashp, *bp, rbufp, 0);
642                         if (!rbufp) {
643                                 save_bufp->flags &= ~BUF_PIN;
644                                 return (ERROR);
645                         }
646                         /* FOR LOOP INIT */
647                         bp = (u_int16_t *)rbufp->page;
648                         n = *bp++;
649                         ndx = 1;
650                         off = hashp->BSIZE;
651                 } else if (bp[1] < REAL_KEY) {
652                         if ((ndx =
653                             __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
654                                 goto found;
655                         if (ndx == -2) {
656                                 bufp = rbufp;
657                                 if (!(pageno =
658                                     __find_last_page(hashp, &bufp))) {
659                                         ndx = 0;
660                                         rbufp = bufp;
661                                         break;  /* FOR */
662                                 }
663                                 rbufp = __get_buf(hashp, pageno, bufp, 0);
664                                 if (!rbufp) {
665                                         save_bufp->flags &= ~BUF_PIN;
666                                         return (ERROR);
667                                 }
668                                 /* FOR LOOP INIT */
669                                 bp = (u_int16_t *)rbufp->page;
670                                 n = *bp++;
671                                 ndx = 1;
672                                 off = hashp->BSIZE;
673                         } else {
674                                 save_bufp->flags &= ~BUF_PIN;
675                                 return (ERROR);
676                         }
677                 }
678
679         /* Not found */
680         switch (action) {
681         case HASH_PUT:
682         case HASH_PUTNEW:
683                 if (__addel(hashp, rbufp, key, val)) {
684                         save_bufp->flags &= ~BUF_PIN;
685                         return (ERROR);
686                 } else {
687                         save_bufp->flags &= ~BUF_PIN;
688                         return (SUCCESS);
689                 }
690         case HASH_GET:
691         case HASH_DELETE:
692         default:
693                 save_bufp->flags &= ~BUF_PIN;
694                 return (ABNORMAL);
695         }
696
697 found:
698         switch (action) {
699         case HASH_PUTNEW:
700                 save_bufp->flags &= ~BUF_PIN;
701                 return (ABNORMAL);
702         case HASH_GET:
703                 bp = (u_int16_t *)rbufp->page;
704                 if (bp[ndx + 1] < REAL_KEY) {
705                         if (__big_return(hashp, rbufp, ndx, val, 0))
706                                 return (ERROR);
707                 } else {
708                         val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
709                         val->size = bp[ndx] - bp[ndx + 1];
710                 }
711                 break;
712         case HASH_PUT:
713                 if ((__delpair(hashp, rbufp, ndx)) ||
714                     (__addel(hashp, rbufp, key, val))) {
715                         save_bufp->flags &= ~BUF_PIN;
716                         return (ERROR);
717                 }
718                 break;
719         case HASH_DELETE:
720                 if (__delpair(hashp, rbufp, ndx))
721                         return (ERROR);
722                 break;
723         default:
724                 abort();
725         }
726         save_bufp->flags &= ~BUF_PIN;
727         return (SUCCESS);
728 }
729
730 static int
731 hash_seq(dbp, key, data, flag)
732         const DB *dbp;
733         DBT *key, *data;
734         u_int32_t flag;
735 {
736         u_int32_t bucket;
737         BUFHEAD *bufp;
738         HTAB *hashp;
739         u_int16_t *bp, ndx;
740
741         hashp = (HTAB *)dbp->internal;
742         if (flag && flag != R_FIRST && flag != R_NEXT) {
743                 hashp->error = errno = EINVAL;
744                 return (ERROR);
745         }
746 #ifdef HASH_STATISTICS
747         hash_accesses++;
748 #endif
749         if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
750                 hashp->cbucket = 0;
751                 hashp->cndx = 1;
752                 hashp->cpage = NULL;
753         }
754
755         for (bp = NULL; !bp || !bp[0]; ) {
756                 if (!(bufp = hashp->cpage)) {
757                         for (bucket = hashp->cbucket;
758                             bucket <= hashp->MAX_BUCKET;
759                             bucket++, hashp->cndx = 1) {
760                                 bufp = __get_buf(hashp, bucket, NULL, 0);
761                                 if (!bufp)
762                                         return (ERROR);
763                                 hashp->cpage = bufp;
764                                 bp = (u_int16_t *)bufp->page;
765                                 if (bp[0])
766                                         break;
767                         }
768                         hashp->cbucket = bucket;
769                         if (hashp->cbucket > hashp->MAX_BUCKET) {
770                                 hashp->cbucket = -1;
771                                 return (ABNORMAL);
772                         }
773                 } else
774                         bp = (u_int16_t *)hashp->cpage->page;
775
776 #ifdef DEBUG
777                 assert(bp);
778                 assert(bufp);
779 #endif
780                 while (bp[hashp->cndx + 1] == OVFLPAGE) {
781                         bufp = hashp->cpage =
782                             __get_buf(hashp, bp[hashp->cndx], bufp, 0);
783                         if (!bufp)
784                                 return (ERROR);
785                         bp = (u_int16_t *)(bufp->page);
786                         hashp->cndx = 1;
787                 }
788                 if (!bp[0]) {
789                         hashp->cpage = NULL;
790                         ++hashp->cbucket;
791                 }
792         }
793         ndx = hashp->cndx;
794         if (bp[ndx + 1] < REAL_KEY) {
795                 if (__big_keydata(hashp, bufp, key, data, 1))
796                         return (ERROR);
797         } else {
798                 key->data = (u_char *)hashp->cpage->page + bp[ndx];
799                 key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
800                 data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
801                 data->size = bp[ndx] - bp[ndx + 1];
802                 ndx += 2;
803                 if (ndx > bp[0]) {
804                         hashp->cpage = NULL;
805                         hashp->cbucket++;
806                         hashp->cndx = 1;
807                 } else
808                         hashp->cndx = ndx;
809         }
810         return (SUCCESS);
811 }
812
813 /********************************* UTILITIES ************************/
814
815 /*
816  * Returns:
817  *       0 ==> OK
818  *      -1 ==> Error
819  */
820 extern int
821 __expand_table(hashp)
822         HTAB *hashp;
823 {
824         u_int32_t old_bucket, new_bucket;
825         int dirsize, new_segnum, spare_ndx;
826
827 #ifdef HASH_STATISTICS
828         hash_expansions++;
829 #endif
830         new_bucket = ++hashp->MAX_BUCKET;
831         old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
832
833         new_segnum = new_bucket >> hashp->SSHIFT;
834
835         /* Check if we need a new segment */
836         if (new_segnum >= hashp->nsegs) {
837                 /* Check if we need to expand directory */
838                 if (new_segnum >= hashp->DSIZE) {
839                         /* Reallocate directory */
840                         dirsize = hashp->DSIZE * sizeof(SEGMENT *);
841                         if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
842                                 return (-1);
843                         hashp->DSIZE = dirsize << 1;
844                 }
845                 if ((hashp->dir[new_segnum] =
846                     (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
847                         return (-1);
848                 hashp->exsegs++;
849                 hashp->nsegs++;
850         }
851         /*
852          * If the split point is increasing (MAX_BUCKET's log base 2
853          * * increases), we need to copy the current contents of the spare
854          * split bucket to the next bucket.
855          */
856         spare_ndx = __log2(hashp->MAX_BUCKET + 1);
857         if (spare_ndx > hashp->OVFL_POINT) {
858                 hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
859                 hashp->OVFL_POINT = spare_ndx;
860         }
861
862         if (new_bucket > hashp->HIGH_MASK) {
863                 /* Starting a new doubling */
864                 hashp->LOW_MASK = hashp->HIGH_MASK;
865                 hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
866         }
867         /* Relocate records to the new bucket */
868         return (__split_page(hashp, old_bucket, new_bucket));
869 }
870
871 /*
872  * If realloc guarantees that the pointer is not destroyed if the realloc
873  * fails, then this routine can go away.
874  */
875 static void *
876 hash_realloc(p_ptr, oldsize, newsize)
877         SEGMENT **p_ptr;
878         int oldsize, newsize;
879 {
880         void *p;
881
882         if ( (p = malloc(newsize)) ) {
883                 memmove(p, *p_ptr, oldsize);
884                 memset((char *)p + oldsize, 0, newsize - oldsize);
885                 free(*p_ptr);
886                 *p_ptr = p;
887         }
888         return (p);
889 }
890
891 extern u_int32_t
892 __call_hash(hashp, k, len)
893         HTAB *hashp;
894         char *k;
895         int len;
896 {
897         int n, bucket;
898
899         n = hashp->hash(k, len);
900         bucket = n & hashp->HIGH_MASK;
901         if (bucket > hashp->MAX_BUCKET)
902                 bucket = bucket & hashp->LOW_MASK;
903         return (bucket);
904 }
905
906 /*
907  * Allocate segment table.  On error, destroy the table and set errno.
908  *
909  * Returns 0 on success
910  */
911 static int
912 alloc_segs(hashp, nsegs)
913         HTAB *hashp;
914         int nsegs;
915 {
916         int i;
917         SEGMENT store;
918
919         int save_errno;
920
921         if ((hashp->dir =
922             (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
923                 save_errno = errno;
924                 (void)hdestroy(hashp);
925                 errno = save_errno;
926                 return (-1);
927         }
928         /* Allocate segments */
929         if ((store =
930             (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
931                 save_errno = errno;
932                 (void)hdestroy(hashp);
933                 errno = save_errno;
934                 return (-1);
935         }
936         for (i = 0; i < nsegs; i++, hashp->nsegs++)
937                 hashp->dir[i] = &store[i << hashp->SSHIFT];
938         return (0);
939 }
940
941 #if BYTE_ORDER == LITTLE_ENDIAN
942 /*
943  * Hashp->hdr needs to be byteswapped.
944  */
945 static void
946 swap_header_copy(srcp, destp)
947         HASHHDR *srcp, *destp;
948 {
949         int i;
950
951         P_32_COPY(srcp->magic, destp->magic);
952         P_32_COPY(srcp->version, destp->version);
953         P_32_COPY(srcp->lorder, destp->lorder);
954         P_32_COPY(srcp->bsize, destp->bsize);
955         P_32_COPY(srcp->bshift, destp->bshift);
956         P_32_COPY(srcp->dsize, destp->dsize);
957         P_32_COPY(srcp->ssize, destp->ssize);
958         P_32_COPY(srcp->sshift, destp->sshift);
959         P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
960         P_32_COPY(srcp->last_freed, destp->last_freed);
961         P_32_COPY(srcp->max_bucket, destp->max_bucket);
962         P_32_COPY(srcp->high_mask, destp->high_mask);
963         P_32_COPY(srcp->low_mask, destp->low_mask);
964         P_32_COPY(srcp->ffactor, destp->ffactor);
965         P_32_COPY(srcp->nkeys, destp->nkeys);
966         P_32_COPY(srcp->hdrpages, destp->hdrpages);
967         P_32_COPY(srcp->h_charkey, destp->h_charkey);
968         for (i = 0; i < NCACHED; i++) {
969                 P_32_COPY(srcp->spares[i], destp->spares[i]);
970                 P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
971         }
972 }
973
974 static void
975 swap_header(hashp)
976         HTAB *hashp;
977 {
978         HASHHDR *hdrp;
979         int i;
980
981         hdrp = &hashp->hdr;
982
983         M_32_SWAP(hdrp->magic);
984         M_32_SWAP(hdrp->version);
985         M_32_SWAP(hdrp->lorder);
986         M_32_SWAP(hdrp->bsize);
987         M_32_SWAP(hdrp->bshift);
988         M_32_SWAP(hdrp->dsize);
989         M_32_SWAP(hdrp->ssize);
990         M_32_SWAP(hdrp->sshift);
991         M_32_SWAP(hdrp->ovfl_point);
992         M_32_SWAP(hdrp->last_freed);
993         M_32_SWAP(hdrp->max_bucket);
994         M_32_SWAP(hdrp->high_mask);
995         M_32_SWAP(hdrp->low_mask);
996         M_32_SWAP(hdrp->ffactor);
997         M_32_SWAP(hdrp->nkeys);
998         M_32_SWAP(hdrp->hdrpages);
999         M_32_SWAP(hdrp->h_charkey);
1000         for (i = 0; i < NCACHED; i++) {
1001                 M_32_SWAP(hdrp->spares[i]);
1002                 M_16_SWAP(hdrp->bitmaps[i]);
1003         }
1004 }
1005 #endif