security/nss/lib/dbm/include/hash.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*-
michael@0 2 * Copyright (c) 1990, 1993, 1994
michael@0 3 * The Regents of the University of California. All rights reserved.
michael@0 4 *
michael@0 5 * This code is derived from software contributed to Berkeley by
michael@0 6 * Margo Seltzer.
michael@0 7 *
michael@0 8 * Redistribution and use in source and binary forms, with or without
michael@0 9 * modification, are permitted provided that the following conditions
michael@0 10 * are met:
michael@0 11 * 1. Redistributions of source code must retain the above copyright
michael@0 12 * notice, this list of conditions and the following disclaimer.
michael@0 13 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 14 * notice, this list of conditions and the following disclaimer in the
michael@0 15 * documentation and/or other materials provided with the distribution.
michael@0 16 * 3. ***REMOVED*** - see
michael@0 17 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
michael@0 18 * 4. Neither the name of the University nor the names of its contributors
michael@0 19 * may be used to endorse or promote products derived from this software
michael@0 20 * without specific prior written permission.
michael@0 21 *
michael@0 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
michael@0 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
michael@0 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
michael@0 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
michael@0 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
michael@0 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
michael@0 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
michael@0 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@0 32 * SUCH DAMAGE.
michael@0 33 *
michael@0 34 * @(#)hash.h 8.3 (Berkeley) 5/31/94
michael@0 35 */
michael@0 36
michael@0 37 /* Operations */
michael@0 38
michael@0 39 #include <stdio.h>
michael@0 40 #include "mcom_db.h"
michael@0 41 typedef enum {
michael@0 42 HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
michael@0 43 } ACTION;
michael@0 44
michael@0 45 /* Buffer Management structures */
michael@0 46 typedef struct _bufhead BUFHEAD;
michael@0 47
michael@0 48 struct _bufhead {
michael@0 49 BUFHEAD *prev; /* LRU links */
michael@0 50 BUFHEAD *next; /* LRU links */
michael@0 51 BUFHEAD *ovfl; /* Overflow page buffer header */
michael@0 52 uint32 addr; /* Address of this page */
michael@0 53 char *page; /* Actual page data */
michael@0 54 char is_disk;
michael@0 55 char flags;
michael@0 56 #define BUF_MOD 0x0001
michael@0 57 #define BUF_DISK 0x0002
michael@0 58 #define BUF_BUCKET 0x0004
michael@0 59 #define BUF_PIN 0x0008
michael@0 60 };
michael@0 61
michael@0 62 #define IS_BUCKET(X) ((X) & BUF_BUCKET)
michael@0 63
michael@0 64 typedef BUFHEAD **SEGMENT;
michael@0 65
michael@0 66 typedef int DBFILE_PTR;
michael@0 67 #define NO_FILE -1
michael@0 68 #ifdef macintosh
michael@0 69 #define DBFILE_OPEN(path, flag,mode) open((path), flag)
michael@0 70 #define EXISTS(path)
michael@0 71 #else
michael@0 72 #define DBFILE_OPEN(path, flag,mode) open((path), (flag), (mode))
michael@0 73 #endif
michael@0 74 /* Hash Table Information */
michael@0 75 typedef struct hashhdr { /* Disk resident portion */
michael@0 76 int32 magic; /* Magic NO for hash tables */
michael@0 77 int32 version; /* Version ID */
michael@0 78 uint32 lorder; /* Byte Order */
michael@0 79 int32 bsize; /* Bucket/Page Size */
michael@0 80 int32 bshift; /* Bucket shift */
michael@0 81 int32 dsize; /* Directory Size */
michael@0 82 int32 ssize; /* Segment Size */
michael@0 83 int32 sshift; /* Segment shift */
michael@0 84 int32 ovfl_point; /* Where overflow pages are being
michael@0 85 * allocated */
michael@0 86 int32 last_freed; /* Last overflow page freed */
michael@0 87 int32 max_bucket; /* ID of Maximum bucket in use */
michael@0 88 int32 high_mask; /* Mask to modulo into entire table */
michael@0 89 int32 low_mask; /* Mask to modulo into lower half of
michael@0 90 * table */
michael@0 91 int32 ffactor; /* Fill factor */
michael@0 92 int32 nkeys; /* Number of keys in hash table */
michael@0 93 int32 hdrpages; /* Size of table header */
michael@0 94 uint32 h_charkey; /* value of hash(CHARKEY) */
michael@0 95 #define NCACHED 32 /* number of bit maps and spare
michael@0 96 * points */
michael@0 97 int32 spares[NCACHED];/* spare pages for overflow */
michael@0 98 uint16 bitmaps[NCACHED]; /* address of overflow page
michael@0 99 * bitmaps */
michael@0 100 } HASHHDR;
michael@0 101
michael@0 102 typedef struct htab { /* Memory resident data structure */
michael@0 103 HASHHDR hdr; /* Header */
michael@0 104 int nsegs; /* Number of allocated segments */
michael@0 105 int exsegs; /* Number of extra allocated
michael@0 106 * segments */
michael@0 107 uint32 /* Hash function */
michael@0 108 (*hash)(const void *, size_t);
michael@0 109 int flags; /* Flag values */
michael@0 110 DBFILE_PTR fp; /* File pointer */
michael@0 111 char *filename;
michael@0 112 char *tmp_buf; /* Temporary Buffer for BIG data */
michael@0 113 char *tmp_key; /* Temporary Buffer for BIG keys */
michael@0 114 BUFHEAD *cpage; /* Current page */
michael@0 115 int cbucket; /* Current bucket */
michael@0 116 int cndx; /* Index of next item on cpage */
michael@0 117 int dbmerrno; /* Error Number -- for DBM
michael@0 118 * compatability */
michael@0 119 int new_file; /* Indicates if fd is backing store
michael@0 120 * or no */
michael@0 121 int save_file; /* Indicates whether we need to flush
michael@0 122 * file at
michael@0 123 * exit */
michael@0 124 uint32 *mapp[NCACHED]; /* Pointers to page maps */
michael@0 125 int nmaps; /* Initial number of bitmaps */
michael@0 126 int nbufs; /* Number of buffers left to
michael@0 127 * allocate */
michael@0 128 BUFHEAD bufhead; /* Header of buffer lru list */
michael@0 129 SEGMENT *dir; /* Hash Bucket directory */
michael@0 130 off_t file_size; /* in bytes */
michael@0 131 char is_temp; /* unlink file on close */
michael@0 132 char updateEOF; /* force EOF update on flush */
michael@0 133 } HTAB;
michael@0 134
michael@0 135 /*
michael@0 136 * Constants
michael@0 137 */
michael@0 138 #define DATABASE_CORRUPTED_ERROR -999 /* big ugly abort, delete database */
michael@0 139 #define OLD_MAX_BSIZE 65536 /* 2^16 */
michael@0 140 #define MAX_BSIZE 32l*1024l /* 2^15 */
michael@0 141 #define MIN_BUFFERS 6
michael@0 142 #define MINHDRSIZE 512
michael@0 143 #define DEF_BUFSIZE 65536l /* 64 K */
michael@0 144 #define DEF_BUCKET_SIZE 4096
michael@0 145 #define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */
michael@0 146 #define DEF_SEGSIZE 256
michael@0 147 #define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
michael@0 148 #define DEF_DIRSIZE 256
michael@0 149 #define DEF_FFACTOR 65536l
michael@0 150 #define MIN_FFACTOR 4
michael@0 151 #define SPLTMAX 8
michael@0 152 #define CHARKEY "%$sniglet^&"
michael@0 153 #define NUMKEY 1038583l
michael@0 154 #define BYTE_SHIFT 3
michael@0 155 #define INT_TO_BYTE 2
michael@0 156 #define INT_BYTE_SHIFT 5
michael@0 157 #define ALL_SET ((uint32)0xFFFFFFFF)
michael@0 158 #define ALL_CLEAR 0
michael@0 159
michael@0 160 #define PTROF(X) ((ptrdiff_t)(X) == BUF_DISK ? 0 : (X))
michael@0 161 #define ISDISK(X) ((X) ? ((ptrdiff_t)(X) == BUF_DISK ? BUF_DISK \
michael@0 162 : (X)->is_disk) : 0)
michael@0 163
michael@0 164 #define BITS_PER_MAP 32
michael@0 165
michael@0 166 /* Given the address of the beginning of a big map, clear/set the nth bit */
michael@0 167 #define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
michael@0 168 #define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
michael@0 169 #define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
michael@0 170
michael@0 171 /* Overflow management */
michael@0 172 /*
michael@0 173 * Overflow page numbers are allocated per split point. At each doubling of
michael@0 174 * the table, we can allocate extra pages. So, an overflow page number has
michael@0 175 * the top 5 bits indicate which split point and the lower 11 bits indicate
michael@0 176 * which page at that split point is indicated (pages within split points are
michael@0 177 * numberered starting with 1).
michael@0 178 */
michael@0 179
michael@0 180 #define SPLITSHIFT 11
michael@0 181 #define SPLITMASK 0x7FF
michael@0 182 #define SPLITNUM(N) (((uint32)(N)) >> SPLITSHIFT)
michael@0 183 #define OPAGENUM(N) ((N) & SPLITMASK)
michael@0 184 #define OADDR_OF(S,O) ((uint32)((uint32)(S) << SPLITSHIFT) + (O))
michael@0 185
michael@0 186 #define BUCKET_TO_PAGE(B) \
michael@0 187 (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((uint32)((B)+1))-1] : 0)
michael@0 188 #define OADDR_TO_PAGE(B) \
michael@0 189 BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
michael@0 190
michael@0 191 /*
michael@0 192 * page.h contains a detailed description of the page format.
michael@0 193 *
michael@0 194 * Normally, keys and data are accessed from offset tables in the top of
michael@0 195 * each page which point to the beginning of the key and data. There are
michael@0 196 * four flag values which may be stored in these offset tables which indicate
michael@0 197 * the following:
michael@0 198 *
michael@0 199 *
michael@0 200 * OVFLPAGE Rather than a key data pair, this pair contains
michael@0 201 * the address of an overflow page. The format of
michael@0 202 * the pair is:
michael@0 203 * OVERFLOW_PAGE_NUMBER OVFLPAGE
michael@0 204 *
michael@0 205 * PARTIAL_KEY This must be the first key/data pair on a page
michael@0 206 * and implies that page contains only a partial key.
michael@0 207 * That is, the key is too big to fit on a single page
michael@0 208 * so it starts on this page and continues on the next.
michael@0 209 * The format of the page is:
michael@0 210 * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
michael@0 211 *
michael@0 212 * KEY_OFF -- offset of the beginning of the key
michael@0 213 * PARTIAL_KEY -- 1
michael@0 214 * OVFL_PAGENO - page number of the next overflow page
michael@0 215 * OVFLPAGE -- 0
michael@0 216 *
michael@0 217 * FULL_KEY This must be the first key/data pair on the page. It
michael@0 218 * is used in two cases.
michael@0 219 *
michael@0 220 * Case 1:
michael@0 221 * There is a complete key on the page but no data
michael@0 222 * (because it wouldn't fit). The next page contains
michael@0 223 * the data.
michael@0 224 *
michael@0 225 * Page format it:
michael@0 226 * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
michael@0 227 *
michael@0 228 * KEY_OFF -- offset of the beginning of the key
michael@0 229 * FULL_KEY -- 2
michael@0 230 * OVFL_PAGENO - page number of the next overflow page
michael@0 231 * OVFLPAGE -- 0
michael@0 232 *
michael@0 233 * Case 2:
michael@0 234 * This page contains no key, but part of a large
michael@0 235 * data field, which is continued on the next page.
michael@0 236 *
michael@0 237 * Page format it:
michael@0 238 * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
michael@0 239 *
michael@0 240 * KEY_OFF -- offset of the beginning of the data on
michael@0 241 * this page
michael@0 242 * FULL_KEY -- 2
michael@0 243 * OVFL_PAGENO - page number of the next overflow page
michael@0 244 * OVFLPAGE -- 0
michael@0 245 *
michael@0 246 * FULL_KEY_DATA
michael@0 247 * This must be the first key/data pair on the page.
michael@0 248 * There are two cases:
michael@0 249 *
michael@0 250 * Case 1:
michael@0 251 * This page contains a key and the beginning of the
michael@0 252 * data field, but the data field is continued on the
michael@0 253 * next page.
michael@0 254 *
michael@0 255 * Page format is:
michael@0 256 * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
michael@0 257 *
michael@0 258 * KEY_OFF -- offset of the beginning of the key
michael@0 259 * FULL_KEY_DATA -- 3
michael@0 260 * OVFL_PAGENO - page number of the next overflow page
michael@0 261 * DATA_OFF -- offset of the beginning of the data
michael@0 262 *
michael@0 263 * Case 2:
michael@0 264 * This page contains the last page of a big data pair.
michael@0 265 * There is no key, only the tail end of the data
michael@0 266 * on this page.
michael@0 267 *
michael@0 268 * Page format is:
michael@0 269 * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
michael@0 270 *
michael@0 271 * DATA_OFF -- offset of the beginning of the data on
michael@0 272 * this page
michael@0 273 * FULL_KEY_DATA -- 3
michael@0 274 * OVFL_PAGENO - page number of the next overflow page
michael@0 275 * OVFLPAGE -- 0
michael@0 276 *
michael@0 277 * OVFL_PAGENO and OVFLPAGE are optional (they are
michael@0 278 * not present if there is no next page).
michael@0 279 */
michael@0 280
michael@0 281 #define OVFLPAGE 0
michael@0 282 #define PARTIAL_KEY 1
michael@0 283 #define FULL_KEY 2
michael@0 284 #define FULL_KEY_DATA 3
michael@0 285 #define REAL_KEY 4
michael@0 286
michael@0 287 /* Short hands for accessing structure */
michael@0 288 #undef BSIZE
michael@0 289 #define BSIZE hdr.bsize
michael@0 290 #undef BSHIFT
michael@0 291 #define BSHIFT hdr.bshift
michael@0 292 #define DSIZE hdr.dsize
michael@0 293 #define SGSIZE hdr.ssize
michael@0 294 #define SSHIFT hdr.sshift
michael@0 295 #define LORDER hdr.lorder
michael@0 296 #define OVFL_POINT hdr.ovfl_point
michael@0 297 #define LAST_FREED hdr.last_freed
michael@0 298 #define MAX_BUCKET hdr.max_bucket
michael@0 299 #define FFACTOR hdr.ffactor
michael@0 300 #define HIGH_MASK hdr.high_mask
michael@0 301 #define LOW_MASK hdr.low_mask
michael@0 302 #define NKEYS hdr.nkeys
michael@0 303 #define HDRPAGES hdr.hdrpages
michael@0 304 #define SPARES hdr.spares
michael@0 305 #define BITMAPS hdr.bitmaps
michael@0 306 #define VERSION hdr.version
michael@0 307 #define MAGIC hdr.magic
michael@0 308 #define NEXT_FREE hdr.next_free
michael@0 309 #define H_CHARKEY hdr.h_charkey
michael@0 310
michael@0 311 extern uint32 (*__default_hash) (const void *, size_t);
michael@0 312 void __buf_init(HTAB *hashp, int32 nbytes);
michael@0 313 int __big_delete(HTAB *hashp, BUFHEAD *bufp);
michael@0 314 BUFHEAD * __get_buf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp, int newpage);
michael@0 315 uint32 __call_hash(HTAB *hashp, char *k, size_t len);
michael@0 316 #include "page.h"
michael@0 317 extern int __big_split(HTAB *hashp, BUFHEAD *op,BUFHEAD *np,
michael@0 318 BUFHEAD *big_keyp,uint32 addr,uint32 obucket, SPLIT_RETURN *ret);
michael@0 319 void __free_ovflpage(HTAB *hashp, BUFHEAD *obufp);
michael@0 320 BUFHEAD * __add_ovflpage(HTAB *hashp, BUFHEAD *bufp);
michael@0 321 int __big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val);
michael@0 322 int __expand_table(HTAB *hashp);
michael@0 323 uint32 __log2(uint32 num);
michael@0 324 void __reclaim_buf(HTAB *hashp, BUFHEAD *bp);
michael@0 325 int __get_page(HTAB *hashp, char * p, uint32 bucket, int is_bucket, int is_disk, int is_bitmap);
michael@0 326 int __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap);
michael@0 327 int __ibitmap(HTAB *hashp, int pnum, int nbits, int ndx);
michael@0 328 int __buf_free(HTAB *hashp, int do_free, int to_disk);
michael@0 329 int __find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size);
michael@0 330 uint16 __find_last_page(HTAB *hashp, BUFHEAD **bpp);
michael@0 331 int __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT * val);
michael@0 332 int __big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current);
michael@0 333 int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx);
michael@0 334 int __big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set);
michael@0 335 int __split_page(HTAB *hashp, uint32 obucket, uint32 nbucket);

mercurial