|
|
1.1 ! root 1: #include <btree.h> ! 2: #include <ingres.h> ! 3: #include <opsys.h> ! 4: #include <sccs.h> ! 5: ! 6: SCCSID(@(#)btree_util.c 8.2 1/31/86) ! 7: ! 8: /* Trace up to the root of the BTree, incrementing (or decrementing) all ! 9: ** key values. ! 10: ** ! 11: ** Parameters : ! 12: ** tree - BTree filename (I) ! 13: ** block - starting node from which path is traced (I) ! 14: ** inc - either +1 or -1 (I) ! 15: */ ! 16: ! 17: tracepath(rootpage, block, inc) ! 18: ! 19: long rootpage; ! 20: register struct locator *block; ! 21: register int inc; ! 22: { ! 23: struct locator p, child; ! 24: ! 25: if (block->pageno != rootpage) /* if at root, no need for adjustment */ ! 26: { ! 27: bmove(block, &child, sizeof(struct locator)); ! 28: ! 29: /* trace up to root node */ ! 30: do ! 31: { ! 32: p.pageno = child.page.parent; ! 33: parentkey(child.pageno, &p); ! 34: p.page.node.intnode.key[p.offset] += inc; ! 35: write_node(p.pageno, &p.page); ! 36: bmove(&p, &child, sizeof(struct locator)); ! 37: } while (p.pageno != rootpage); ! 38: } ! 39: } ! 40: ! 41: /* Determines which key/ptr pair is the parent of the given page ! 42: ** ! 43: ** Parameters : ! 44: ** tree - BTree filename (I) ! 45: ** block - page number of child (I) ! 46: ** prt - information about the parent of the child (I, O) ! 47: ** ! 48: */ ! 49: ! 50: parentkey(block, prt) ! 51: ! 52: long block; ! 53: register struct locator *prt; ! 54: { ! 55: register int i; ! 56: ! 57: get_node(prt->pageno, &prt->page); ! 58: /* find pointer in parent which references desired block */ ! 59: for (i = 0; prt->page.node.intnode.ptr[i] != block && i < prt->page.nelmts; ++i) ! 60: continue; ! 61: ! 62: if (i == prt->page.nelmts) ! 63: syserr("parentkey: child = %ld", block); ! 64: prt->offset = i; ! 65: return(0); ! 66: } ! 67: ! 68: /* Retrieve a node from the BTree ! 69: ** ! 70: ** Parameters : ! 71: ** tree - BTree filename (I) ! 72: ** pagenum - page number of page to be retrieved (I) ! 73: ** buffer - buffer into which page is retrieved (O) ! 74: */ ! 75: ! 76: get_node(pagenum, buffer) ! 77: ! 78: long pagenum; ! 79: register struct BTreeNode *buffer; ! 80: { ! 81: extern int Btree_fd; ! 82: ! 83: if ( lseek(Btree_fd, pagenum * PGSIZE, 0) == -1 ) ! 84: syserr("GET_NODE: seek to %ld failed",pagenum); ! 85: if (read(Btree_fd, buffer, sizeof *buffer) != sizeof *buffer) ! 86: syserr("GET_NODE: read btree, page %ld", pagenum); ! 87: } ! 88: ! 89: /* Write a node into the BTree file name ! 90: ** ! 91: ** Parameters : ! 92: ** tree - BTree filename (I) ! 93: ** pagenum - page number of page to be written (I) ! 94: ** buffer - buffer containing page to be written (I) ! 95: */ ! 96: ! 97: write_node(pagenum, buffer) ! 98: ! 99: long pagenum; ! 100: register struct BTreeNode *buffer; ! 101: { ! 102: extern int Btree_fd; ! 103: ! 104: lseek(Btree_fd, pagenum * PGSIZE, 0); ! 105: if (write(Btree_fd, buffer, sizeof *buffer) != sizeof *buffer) ! 106: syserr("WRITE_NODE: write btree, page %ld", pagenum); ! 107: } ! 108: ! 109: /* Retrieves a new page from the BTree file. If there is an empty page ! 110: ** in the file, that page is used. Otherwise, a new page is added to ! 111: ** the end of the file. ! 112: ** ! 113: ** Parameters : ! 114: ** tree - BTree filename (I) ! 115: ** ! 116: ** Returns : ! 117: ** page number of new page ! 118: */ ! 119: ! 120: long ! 121: new_page(tree) ! 122: ! 123: char *tree; ! 124: { ! 125: int i; ! 126: long freepage, newpage; ! 127: struct BTreeNode page, root, garbage; ! 128: struct stat fileinfo; ! 129: extern DESC Btreesec; ! 130: ! 131: get_node(RT, &root); ! 132: freepage = root.parent; ! 133: if (freepage == 0) ! 134: /* no free pages in file, add a new page to the end */ ! 135: { ! 136: /* determine page number of page at very end of file */ ! 137: stat(tree, &fileinfo); ! 138: newpage = fileinfo.st_size / PGSIZE; ! 139: write_node(newpage, &page); ! 140: } ! 141: else ! 142: /* use first free page, adjusting free page chain */ ! 143: { ! 144: newpage = freepage; ! 145: get_node(newpage, &garbage); ! 146: root.parent = garbage.parent; ! 147: write_node(RT, &root); ! 148: } ! 149: return(newpage); ! 150: } ! 151: ! 152: /* Returns an empty file to the empty file list. The head of the list ! 153: ** is indicated through the parent of the root and linked together ! 154: ** through the parents of the empty pages. ! 155: ** ! 156: ** Parameters : ! 157: ** tree - BTree filename (I) ! 158: ** pagenum - page number of empty page (I) ! 159: */ ! 160: ! 161: return_page(pagenum) ! 162: ! 163: long pagenum; ! 164: { ! 165: struct BTreeNode root, freepage; ! 166: ! 167: /* indicate that page is free by inserting its page number at the ! 168: ** head of the free page list */ ! 169: get_node(RT, &root); ! 170: get_node(pagenum, &freepage); ! 171: freepage.parent = root.parent; ! 172: freepage.depth = 0; ! 173: write_node(pagenum, &freepage); ! 174: root.parent = pagenum; ! 175: write_node(RT, &root); ! 176: } ! 177: ! 178: /* ! 179: ** Determine the lid that corresponds to a given position in the B-Tree. ! 180: ** ! 181: ** Parameters : ! 182: ** tree - BTree name (I) ! 183: ** tidloc - location in BTree (I) ! 184: ** ! 185: ** Returns : ! 186: ** lid value ! 187: */ ! 188: get_lid(tidloc, lid) ! 189: ! 190: TID *tidloc; ! 191: long lid[]; ! 192: { ! 193: static struct locator tid; ! 194: register int i, j; ! 195: long l, child; ! 196: ! 197: do ! 198: { ! 199: /* determine where in BTree to search */ ! 200: pluck_page(tidloc, &tid.pageno); ! 201: ! 202: get_node(tid.pageno, (char *) &tid.page); ! 203: tid.offset = tid.page.node.leafnode.back_ptr[tidloc->line_id & I1MASK]; ! 204: ! 205: if (tid.offset > tid.page.nelmts - 1) ! 206: syserr("get_lid: bad tid location %ld, tid.offset=%d, tid.page.nelmts=%d", *tidloc, tid.offset,tid.page.nelmts); ! 207: ! 208: /* scan through leaf */ ! 209: for (l = 1, i = tid.offset; i > 0; ++l, --i) ! 210: continue; ! 211: /* trace up to root, adding keys */ ! 212: while (!tid.page.depth) ! 213: { ! 214: child = tid.pageno; ! 215: tid.pageno = tid.page.parent; ! 216: parentkey(child, &tid); ! 217: for (i = tid.offset - 1; i >= 0; l += tid.page.node.intnode.key[i--]) ! 218: continue; ! 219: } ! 220: lid[tid.page.depth - 1] = l; ! 221: # ifdef xATR1 ! 222: if (tTf(24,0)) ! 223: printf("lid=%ld\n", lid[tid.page.depth - 1]); ! 224: # endif ! 225: bmove(&tid.page.prttree, tidloc, LIDSIZE); ! 226: } while (tid.page.depth > 1); ! 227: } ! 228: ! 229: /* ! 230: ** Uses the secondary btree relation to find the btree tid corresponding ! 231: ** to a given main relation tid ! 232: */ ! 233: ! 234: search_btree(mtid, tidloc) ! 235: ! 236: TID mtid; ! 237: register TID *tidloc; ! 238: { ! 239: char key[2 * LIDSIZE], tup[2 * LIDSIZE]; ! 240: TID tid; ! 241: extern DESC Btreesec; ! 242: ! 243: # ifdef xATR1 ! 244: if (tTf(24,0)) ! 245: { ! 246: printf("In Search_btree: searching for tid %ld\n", mtid); ! 247: printdesc(&Btreesec); ! 248: } ! 249: # endif ! 250: clearkeys(&Btreesec); ! 251: setkey(&Btreesec, key, &mtid, 1); ! 252: if (!getequal(&Btreesec, key, tup, &tid)) ! 253: bmove(tup + LIDSIZE, tidloc, LIDSIZE); ! 254: else ! 255: syserr("search_btree:can't find mtid %ld in btree", mtid); ! 256: # ifdef xATR1 ! 257: if (tTf(24,0)) ! 258: printup(&Btreesec, tup); ! 259: # endif ! 260: } ! 261: ! 262: /* ! 263: ** Linearly searches the leaves of the BTree for a desired tid ! 264: ** ! 265: ** Parameters : ! 266: ** tree - BTree file name (I) ! 267: ** tid - desired tid value (I) ! 268: ** tidloc - location of the desired tid (O) ! 269: */ ! 270: ! 271: lin_search(level, tid, tidloc, lid, tupcnt) ! 272: ! 273: int level; ! 274: long tid; ! 275: TID *tidloc; ! 276: long lid[]; ! 277: long tupcnt; ! 278: { ! 279: struct locator block; ! 280: register int i; ! 281: long page, t, next; ! 282: int found; ! 283: long nextpage, count; ! 284: int forward, first; ! 285: ! 286: page = RT; ! 287: for (i = 0; i < level - 1; ++i) ! 288: { ! 289: t = get_tid(page, lid[i], &block); ! 290: page = t; ! 291: } ! 292: ! 293: found = 0; ! 294: forward = 0; ! 295: first = 1; ! 296: do ! 297: { ! 298: if (!forward) ! 299: { ! 300: get_node(page, &block.page); ! 301: next = block.page.nexttree; ! 302: } ! 303: count = 0; ! 304: ! 305: /* start at leftmost leaf */ ! 306: do ! 307: { ! 308: get_node(page, &block.page); ! 309: if (forward) ! 310: nextpage = block.page.nexttree; ! 311: else ! 312: nextpage = block.page.prevtree; ! 313: get_tid(page, 1, &block); ! 314: for ( ; ; ) ! 315: { ! 316: /* search through leaf */ ! 317: for (i = 0; i < block.page.nelmts && block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]] != tid; ++i) ! 318: { ! 319: if (!first) ! 320: ++count; ! 321: } ! 322: if (i < block.page.nelmts && block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]] == tid) ! 323: { ! 324: found = 1; ! 325: break; /* tid found */ ! 326: } ! 327: first = 0; ! 328: if (!(block.pageno = block.page.node.leafnode.nextleaf) || count >= tupcnt) ! 329: break; /* all leaves exhausted */ ! 330: else ! 331: /* try leaf to the right */ ! 332: get_node(block.pageno, &block.page); ! 333: } ! 334: if (found || count >= tupcnt) ! 335: break; ! 336: } while (page = nextpage); ! 337: nextpage = next; ! 338: forward = !forward; ! 339: } while (forward != 0 && !found); ! 340: if (!found) ! 341: syserr("search_btree: tid not found %ld", tid); ! 342: else ! 343: { ! 344: stuff_page(tidloc, &block.pageno); ! 345: tidloc->line_id = block.page.node.leafnode.tid_loc[i]; ! 346: } ! 347: } ! 348: ! 349: /* ! 350: ** Determines the value corresponding to the very last lid in the ! 351: ** BTree. ! 352: ** ! 353: ** Parameters : ! 354: ** tree - BTree file name (I) ! 355: ** ! 356: ** Returns : ! 357: ** value of last lid ! 358: */ ! 359: long ! 360: last_lid(rootpage) ! 361: ! 362: long rootpage; ! 363: ! 364: { ! 365: register int i; ! 366: long lid; ! 367: struct BTreeNode root; ! 368: ! 369: lid = 0; ! 370: get_node(rootpage, &root); ! 371: if (root.nodetype == 'L') ! 372: lid = root.nelmts; ! 373: else ! 374: for (i = 0; i < root.nelmts; ++i) ! 375: lid += root.node.intnode.key[i]; ! 376: ++lid; ! 377: return(lid); ! 378: } ! 379: ! 380: /* ! 381: ** Changes the tid value stored in the leaf of a BTree node ! 382: ** ! 383: ** Parameters : ! 384: ** tree - BTree file name (I) ! 385: ** tid - new tid value (I) ! 386: ** tidloc - location of tid to be replaced (I) ! 387: */ ! 388: ! 389: replace_btree(tid, tidloc) ! 390: ! 391: long tid; ! 392: register TID *tidloc; ! 393: ! 394: { ! 395: long pageno; ! 396: struct BTreeNode p; ! 397: ! 398: pluck_page(tidloc, &pageno); ! 399: get_node(pageno, &p); ! 400: p.node.leafnode.tid_pos[tidloc->line_id] = tid; ! 401: write_node(pageno, &p); ! 402: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.