# # include SCCSID(@(#)bndxsearch.c 8.1 12/31/84) /* ** BNDXSEARCH -- search an BTREE directory ** ** Looks for an available page, if this would force out a page from ** the relation it adds its own. Searches each level of the dirctory ** for the lowest (highest) page on which the key could occur if mode ** is < (>) 0. At each level the number of keys on the page is checked ** if it is <= SEARCHFUDGE a linear sharch is done, otherwize a binary ** search is preformed. If the full key matches exactly the seach ** can stop. Note that the keys tell the minimum value on that page. ** ** Parameters: ** d - pointer to descriptor of open relation ** tid - returns tid of page to start (end) looking ** key - to look for ** mode - < 0 lowkey, > 0 hikey ** keyok - true if all keys are assumed to be set ** path - if non-null, is set to the tids of the access path ** ** Returns: ** -2 - pageflush failure ** -1 - get_page failure ** 0 - success ** ** Side Effects: ** causes I/O ** ** Requires: ** getpage, icompare, paramd, pageflush, top_acc, resetacc, etc. ** ** Called By: ** find ** ** History: ** Stolen from ndxsearch 7/26/80 (jiw) */ # include # include # include # include # include # define SEARCHFUDGE 6 /* # of linenos to do a binary search */ bndxsearch(d, tidx, tuple, mode, keyok, path) struct descriptor *d; struct tup_id *tidx; char tuple[]; int mode; int keyok; struct tup_id *path; { register struct tup_id *tid; register int i; long pageid; int j, keylen, dno, partialkey; char *p; int pagerr; struct accessparam relparm; int top; register bottom; extern char *get_addr(); tid = tidx; pagerr = 0; paramd(d, &relparm); /* get domains in key order */ /* assume fullkey is given */ partialkey = FALSE; /* remove any key domains not given by the user */ if (!keyok) { for (i = 0; dno = relparm.keydno[i]; i++) { if (d->relgiven[dno]) continue; relparm.keydno[i] = 0; partialkey = TRUE; printf("partial key true\n"); break; } } /* if the first key isn't given, just return else search directory */ if (relparm.keydno[0] != 0) { /* The actual BTREE directory search must be performed */ pageid = 0; /* BTREE root is page 0 */ stuff_page(tid, &pageid); Acclock = FALSE; do { if (path) { bmove(tid, path++, sizeof(struct tup_id)); } if (pagerr = get_page(d, tid)) break; /* fatal error */ Acc_head->bufstatus |= BUF_DIRECT; /* don't get confused */ bottom = -1; top = Acc_head->nxtlino - 1; if (top >= SEARCHFUDGE) /* we are past breakeven */ { printf("doing binary search\n"); while (top != bottom) /* binary search */ { tid->line_id = ((1 + top - bottom) >> 1) + bottom; /* get to half way point */ p = get_addr(tid) + PGPTRSIZ; for (j = 0; dno = relparm.keydno[j]; j++) { keylen = d->relfrml[dno] & I1MASK; printf("data: "); printatt(d->relfrmt[dno], keylen, p); printf("| compared with: "); printatt(d->relfrmt[dno], keylen, &tuple[d->reloff[dno]]); printf("|\n"); if (i = icompare(&tuple[d->reloff[dno]], p, d->relfrmt[dno], keylen)) break; p += keylen; } /* if key is below directory, then we are in the bottom half */ printf("i = %d, mode %d, partialkey %d, top %d, bottom %d\n", i, mode, partialkey, top, bottom); if (i < 0 || (i == 0 && partialkey && mode < 0)) top = tid->line_id - 1; else if (i == 0 && !partialkey) { bottom = tid->line_id; break; } else bottom = tid->line_id; } } else /* do a linear search */ { printf("doing linear search\n"); for (tid->line_id = 0; (tid->line_id & I1MASK) < Acc_head->nxtlino; tid->line_id++) { printf("inside loop: tid\n"); dumptid(tid); p = get_addr(tid) + PGPTRSIZ; for (i = 0; dno = relparm.keydno[i]; i++) { keylen = d->relfrml[dno] & I1MASK; printf("data: "); printatt(d->relfrmt[dno], keylen, p); printf("| compared with: "); printatt(d->relfrmt[dno], keylen, &tuple[d->reloff[dno]]); printf("|\n"); if (j = icompare(&tuple[d->reloff[dno]], p, d->relfrmt[dno], keylen)) break; printf("after break in tuple comp\n"); p += keylen; } /* if key is below directory, then we have passed the position */ printf("j = %d, mode %d, partialkey %d\n", j, mode, partialkey); if (j < 0) break; /* if lowkey search on partial key matches, then done */ if (j == 0 && partialkey && mode < 0) break; if (j == 0 && mode < 0) { break; } } } if (bottom < 0) p = Acc_head->firstup; else { tid->line_id = bottom; p = get_addr(tid); } printf("result: "); dumptid(tid); bmove(p, tid, PGPTRSIZ); printf("and next tid: "); dumptid(tid); } while (Acc_head->mainpg); /* if at level zero then done */ Acclock = TRUE; } tid->line_id = -1; if (path) { bmove(tid, path++, sizeof(struct tup_id)); path->line_id = -2; /* impossible value */ } printf("final: "); dumptid(tid); return (pagerr); }