146137Smao /*- 246137Smao * Copyright (c) 1990 The Regents of the University of California. 346137Smao * All rights reserved. 446137Smao * 546137Smao * This code is derived from software contributed to Berkeley by 646137Smao * Mike Olson. 746137Smao * 846137Smao * %sccs.include.redist.c% 946137Smao */ 1046137Smao 1146137Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46561Sbostic static char sccsid[] = "@(#)bt_utils.c 5.2 (Berkeley) 02/22/91"; 1346137Smao #endif /* LIBC_SCCS and not lint */ 1446137Smao 1546137Smao #include <sys/types.h> 1646137Smao #include <db.h> 17*46561Sbostic #include <stdlib.h> 18*46561Sbostic #include <string.h> 1946137Smao #include "btree.h" 2046137Smao 2146137Smao /* 2246137Smao * _BT_BUILDRET -- Build return key/data pair as a result of search or scan. 2346137Smao * 2446137Smao * This routine manages the statically allocated buffers in which we 2546137Smao * return data to the user. 2646137Smao * 2746137Smao * Parameters: 2846137Smao * t -- btree from which to return datum 2946137Smao * d -- DATUM to be returned to the user. 3046137Smao * data -- data argument supplied by user for return 3146137Smao * key -- key argument supplied by user for return 3246137Smao * 3346137Smao * Returns: 3446137Smao * RET_SUCCESS, RET_ERROR. 3546137Smao * 3646137Smao * Side Effects: 3746137Smao * May free and reallocate static buffers, if the data 3846137Smao * we want to return is bigger than the space we have to 3946137Smao * do so. 4046137Smao */ 4146137Smao 4246137Smao int 4346137Smao _bt_buildret(t, d, data, key) 4446137Smao BTREE_P t; 4546137Smao DATUM *d; 4646137Smao DBT *data; 4746137Smao DBT *key; 4846137Smao { 4946137Smao static int _data_s = 0; 5046137Smao static int _key_s = 0; 5146137Smao static char *_data = (char *) NULL; 5246137Smao static char *_key = (char *) NULL; 5346137Smao pgno_t chain; 5446137Smao 5546137Smao if (d->d_flags & D_BIGKEY) { 5646137Smao if (_key != (char *) NULL) 5746137Smao (void) free(_key); 5846137Smao (void) bcopy((char *) &(d->d_bytes[0]), 5946137Smao (char *) &chain, 6046137Smao sizeof(chain)); 6146137Smao if (_bt_getbig(t, chain, &_key, &_key_s) == RET_ERROR) 6246137Smao return (RET_ERROR); 6346137Smao key->data = _key; 6446137Smao key->size = _key_s; 6546137Smao } else { 6646137Smao /* need more space for key? */ 6746137Smao if (d->d_ksize > _key_s) { 6846137Smao if (_key != (char *) NULL) 6946137Smao (void) free (_key); 7046137Smao if ((_key = (char *) malloc((unsigned) d->d_ksize)) 7146137Smao == (char *) NULL) 7246137Smao return (RET_ERROR); 7346137Smao _key_s = d->d_ksize; 7446137Smao } 7546137Smao 7646137Smao key->data = _key; 7746137Smao if ((key->size = d->d_ksize) > 0) 7846137Smao (void) bcopy(&(d->d_bytes[0]), 7946137Smao _key, 8046137Smao (int) d->d_ksize); 8146137Smao } 8246137Smao 8346137Smao if (d->d_flags & D_BIGDATA) { 8446137Smao if (_data != (char *) NULL) 8546137Smao (void) free(_data); 8646137Smao (void) bcopy(&(d->d_bytes[d->d_ksize]), 8746137Smao (char *) &chain, 8846137Smao sizeof(chain)); 8946137Smao if (_bt_getbig(t, chain, &_data, &_data_s) == RET_ERROR) 9046137Smao return (RET_ERROR); 9146137Smao data->data = _data; 9246137Smao data->size = _data_s; 9346137Smao } else { 9446137Smao /* need more space for data? */ 9546137Smao if (d->d_dsize > _data_s) { 9646137Smao if (_data != (char *) NULL) 9746137Smao (void) free (_data); 9846137Smao if ((_data = (char *) malloc((unsigned) d->d_dsize)) 9946137Smao == (char *) NULL) 10046137Smao return (RET_ERROR); 10146137Smao _data_s = d->d_dsize; 10246137Smao } 10346137Smao 10446137Smao data->data = _data; 10546137Smao 10646137Smao if ((data->size = d->d_dsize) > 0) 10746137Smao (void) bcopy(&(d->d_bytes[d->d_ksize]), 10846137Smao _data, 10946137Smao (size_t) (d->d_dsize)); 11046137Smao } 11146137Smao 11246137Smao return (RET_SUCCESS); 11346137Smao } 11446137Smao 11546137Smao /* 11646137Smao * _BT_CMP -- Compare a key to a given item on the current page. 11746137Smao * 11846137Smao * This routine is a wrapper for the user's comparison function. 11946137Smao * 12046137Smao * Parameters: 12146137Smao * t -- tree in which to do comparison 12246137Smao * p -- pointer to one argument for the comparison function 12346137Smao * n -- index of item to supply second arg to comparison function 12446137Smao * 12546137Smao * Returns: 12646137Smao * < 0 if p is < item at n 12746137Smao * = 0 if p is = item at n 12846137Smao * > 0 if p is > item at n 12946137Smao */ 13046137Smao 13146137Smao int 13246137Smao _bt_cmp(t, p, n) 13346137Smao BTREE_P t; 13446137Smao char *p; 13546137Smao index_t n; 13646137Smao { 13746137Smao BTHEADER *h; 13846137Smao IDATUM *id; 13946137Smao DATUM *d; 14046137Smao char *arg; 14146137Smao int ignore; 14246137Smao int free_arg; 14346137Smao pgno_t chain; 14446137Smao int r; 14546137Smao 14646137Smao h = t->bt_curpage; 14746137Smao 14846137Smao /* 14946137Smao * The left-most key at any level of the tree on internal pages 15046137Smao * is guaranteed (artificially, by the code here) to be less than 15146137Smao * any user key. This saves us from having to update the leftmost 15246137Smao * key when the user inserts a new key in the tree smaller than 15346137Smao * anything we've seen yet. 15446137Smao */ 15546137Smao 15646137Smao if (h->h_prevpg == P_NONE && !(h->h_flags & F_LEAF) && n == 0) 15746137Smao return (1); 15846137Smao 15946137Smao if (h->h_flags & F_LEAF) { 16046137Smao d = (DATUM *) GETDATUM(h,n); 16146137Smao if (d->d_flags & D_BIGKEY) { 16246137Smao free_arg = TRUE; 16346137Smao bcopy(&(d->d_bytes[0]), (char *) &chain, sizeof(chain)); 16446137Smao if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR) 16546137Smao return (RET_ERROR); 16646137Smao } else { 16746137Smao free_arg = FALSE; 16846137Smao arg = &(d->d_bytes[0]); 16946137Smao } 17046137Smao } else { 17146137Smao id = (IDATUM *) GETDATUM(h,n); 17246137Smao if (id->i_flags & D_BIGKEY) { 17346137Smao free_arg = TRUE; 17446137Smao bcopy(&(id->i_bytes[0]), 17546137Smao (char *) &chain, 17646137Smao sizeof(chain)); 17746137Smao if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR) 17846137Smao return (RET_ERROR); 17946137Smao } else { 18046137Smao free_arg = FALSE; 18146137Smao arg = &(id->i_bytes[0]); 18246137Smao } 18346137Smao } 18446137Smao r = (*(t->bt_compare))(p, arg); 18546137Smao 18646137Smao if (free_arg) 18746137Smao (void) free(arg); 18846137Smao 18946137Smao return (r); 19046137Smao } 19146137Smao 19246137Smao /* 19346137Smao * _BT_PUSH/_BT_POP -- Push/pop a parent page number on the parent stack. 19446137Smao * 19546137Smao * When we descend the tree, we keep track of parent pages in order 19646137Smao * to handle splits on insertions. 19746137Smao * 19846137Smao * Parameters: 19946137Smao * t -- tree for which to push parent 20046137Smao * pgno -- page number to push (_bt_push only) 20146137Smao * 20246137Smao * Returns: 20346137Smao * RET_SUCCESS, RET_ERROR. 20446137Smao */ 20546137Smao 20646137Smao int 20746137Smao _bt_push(t, pgno) 20846137Smao BTREE_P t; 20946137Smao pgno_t pgno; 21046137Smao { 21146137Smao BTSTACK *new; 21246137Smao 21346137Smao if ((new = (BTSTACK *) malloc((unsigned) sizeof(BTSTACK))) 21446137Smao == (BTSTACK *) NULL) 21546137Smao return (RET_ERROR); 21646137Smao new->bts_pgno = pgno; 21746137Smao new->bts_next = t->bt_stack; 21846137Smao t->bt_stack = new; 21946137Smao 22046137Smao return (RET_SUCCESS); 22146137Smao } 22246137Smao 22346137Smao pgno_t 22446137Smao _bt_pop(t) 22546137Smao BTREE_P t; 22646137Smao { 22746137Smao BTSTACK *s; 22846137Smao pgno_t p = P_NONE; 22946137Smao 23046137Smao if ((s = t->bt_stack) != (BTSTACK *) NULL) { 23146137Smao p = s->bts_pgno; 23246137Smao t->bt_stack = s->bts_next; 23346137Smao (void) free ((char *) s); 23446137Smao } 23546137Smao return (p); 23646137Smao } 23746137Smao 23846137Smao #ifdef DEBUG 23946137Smao void 24046137Smao _btdump(tree) 24146137Smao BTREE tree; 24246137Smao { 24346137Smao BTREE_P t = (BTREE_P) tree; 24446137Smao DATUM *d; 24546137Smao IDATUM *id; 24646137Smao BTHEADER *h; 24746137Smao pgno_t npages; 24846137Smao pgno_t i; 24946137Smao index_t cur, top; 25046137Smao 25146137Smao npages = t->bt_npages; 25246137Smao (void) printf("\"%s\" fd %d pgsz %d curpg %d @ 0x%lx", 25346137Smao t->bt_fname, t->bt_s.bt_d.d_fd, 25446137Smao t->bt_psize, t->bt_curpage); 25546137Smao (void) printf("npg %d cmp 0x%lx flags=(", npages, t->bt_compare); 25646137Smao if (t->bt_flags & BTF_SEQINIT) 25746137Smao (void) printf("BTF_SEQINIT"); 25846137Smao (void) printf(")\n"); 25946137Smao 26046137Smao for (i = P_ROOT; i <= npages; i++) { 26146137Smao if (_bt_getpage(t, i) == RET_ERROR) 26246137Smao _punt(); 26346137Smao h = t->bt_curpage; 26446137Smao top = NEXTINDEX(h); 26546137Smao (void) printf(" page %d:\n", i); 26646137Smao (void) printf("\tpgno %d prev %d next %d\n", 26746137Smao h->h_pgno, h->h_prevpg, h->h_nextpg); 26846137Smao (void) printf("\tlower %d upper %d nextind %d flags (", 26946137Smao h->h_lower, h->h_upper, top); 27046137Smao if (h->h_flags & F_LEAF) 27146137Smao (void) printf("F_LEAF"); 27246137Smao else 27346137Smao (void) printf("<internal>"); 27446137Smao if (h->h_flags & F_DIRTY) 27546137Smao (void) printf("|F_DIRTY"); 27646137Smao if (h->h_flags & F_PRESERVE) 27746137Smao (void) printf("|F_PRESERVE"); 27846137Smao if (h->h_flags & F_CONT) { 27946137Smao (void) printf("|F_CONT)"); 28046137Smao if (h->h_prevpg == P_NONE) { 28146137Smao size_t longsz; 28246137Smao (void) bcopy((char *) &(h->h_linp[0]), 28346137Smao (char *) &longsz, 28446137Smao sizeof(longsz)); 28546137Smao printf("\n\t\t(chain start, data length %ld)", 28646137Smao longsz); 28746137Smao } 28846137Smao printf("\n"); 28946137Smao continue; 29046137Smao } 29146137Smao (void) printf(")\n"); 29246137Smao for (cur = 0; cur < top; cur++) { 29346137Smao (void) printf("\t [%d] off %d ", cur, h->h_linp[cur]); 29446137Smao if (h->h_flags & F_LEAF) { 29546137Smao d = (DATUM *) GETDATUM(h,cur); 29646137Smao (void) printf("ksize %d", d->d_ksize); 29746137Smao if (d->d_flags & D_BIGKEY) 29846137Smao (void) printf(" (indirect)"); 29946137Smao (void) printf("; dsize %d", d->d_dsize); 30046137Smao if (d->d_flags & D_BIGDATA) 30146137Smao (void) printf(" (indirect)"); 30246137Smao } else { 30346137Smao id = (IDATUM *) GETDATUM(h,cur); 30446137Smao (void) printf("size %d pgno %d", 30546137Smao id->i_size, id->i_pgno); 30646137Smao if (id->i_flags & D_BIGKEY) 30746137Smao (void) printf(" (indirect)"); 30846137Smao } 30946137Smao (void) printf("\n"); 31046137Smao } 31146137Smao (void) printf("\n"); 31246137Smao } 31346137Smao } 31446137Smao #endif /* DEBUG */ 31546137Smao 31646137Smao #ifdef DEBUG 31746137Smao _punt() 31846137Smao { 31946137Smao int pid; 32046137Smao 32146137Smao pid = getpid(); 32246137Smao (void) kill(pid, SIGILL); 32346137Smao } 32446137Smao #endif /* DEBUG */ 325