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