1*46137Smao /*- 2*46137Smao * Copyright (c) 1990 The Regents of the University of California. 3*46137Smao * All rights reserved. 4*46137Smao * 5*46137Smao * This code is derived from software contributed to Berkeley by 6*46137Smao * Mike Olson. 7*46137Smao * 8*46137Smao * %sccs.include.redist.c% 9*46137Smao */ 10*46137Smao 11*46137Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46137Smao static char sccsid[] = "@(#)bt_utils.c 5.1 (Berkeley) 01/23/91"; 13*46137Smao #endif /* LIBC_SCCS and not lint */ 14*46137Smao 15*46137Smao #include <sys/types.h> 16*46137Smao #include <db.h> 17*46137Smao #include "btree.h" 18*46137Smao 19*46137Smao /* 20*46137Smao * _BT_BUILDRET -- Build return key/data pair as a result of search or scan. 21*46137Smao * 22*46137Smao * This routine manages the statically allocated buffers in which we 23*46137Smao * return data to the user. 24*46137Smao * 25*46137Smao * Parameters: 26*46137Smao * t -- btree from which to return datum 27*46137Smao * d -- DATUM to be returned to the user. 28*46137Smao * data -- data argument supplied by user for return 29*46137Smao * key -- key argument supplied by user for return 30*46137Smao * 31*46137Smao * Returns: 32*46137Smao * RET_SUCCESS, RET_ERROR. 33*46137Smao * 34*46137Smao * Side Effects: 35*46137Smao * May free and reallocate static buffers, if the data 36*46137Smao * we want to return is bigger than the space we have to 37*46137Smao * do so. 38*46137Smao */ 39*46137Smao 40*46137Smao int 41*46137Smao _bt_buildret(t, d, data, key) 42*46137Smao BTREE_P t; 43*46137Smao DATUM *d; 44*46137Smao DBT *data; 45*46137Smao DBT *key; 46*46137Smao { 47*46137Smao static int _data_s = 0; 48*46137Smao static int _key_s = 0; 49*46137Smao static char *_data = (char *) NULL; 50*46137Smao static char *_key = (char *) NULL; 51*46137Smao pgno_t chain; 52*46137Smao 53*46137Smao if (d->d_flags & D_BIGKEY) { 54*46137Smao if (_key != (char *) NULL) 55*46137Smao (void) free(_key); 56*46137Smao (void) bcopy((char *) &(d->d_bytes[0]), 57*46137Smao (char *) &chain, 58*46137Smao sizeof(chain)); 59*46137Smao if (_bt_getbig(t, chain, &_key, &_key_s) == RET_ERROR) 60*46137Smao return (RET_ERROR); 61*46137Smao key->data = _key; 62*46137Smao key->size = _key_s; 63*46137Smao } else { 64*46137Smao /* need more space for key? */ 65*46137Smao if (d->d_ksize > _key_s) { 66*46137Smao if (_key != (char *) NULL) 67*46137Smao (void) free (_key); 68*46137Smao if ((_key = (char *) malloc((unsigned) d->d_ksize)) 69*46137Smao == (char *) NULL) 70*46137Smao return (RET_ERROR); 71*46137Smao _key_s = d->d_ksize; 72*46137Smao } 73*46137Smao 74*46137Smao key->data = _key; 75*46137Smao if ((key->size = d->d_ksize) > 0) 76*46137Smao (void) bcopy(&(d->d_bytes[0]), 77*46137Smao _key, 78*46137Smao (int) d->d_ksize); 79*46137Smao } 80*46137Smao 81*46137Smao if (d->d_flags & D_BIGDATA) { 82*46137Smao if (_data != (char *) NULL) 83*46137Smao (void) free(_data); 84*46137Smao (void) bcopy(&(d->d_bytes[d->d_ksize]), 85*46137Smao (char *) &chain, 86*46137Smao sizeof(chain)); 87*46137Smao if (_bt_getbig(t, chain, &_data, &_data_s) == RET_ERROR) 88*46137Smao return (RET_ERROR); 89*46137Smao data->data = _data; 90*46137Smao data->size = _data_s; 91*46137Smao } else { 92*46137Smao /* need more space for data? */ 93*46137Smao if (d->d_dsize > _data_s) { 94*46137Smao if (_data != (char *) NULL) 95*46137Smao (void) free (_data); 96*46137Smao if ((_data = (char *) malloc((unsigned) d->d_dsize)) 97*46137Smao == (char *) NULL) 98*46137Smao return (RET_ERROR); 99*46137Smao _data_s = d->d_dsize; 100*46137Smao } 101*46137Smao 102*46137Smao data->data = _data; 103*46137Smao 104*46137Smao if ((data->size = d->d_dsize) > 0) 105*46137Smao (void) bcopy(&(d->d_bytes[d->d_ksize]), 106*46137Smao _data, 107*46137Smao (size_t) (d->d_dsize)); 108*46137Smao } 109*46137Smao 110*46137Smao return (RET_SUCCESS); 111*46137Smao } 112*46137Smao 113*46137Smao /* 114*46137Smao * _BT_CMP -- Compare a key to a given item on the current page. 115*46137Smao * 116*46137Smao * This routine is a wrapper for the user's comparison function. 117*46137Smao * 118*46137Smao * Parameters: 119*46137Smao * t -- tree in which to do comparison 120*46137Smao * p -- pointer to one argument for the comparison function 121*46137Smao * n -- index of item to supply second arg to comparison function 122*46137Smao * 123*46137Smao * Returns: 124*46137Smao * < 0 if p is < item at n 125*46137Smao * = 0 if p is = item at n 126*46137Smao * > 0 if p is > item at n 127*46137Smao */ 128*46137Smao 129*46137Smao int 130*46137Smao _bt_cmp(t, p, n) 131*46137Smao BTREE_P t; 132*46137Smao char *p; 133*46137Smao index_t n; 134*46137Smao { 135*46137Smao BTHEADER *h; 136*46137Smao IDATUM *id; 137*46137Smao DATUM *d; 138*46137Smao char *arg; 139*46137Smao int ignore; 140*46137Smao int free_arg; 141*46137Smao pgno_t chain; 142*46137Smao int r; 143*46137Smao 144*46137Smao h = t->bt_curpage; 145*46137Smao 146*46137Smao /* 147*46137Smao * The left-most key at any level of the tree on internal pages 148*46137Smao * is guaranteed (artificially, by the code here) to be less than 149*46137Smao * any user key. This saves us from having to update the leftmost 150*46137Smao * key when the user inserts a new key in the tree smaller than 151*46137Smao * anything we've seen yet. 152*46137Smao */ 153*46137Smao 154*46137Smao if (h->h_prevpg == P_NONE && !(h->h_flags & F_LEAF) && n == 0) 155*46137Smao return (1); 156*46137Smao 157*46137Smao if (h->h_flags & F_LEAF) { 158*46137Smao d = (DATUM *) GETDATUM(h,n); 159*46137Smao if (d->d_flags & D_BIGKEY) { 160*46137Smao free_arg = TRUE; 161*46137Smao bcopy(&(d->d_bytes[0]), (char *) &chain, sizeof(chain)); 162*46137Smao if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR) 163*46137Smao return (RET_ERROR); 164*46137Smao } else { 165*46137Smao free_arg = FALSE; 166*46137Smao arg = &(d->d_bytes[0]); 167*46137Smao } 168*46137Smao } else { 169*46137Smao id = (IDATUM *) GETDATUM(h,n); 170*46137Smao if (id->i_flags & D_BIGKEY) { 171*46137Smao free_arg = TRUE; 172*46137Smao bcopy(&(id->i_bytes[0]), 173*46137Smao (char *) &chain, 174*46137Smao sizeof(chain)); 175*46137Smao if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR) 176*46137Smao return (RET_ERROR); 177*46137Smao } else { 178*46137Smao free_arg = FALSE; 179*46137Smao arg = &(id->i_bytes[0]); 180*46137Smao } 181*46137Smao } 182*46137Smao r = (*(t->bt_compare))(p, arg); 183*46137Smao 184*46137Smao if (free_arg) 185*46137Smao (void) free(arg); 186*46137Smao 187*46137Smao return (r); 188*46137Smao } 189*46137Smao 190*46137Smao /* 191*46137Smao * _BT_PUSH/_BT_POP -- Push/pop a parent page number on the parent stack. 192*46137Smao * 193*46137Smao * When we descend the tree, we keep track of parent pages in order 194*46137Smao * to handle splits on insertions. 195*46137Smao * 196*46137Smao * Parameters: 197*46137Smao * t -- tree for which to push parent 198*46137Smao * pgno -- page number to push (_bt_push only) 199*46137Smao * 200*46137Smao * Returns: 201*46137Smao * RET_SUCCESS, RET_ERROR. 202*46137Smao */ 203*46137Smao 204*46137Smao int 205*46137Smao _bt_push(t, pgno) 206*46137Smao BTREE_P t; 207*46137Smao pgno_t pgno; 208*46137Smao { 209*46137Smao BTSTACK *new; 210*46137Smao 211*46137Smao if ((new = (BTSTACK *) malloc((unsigned) sizeof(BTSTACK))) 212*46137Smao == (BTSTACK *) NULL) 213*46137Smao return (RET_ERROR); 214*46137Smao new->bts_pgno = pgno; 215*46137Smao new->bts_next = t->bt_stack; 216*46137Smao t->bt_stack = new; 217*46137Smao 218*46137Smao return (RET_SUCCESS); 219*46137Smao } 220*46137Smao 221*46137Smao pgno_t 222*46137Smao _bt_pop(t) 223*46137Smao BTREE_P t; 224*46137Smao { 225*46137Smao BTSTACK *s; 226*46137Smao pgno_t p = P_NONE; 227*46137Smao 228*46137Smao if ((s = t->bt_stack) != (BTSTACK *) NULL) { 229*46137Smao p = s->bts_pgno; 230*46137Smao t->bt_stack = s->bts_next; 231*46137Smao (void) free ((char *) s); 232*46137Smao } 233*46137Smao return (p); 234*46137Smao } 235*46137Smao 236*46137Smao #ifdef DEBUG 237*46137Smao void 238*46137Smao _btdump(tree) 239*46137Smao BTREE tree; 240*46137Smao { 241*46137Smao BTREE_P t = (BTREE_P) tree; 242*46137Smao DATUM *d; 243*46137Smao IDATUM *id; 244*46137Smao BTHEADER *h; 245*46137Smao pgno_t npages; 246*46137Smao pgno_t i; 247*46137Smao index_t cur, top; 248*46137Smao 249*46137Smao npages = t->bt_npages; 250*46137Smao (void) printf("\"%s\" fd %d pgsz %d curpg %d @ 0x%lx", 251*46137Smao t->bt_fname, t->bt_s.bt_d.d_fd, 252*46137Smao t->bt_psize, t->bt_curpage); 253*46137Smao (void) printf("npg %d cmp 0x%lx flags=(", npages, t->bt_compare); 254*46137Smao if (t->bt_flags & BTF_SEQINIT) 255*46137Smao (void) printf("BTF_SEQINIT"); 256*46137Smao (void) printf(")\n"); 257*46137Smao 258*46137Smao for (i = P_ROOT; i <= npages; i++) { 259*46137Smao if (_bt_getpage(t, i) == RET_ERROR) 260*46137Smao _punt(); 261*46137Smao h = t->bt_curpage; 262*46137Smao top = NEXTINDEX(h); 263*46137Smao (void) printf(" page %d:\n", i); 264*46137Smao (void) printf("\tpgno %d prev %d next %d\n", 265*46137Smao h->h_pgno, h->h_prevpg, h->h_nextpg); 266*46137Smao (void) printf("\tlower %d upper %d nextind %d flags (", 267*46137Smao h->h_lower, h->h_upper, top); 268*46137Smao if (h->h_flags & F_LEAF) 269*46137Smao (void) printf("F_LEAF"); 270*46137Smao else 271*46137Smao (void) printf("<internal>"); 272*46137Smao if (h->h_flags & F_DIRTY) 273*46137Smao (void) printf("|F_DIRTY"); 274*46137Smao if (h->h_flags & F_PRESERVE) 275*46137Smao (void) printf("|F_PRESERVE"); 276*46137Smao if (h->h_flags & F_CONT) { 277*46137Smao (void) printf("|F_CONT)"); 278*46137Smao if (h->h_prevpg == P_NONE) { 279*46137Smao size_t longsz; 280*46137Smao (void) bcopy((char *) &(h->h_linp[0]), 281*46137Smao (char *) &longsz, 282*46137Smao sizeof(longsz)); 283*46137Smao printf("\n\t\t(chain start, data length %ld)", 284*46137Smao longsz); 285*46137Smao } 286*46137Smao printf("\n"); 287*46137Smao continue; 288*46137Smao } 289*46137Smao (void) printf(")\n"); 290*46137Smao for (cur = 0; cur < top; cur++) { 291*46137Smao (void) printf("\t [%d] off %d ", cur, h->h_linp[cur]); 292*46137Smao if (h->h_flags & F_LEAF) { 293*46137Smao d = (DATUM *) GETDATUM(h,cur); 294*46137Smao (void) printf("ksize %d", d->d_ksize); 295*46137Smao if (d->d_flags & D_BIGKEY) 296*46137Smao (void) printf(" (indirect)"); 297*46137Smao (void) printf("; dsize %d", d->d_dsize); 298*46137Smao if (d->d_flags & D_BIGDATA) 299*46137Smao (void) printf(" (indirect)"); 300*46137Smao } else { 301*46137Smao id = (IDATUM *) GETDATUM(h,cur); 302*46137Smao (void) printf("size %d pgno %d", 303*46137Smao id->i_size, id->i_pgno); 304*46137Smao if (id->i_flags & D_BIGKEY) 305*46137Smao (void) printf(" (indirect)"); 306*46137Smao } 307*46137Smao (void) printf("\n"); 308*46137Smao } 309*46137Smao (void) printf("\n"); 310*46137Smao } 311*46137Smao } 312*46137Smao #endif /* DEBUG */ 313*46137Smao 314*46137Smao #ifdef DEBUG 315*46137Smao _punt() 316*46137Smao { 317*46137Smao int pid; 318*46137Smao 319*46137Smao pid = getpid(); 320*46137Smao (void) kill(pid, SIGILL); 321*46137Smao } 322*46137Smao #endif /* DEBUG */ 323