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