1*46135Smao /*- 2*46135Smao * Copyright (c) 1990 The Regents of the University of California. 3*46135Smao * All rights reserved. 4*46135Smao * 5*46135Smao * This code is derived from software contributed to Berkeley by 6*46135Smao * Mike Olson. 7*46135Smao * 8*46135Smao * %sccs.include.redist.c% 9*46135Smao */ 10*46135Smao 11*46135Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46135Smao static char sccsid[] = "@(#)bt_get.c 5.1 (Berkeley) 01/23/91"; 13*46135Smao #endif /* LIBC_SCCS and not lint */ 14*46135Smao 15*46135Smao #include <sys/param.h> 16*46135Smao #include <sys/types.h> 17*46135Smao #include <sys/errno.h> 18*46135Smao #include <sys/file.h> 19*46135Smao #include <db.h> 20*46135Smao #include "btree.h" 21*46135Smao 22*46135Smao /* 23*46135Smao * BT_GETPAGE -- Make pgno the current page of the btree. 24*46135Smao * 25*46135Smao * This routine is just a wrapper that decides whether to call the 26*46135Smao * memory or disk-based routine to do the work. 27*46135Smao * 28*46135Smao * Parameters: 29*46135Smao * t -- btree in which to get page 30*46135Smao * pgno -- page number to get 31*46135Smao * 32*46135Smao * Returns: 33*46135Smao * RET_SUCCESS or RET_ERROR. 34*46135Smao */ 35*46135Smao 36*46135Smao int 37*46135Smao _bt_getpage(t, pgno) 38*46135Smao BTREE_P t; 39*46135Smao pgno_t pgno; 40*46135Smao { 41*46135Smao #ifdef DEBUG 42*46135Smao if (pgno == P_NONE) 43*46135Smao _punt(); 44*46135Smao #endif /* DEBUG */ 45*46135Smao 46*46135Smao /* see if we can get away without doing any work */ 47*46135Smao if (t->bt_curpage != (BTHEADER *) NULL) { 48*46135Smao if (t->bt_curpage->h_pgno == pgno) 49*46135Smao return (RET_SUCCESS); 50*46135Smao } 51*46135Smao 52*46135Smao if (t->bt_fname == (char *) NULL) 53*46135Smao return (_bt_getmpage(t, pgno)); 54*46135Smao else 55*46135Smao return (_bt_getdpage(t, pgno)); 56*46135Smao } 57*46135Smao 58*46135Smao /* 59*46135Smao * _BT_GETMPAGE -- Make pgno the current page of the btree. 60*46135Smao * 61*46135Smao * This routine gets pages for in-memory btrees. 62*46135Smao * 63*46135Smao * Parameters: 64*46135Smao * t -- btree in which to get page 65*46135Smao * pgno -- page number to get 66*46135Smao * 67*46135Smao * Returns: 68*46135Smao * RET_SUCCESS or RET_ERROR. 69*46135Smao */ 70*46135Smao 71*46135Smao int 72*46135Smao _bt_getmpage(t, pgno) 73*46135Smao register BTREE_P t; 74*46135Smao pgno_t pgno; 75*46135Smao { 76*46135Smao int htindex; 77*46135Smao BTHEADER *h; 78*46135Smao HTBUCKET *b; 79*46135Smao 80*46135Smao if (t->bt_curpage == (BTHEADER *) NULL) { 81*46135Smao if (pgno != P_ROOT) { 82*46135Smao errno = EBADF; 83*46135Smao return (RET_ERROR); 84*46135Smao } 85*46135Smao 86*46135Smao t->bt_npages++; 87*46135Smao h = (BTHEADER *) malloc((unsigned) t->bt_psize); 88*46135Smao if (h == (BTHEADER *) NULL) 89*46135Smao return (RET_ERROR); 90*46135Smao 91*46135Smao h->h_pgno = P_ROOT; 92*46135Smao h->h_flags = F_LEAF; 93*46135Smao h->h_lower = (index_t) 94*46135Smao (((char *) &(h->h_linp[0])) - ((char *) h)); 95*46135Smao h->h_upper = t->bt_psize; 96*46135Smao h->h_prevpg = h->h_nextpg = P_NONE; 97*46135Smao 98*46135Smao t->bt_curpage = h; 99*46135Smao 100*46135Smao /* get the root page into the hash table */ 101*46135Smao if (_bt_write(t, h, RELEASE) == RET_ERROR) 102*46135Smao return (RET_ERROR); 103*46135Smao } 104*46135Smao 105*46135Smao htindex = HASHKEY(pgno); 106*46135Smao 107*46135Smao for (b = t->bt_s.bt_ht[htindex]; 108*46135Smao b != (HTBUCKET *) NULL; 109*46135Smao b = b->ht_next) { 110*46135Smao if (b->ht_pgno == pgno) { 111*46135Smao t->bt_curpage = b->ht_page; 112*46135Smao return (RET_SUCCESS); 113*46135Smao } 114*46135Smao } 115*46135Smao return (RET_ERROR); 116*46135Smao } 117*46135Smao 118*46135Smao /* 119*46135Smao * _BT_GETDPAGE -- Make pgno the current page of the btree. 120*46135Smao * 121*46135Smao * This routine gets pages for disk btrees. 122*46135Smao * 123*46135Smao * Because disk btree pages must be readable across machine architectures, 124*46135Smao * the btree code writes integers out in network format. This routine 125*46135Smao * converts them back to host format before returning the page. 126*46135Smao * 127*46135Smao * Parameters: 128*46135Smao * t -- btree in which to get page 129*46135Smao * pgno -- page number to get 130*46135Smao * 131*46135Smao * Returns: 132*46135Smao * RET_SUCCESS, RET_ERROR. 133*46135Smao */ 134*46135Smao 135*46135Smao int 136*46135Smao _bt_getdpage(t, pgno) 137*46135Smao register BTREE_P t; 138*46135Smao pgno_t pgno; 139*46135Smao { 140*46135Smao BTHEADER *h; 141*46135Smao char *cache; 142*46135Smao long pos; 143*46135Smao int n, nbytes; 144*46135Smao 145*46135Smao /* if we have an lru cache, let the cache code do the work */ 146*46135Smao if (ISCACHE(t)) { 147*46135Smao cache = t->bt_s.bt_d.d_cache; 148*46135Smao 149*46135Smao /* release the old page */ 150*46135Smao if (t->bt_curpage != (BTHEADER *) NULL) { 151*46135Smao pgno_t opgno = t->bt_curpage->h_pgno; 152*46135Smao t->bt_curpage->h_flags &= ~F_DIRTY; 153*46135Smao 154*46135Smao if (lruwrite(cache, (int) opgno) < 0) 155*46135Smao return (RET_ERROR); 156*46135Smao 157*46135Smao if (lrurelease(cache, (int) opgno) < 0) 158*46135Smao return (RET_ERROR); 159*46135Smao } 160*46135Smao 161*46135Smao if (pgno > t->bt_npages) { 162*46135Smao if ((h = (BTHEADER *) lrugetnew(cache, (int)pgno, &nbytes)) 163*46135Smao == (BTHEADER *) NULL) 164*46135Smao return (RET_ERROR); 165*46135Smao t->bt_npages = pgno; 166*46135Smao } else { 167*46135Smao if ((h = (BTHEADER *) lruget(cache, (int)pgno, &nbytes)) 168*46135Smao == (BTHEADER *) NULL) 169*46135Smao return (RET_ERROR); 170*46135Smao } 171*46135Smao 172*46135Smao /* init this page, if necessary */ 173*46135Smao if (nbytes == 0) { 174*46135Smao h->h_pgno = pgno; 175*46135Smao h->h_flags = F_LEAF; 176*46135Smao h->h_lower = (index_t) 177*46135Smao (((char *) &(h->h_linp[0])) - ((char *) h)); 178*46135Smao h->h_upper = t->bt_psize; 179*46135Smao h->h_prevpg = h->h_nextpg = P_NONE; 180*46135Smao } 181*46135Smao 182*46135Smao t->bt_curpage = h; 183*46135Smao 184*46135Smao return (RET_SUCCESS); 185*46135Smao } 186*46135Smao 187*46135Smao /* sync the current page, if necessary */ 188*46135Smao if (t->bt_curpage != (BTHEADER *) NULL) { 189*46135Smao if (t->bt_curpage->h_flags & F_DIRTY) 190*46135Smao if (_bt_write(t, t->bt_curpage, RELEASE) == RET_ERROR) 191*46135Smao return (RET_ERROR); 192*46135Smao } else { 193*46135Smao if (t->bt_npages == 0) 194*46135Smao t->bt_npages = 1; 195*46135Smao 196*46135Smao /* if no current page, get space for one */ 197*46135Smao if ((t->bt_curpage = (BTHEADER *) malloc((unsigned) t->bt_psize)) 198*46135Smao == (BTHEADER *) NULL) { 199*46135Smao return (RET_ERROR); 200*46135Smao } 201*46135Smao } 202*46135Smao 203*46135Smao n = t->bt_psize; 204*46135Smao pos = (long) (pgno * n); 205*46135Smao 206*46135Smao /* seek to correct location in file */ 207*46135Smao if (lseek(t->bt_s.bt_d.d_fd, pos, L_SET) != pos) { 208*46135Smao return (RET_ERROR); 209*46135Smao } 210*46135Smao 211*46135Smao /* read the page */ 212*46135Smao if ((nbytes = read(t->bt_s.bt_d.d_fd, t->bt_curpage, n)) < n) { 213*46135Smao 214*46135Smao /* 215*46135Smao * If we didn't get a full page, we must have gotten no 216*46135Smao * data at all -- in which case we're trying to read a 217*46135Smao * root page that doesn't exist yet. This is the only 218*46135Smao * case in which this is okay. If this happens, construct 219*46135Smao * an empty root page by hand. 220*46135Smao */ 221*46135Smao if (nbytes != 0 || pgno != P_ROOT) { 222*46135Smao errno = EBADF; 223*46135Smao return (RET_ERROR); 224*46135Smao } 225*46135Smao 226*46135Smao h = (BTHEADER *) t->bt_curpage; 227*46135Smao h->h_pgno = pgno; 228*46135Smao h->h_flags = F_LEAF; 229*46135Smao h->h_lower = (index_t) 230*46135Smao (((char *) &(h->h_linp[0])) - ((char *) h)); 231*46135Smao h->h_upper = t->bt_psize; 232*46135Smao h->h_prevpg = h->h_nextpg = P_NONE; 233*46135Smao } else 234*46135Smao (void) _bt_pgin(t->bt_curpage, (char *) t->bt_lorder); 235*46135Smao 236*46135Smao return (RET_SUCCESS); 237*46135Smao } 238*46135Smao 239*46135Smao /* 240*46135Smao * _BT_PGOUT, _BT_PGIN -- Convert host-specific number layout to/from 241*46135Smao * the host-independent format stored on disk. 242*46135Smao * 243*46135Smao * Parameters: 244*46135Smao * h -- page to convert 245*46135Smao * _lorder -- byte order for pages (stored as a char * in the 246*46135Smao * cache, and passed around as a magic cookie). 247*46135Smao * 248*46135Smao * Returns: 249*46135Smao * RET_SUCCESS (lru code requires a return value). 250*46135Smao * 251*46135Smao * Side Effects: 252*46135Smao * Layout of tree metadata on the page is changed in place. 253*46135Smao * 254*46135Smao * Warnings: 255*46135Smao * Everywhere else in the code, the types pgno_t and index_t 256*46135Smao * are opaque. These two routines know what they really 257*46135Smao * are. 258*46135Smao */ 259*46135Smao 260*46135Smao int 261*46135Smao _bt_pgout(h, _lorder) 262*46135Smao BTHEADER *h; 263*46135Smao char *_lorder; 264*46135Smao { 265*46135Smao int i; 266*46135Smao int top; 267*46135Smao int lorder; 268*46135Smao DATUM *d; 269*46135Smao IDATUM *id; 270*46135Smao size_t chain; 271*46135Smao 272*46135Smao lorder = (int) _lorder; 273*46135Smao if (lorder == BYTE_ORDER) 274*46135Smao return (RET_SUCCESS); 275*46135Smao 276*46135Smao if (h->h_flags & F_LEAF) { 277*46135Smao if (h->h_flags & F_CONT) { 278*46135Smao if (h->h_prevpg == P_NONE) { 279*46135Smao size_t longsz; 280*46135Smao 281*46135Smao (void) bcopy((char *) &(h->h_linp[0]), 282*46135Smao (char *) &longsz, 283*46135Smao sizeof(longsz)); 284*46135Smao BLSWAP(longsz); 285*46135Smao (void) bcopy((char *) &longsz, 286*46135Smao (char *) &(h->h_linp[0]), 287*46135Smao sizeof(longsz)); 288*46135Smao } 289*46135Smao } else { 290*46135Smao top = NEXTINDEX(h); 291*46135Smao for (i = 0; i < top; i++) { 292*46135Smao d = (DATUM *) GETDATUM(h, i); 293*46135Smao if (d->d_flags & D_BIGKEY) { 294*46135Smao (void) bcopy((char *) &(d->d_bytes[0]), 295*46135Smao (char *) &chain, 296*46135Smao sizeof(chain)); 297*46135Smao BLSWAP(chain); 298*46135Smao (void) bcopy((char *) &chain, 299*46135Smao (char *) &(d->d_bytes[0]), 300*46135Smao sizeof(chain)); 301*46135Smao } 302*46135Smao if (d->d_flags & D_BIGDATA) { 303*46135Smao (void) bcopy((char *) &(d->d_bytes[d->d_ksize]), 304*46135Smao (char *) &chain, 305*46135Smao sizeof(chain)); 306*46135Smao BLSWAP(chain); 307*46135Smao (void) bcopy((char *) &chain, 308*46135Smao (char *) &(d->d_bytes[d->d_ksize]), 309*46135Smao sizeof(chain)); 310*46135Smao } 311*46135Smao BLSWAP(d->d_dsize); 312*46135Smao BLSWAP(d->d_ksize); 313*46135Smao BLSWAP(d->d_flags); 314*46135Smao BLSWAP(h->h_linp[i]); 315*46135Smao } 316*46135Smao } 317*46135Smao } else { 318*46135Smao top = NEXTINDEX(h); 319*46135Smao for (i = 0; i < top; i++) { 320*46135Smao id = (IDATUM *) GETDATUM(h, i); 321*46135Smao BLSWAP(id->i_size); 322*46135Smao BLSWAP(id->i_pgno); 323*46135Smao BLSWAP(id->i_flags); 324*46135Smao if (id->i_flags & D_BIGKEY) { 325*46135Smao (void) bcopy((char *) &(id->i_bytes[0]), 326*46135Smao (char *) &chain, 327*46135Smao sizeof(chain)); 328*46135Smao BLSWAP(chain); 329*46135Smao (void) bcopy((char *) &chain, 330*46135Smao (char *) &(id->i_bytes[0]), 331*46135Smao sizeof(chain)); 332*46135Smao } 333*46135Smao BLSWAP(h->h_linp[i]); 334*46135Smao } 335*46135Smao } 336*46135Smao BLSWAP(h->h_flags); 337*46135Smao BLSWAP(h->h_pgno); 338*46135Smao BLSWAP(h->h_prevpg); 339*46135Smao BLSWAP(h->h_nextpg); 340*46135Smao BLSWAP(h->h_lower); 341*46135Smao BLSWAP(h->h_upper); 342*46135Smao 343*46135Smao return (RET_SUCCESS); 344*46135Smao } 345*46135Smao 346*46135Smao int 347*46135Smao _bt_pgin(h, _lorder) 348*46135Smao BTHEADER *h; 349*46135Smao char *_lorder; 350*46135Smao { 351*46135Smao int i; 352*46135Smao int top; 353*46135Smao int lorder; 354*46135Smao DATUM *d; 355*46135Smao IDATUM *id; 356*46135Smao size_t chain; 357*46135Smao 358*46135Smao /* 359*46135Smao * If btree pages are to be stored in the host byte order, don't 360*46135Smao * bother swapping. 361*46135Smao */ 362*46135Smao lorder = (int) _lorder; 363*46135Smao if (lorder == BYTE_ORDER) 364*46135Smao return (RET_SUCCESS); 365*46135Smao 366*46135Smao BLSWAP(h->h_upper); 367*46135Smao BLSWAP(h->h_lower); 368*46135Smao BLSWAP(h->h_nextpg); 369*46135Smao BLSWAP(h->h_prevpg); 370*46135Smao BLSWAP(h->h_pgno); 371*46135Smao BLSWAP(h->h_flags); 372*46135Smao 373*46135Smao if (h->h_flags & F_LEAF) { 374*46135Smao if (h->h_flags & F_CONT) { 375*46135Smao if (h->h_prevpg == P_NONE) { 376*46135Smao size_t longsz; 377*46135Smao 378*46135Smao (void) bcopy((char *) &(h->h_linp[0]), 379*46135Smao (char *) &longsz, 380*46135Smao sizeof(longsz)); 381*46135Smao BLSWAP(longsz); 382*46135Smao (void) bcopy((char *) &longsz, 383*46135Smao (char *) &(h->h_linp[0]), 384*46135Smao sizeof(longsz)); 385*46135Smao } 386*46135Smao } else { 387*46135Smao top = NEXTINDEX(h); 388*46135Smao for (i = 0; i < top; i++) { 389*46135Smao BLSWAP(h->h_linp[i]); 390*46135Smao d = (DATUM *) GETDATUM(h, i); 391*46135Smao BLSWAP(d->d_dsize); 392*46135Smao BLSWAP(d->d_ksize); 393*46135Smao BLSWAP(d->d_flags); 394*46135Smao if (d->d_flags & D_BIGKEY) { 395*46135Smao (void) bcopy((char *) &(d->d_bytes[0]), 396*46135Smao (char *) &chain, 397*46135Smao sizeof(chain)); 398*46135Smao BLSWAP(chain); 399*46135Smao (void) bcopy((char *) &chain, 400*46135Smao (char *) &(d->d_bytes[0]), 401*46135Smao sizeof(chain)); 402*46135Smao } 403*46135Smao if (d->d_flags & D_BIGDATA) { 404*46135Smao (void) bcopy((char *) &(d->d_bytes[d->d_ksize]), 405*46135Smao (char *) &chain, 406*46135Smao sizeof(chain)); 407*46135Smao BLSWAP(chain); 408*46135Smao (void) bcopy((char *) &chain, 409*46135Smao (char *) &(d->d_bytes[d->d_ksize]), 410*46135Smao sizeof(chain)); 411*46135Smao } 412*46135Smao } 413*46135Smao } 414*46135Smao } else { 415*46135Smao top = NEXTINDEX(h); 416*46135Smao for (i = 0; i < top; i++) { 417*46135Smao BLSWAP(h->h_linp[i]); 418*46135Smao id = (IDATUM *) GETDATUM(h, i); 419*46135Smao BLSWAP(id->i_size); 420*46135Smao BLSWAP(id->i_pgno); 421*46135Smao BLSWAP(id->i_flags); 422*46135Smao if (id->i_flags & D_BIGKEY) { 423*46135Smao (void) bcopy((char *) &(id->i_bytes[0]), 424*46135Smao (char *) &chain, 425*46135Smao sizeof(chain)); 426*46135Smao BLSWAP(chain); 427*46135Smao (void) bcopy((char *) &chain, 428*46135Smao (char *) &(id->i_bytes[0]), 429*46135Smao sizeof(chain)); 430*46135Smao } 431*46135Smao } 432*46135Smao } 433*46135Smao return (RET_SUCCESS); 434*46135Smao } 435*46135Smao 436*46135Smao /* 437*46135Smao * _BT_ALLOCPG -- allocate a new page in the btree. 438*46135Smao * 439*46135Smao * This is called when we split a page, to get space to do the split. 440*46135Smao * For disk btrees, these pages are released when the split is done. 441*46135Smao * For memory btrees, they are not. 442*46135Smao * 443*46135Smao * Parameters: 444*46135Smao * t -- tree in which to do split 445*46135Smao * 446*46135Smao * Returns: 447*46135Smao * Pointer to the newly-allocated page 448*46135Smao */ 449*46135Smao 450*46135Smao BTHEADER * 451*46135Smao _bt_allocpg(t) 452*46135Smao BTREE_P t; 453*46135Smao { 454*46135Smao BTHEADER *h = t->bt_curpage; 455*46135Smao BTHEADER *nh; 456*46135Smao int nbytes; 457*46135Smao 458*46135Smao /* if we have a cache, let the cache code do the work */ 459*46135Smao if (ISDISK(t) && ISCACHE(t)) { 460*46135Smao nh = (BTHEADER *) lrugetnew(t->bt_s.bt_d.d_cache, 461*46135Smao (int) (t->bt_npages + 1), 462*46135Smao &nbytes); 463*46135Smao } else { 464*46135Smao nh = (BTHEADER *) malloc((unsigned) t->bt_psize); 465*46135Smao } 466*46135Smao 467*46135Smao if (nh != (BTHEADER *) NULL) { 468*46135Smao nh->h_pgno = nh->h_prevpg = nh->h_nextpg = P_NONE; 469*46135Smao nh->h_flags = h->h_flags; 470*46135Smao nh->h_lower = (index_t) 471*46135Smao (((char *) &(nh->h_linp[0])) - ((char *) nh)); 472*46135Smao nh->h_upper = t->bt_psize; 473*46135Smao } 474*46135Smao 475*46135Smao return (nh); 476*46135Smao } 477*46135Smao 478*46135Smao /* 479*46135Smao * _BT_WRITE -- Write a specific page to a btree file. 480*46135Smao * 481*46135Smao * Parameters: 482*46135Smao * t -- btree to get the page 483*46135Smao * h -- page to write 484*46135Smao * relflag -- (int) this page may/may not be released 485*46135Smao * 486*46135Smao * Returns: 487*46135Smao * RET_SUCCESS, RET_ERROR. 488*46135Smao * 489*46135Smao * Side Effects: 490*46135Smao * Writes a metadata page if none has been written yet. 491*46135Smao */ 492*46135Smao 493*46135Smao int 494*46135Smao _bt_write(t, h, relflag) 495*46135Smao BTREE_P t; 496*46135Smao BTHEADER *h; 497*46135Smao int relflag; 498*46135Smao { 499*46135Smao long pos; 500*46135Smao int htindex; 501*46135Smao HTBUCKET *b; 502*46135Smao char *cache; 503*46135Smao pgno_t pgno; 504*46135Smao 505*46135Smao h->h_flags &= ~F_DIRTY; 506*46135Smao if (ISDISK(t)) { 507*46135Smao 508*46135Smao /* if we haven't done so yet, write the metadata */ 509*46135Smao if (!(t->bt_flags & BTF_METAOK)) { 510*46135Smao if (_bt_wrtmeta(t) == RET_ERROR) 511*46135Smao return (RET_ERROR); 512*46135Smao } 513*46135Smao 514*46135Smao pgno = h->h_pgno; 515*46135Smao 516*46135Smao 517*46135Smao /* if we have a cache, let the cache code do the work */ 518*46135Smao if ((cache = t->bt_s.bt_d.d_cache) != (char *) NULL) { 519*46135Smao if (lruwrite(cache, (int) pgno) < 0) 520*46135Smao return (RET_ERROR); 521*46135Smao if (relflag && lrurelease(cache, (int) pgno) < 0) 522*46135Smao return (RET_ERROR); 523*46135Smao 524*46135Smao } else { 525*46135Smao (void) _bt_pgout(h, (char *) t->bt_lorder); 526*46135Smao /* now write the current page */ 527*46135Smao pos = (long) (pgno * t->bt_psize); 528*46135Smao if (lseek(t->bt_s.bt_d.d_fd, pos, L_SET) != pos) 529*46135Smao return (RET_ERROR); 530*46135Smao if (write(t->bt_s.bt_d.d_fd, (char *) h, (int) t->bt_psize) 531*46135Smao < t->bt_psize) 532*46135Smao return (RET_ERROR); 533*46135Smao if (!relflag) 534*46135Smao (void) _bt_pgin(h, (char *) t->bt_lorder); 535*46135Smao } 536*46135Smao } else { 537*46135Smao /* in-memory btree */ 538*46135Smao htindex = HASHKEY(h->h_pgno); 539*46135Smao 540*46135Smao /* see if we need to overwrite existing entry */ 541*46135Smao for (b = t->bt_s.bt_ht[htindex]; 542*46135Smao b != (HTBUCKET *) NULL; 543*46135Smao b = b->ht_next) { 544*46135Smao if (b->ht_pgno == h->h_pgno) { 545*46135Smao b->ht_page = h; 546*46135Smao return (RET_SUCCESS); 547*46135Smao } 548*46135Smao } 549*46135Smao 550*46135Smao /* new entry, write it */ 551*46135Smao b = (HTBUCKET *) malloc((unsigned) sizeof (HTBUCKET)); 552*46135Smao if (b == (HTBUCKET *) NULL) 553*46135Smao return (RET_ERROR); 554*46135Smao 555*46135Smao b->ht_pgno = h->h_pgno; 556*46135Smao b->ht_page = h; 557*46135Smao b->ht_next = t->bt_s.bt_ht[htindex]; 558*46135Smao t->bt_s.bt_ht[htindex] = b; 559*46135Smao } 560*46135Smao return (RET_SUCCESS); 561*46135Smao } 562*46135Smao 563*46135Smao /* 564*46135Smao * _BT_RELEASE -- Release a locked-down cache page 565*46135Smao * 566*46135Smao * During page splits, we want to force pages out to the cache 567*46135Smao * before we actually release them, in some cases. This routine 568*46135Smao * releases such a page when it is no longer needed. 569*46135Smao * 570*46135Smao * Parameters: 571*46135Smao * t -- btree in which to release page 572*46135Smao * h -- page to release 573*46135Smao * 574*46135Smao * Returns: 575*46135Smao * RET_SUCCESS, RET_ERROR. 576*46135Smao * 577*46135Smao * Side Effects: 578*46135Smao * None. 579*46135Smao */ 580*46135Smao 581*46135Smao int 582*46135Smao _bt_release(t, h) 583*46135Smao BTREE_P t; 584*46135Smao BTHEADER *h; 585*46135Smao { 586*46135Smao if (ISDISK(t) && ISCACHE(t)) { 587*46135Smao if (lrurelease(t->bt_s.bt_d.d_cache, (int) (h->h_pgno)) < 0) 588*46135Smao return (RET_ERROR); 589*46135Smao } 590*46135Smao return (RET_SUCCESS); 591*46135Smao } 592*46135Smao 593*46135Smao /* 594*46135Smao * _BT_WRTMETA -- Write metadata to the btree. 595*46135Smao * 596*46135Smao * Parameters: 597*46135Smao * t -- tree to which to write 598*46135Smao * 599*46135Smao * Returns: 600*46135Smao * RET_SUCCESS, RET_ERROR. 601*46135Smao */ 602*46135Smao 603*46135Smao int 604*46135Smao _bt_wrtmeta(t) 605*46135Smao BTREE_P t; 606*46135Smao { 607*46135Smao BTMETA m; 608*46135Smao 609*46135Smao if (lseek(t->bt_s.bt_d.d_fd, 0l, L_SET) != 0l) 610*46135Smao return (RET_ERROR); 611*46135Smao 612*46135Smao /* lorder has to be in host-independent format */ 613*46135Smao m.m_lorder = (u_long) htonl((long) t->bt_lorder); 614*46135Smao 615*46135Smao m.m_magic = BTREEMAGIC; 616*46135Smao m.m_version = BTREEVERSION; 617*46135Smao m.m_psize = t->bt_psize; 618*46135Smao m.m_free = t->bt_free; 619*46135Smao m.m_flags = t->bt_flags & BTF_NODUPS; 620*46135Smao 621*46135Smao if (t->bt_lorder != BYTE_ORDER) { 622*46135Smao BLSWAP(m.m_magic); 623*46135Smao BLSWAP(m.m_version); 624*46135Smao BLSWAP(m.m_psize); 625*46135Smao BLSWAP(m.m_free); 626*46135Smao BLSWAP(m.m_flags); 627*46135Smao } 628*46135Smao 629*46135Smao if (write(t->bt_s.bt_d.d_fd, (char *) &m, sizeof(m)) 630*46135Smao != sizeof(m)) { 631*46135Smao return (RET_ERROR); 632*46135Smao } 633*46135Smao 634*46135Smao t->bt_flags |= BTF_METAOK; 635*46135Smao 636*46135Smao return (RET_SUCCESS); 637*46135Smao } 638