|
|
1.1 ! root 1: # include <btree.h> ! 2: # include <ingres.h> ! 3: # include <batch.h> ! 4: # include <symbol.h> ! 5: # include <sccs.h> ! 6: ! 7: SCCSID(@(#)insert_btree.c 8.1 12/31/84) ! 8: ! 9: /* INSERT_BTREE -- BTree insertion routine ! 10: ** ! 11: ** Insert a tid into the BTree at the position corresponding to its lid. ! 12: ** Split the leaf if necessary and adjust all values up the tree. ! 13: ** ! 14: ** Parameters : ! 15: ** tree - BTree filename (I) ! 16: ** lid - given lid (I) ! 17: ** tid - tid to be inserted into BTree leaf (I) ! 18: ** tidpos - location where tid was inserted (O) ! 19: ** ! 20: ** Returns : ! 21: ** -1 lid position does not exist ! 22: ** 0 successful insertion ! 23: */ ! 24: ! 25: insert_btree(tree, rootpage, lid, tid, tidpos, create) ! 26: ! 27: char *tree; ! 28: long rootpage; ! 29: long lid; ! 30: long *tid; ! 31: register TID *tidpos; ! 32: char create; ! 33: { ! 34: register int i, j, start; ! 35: struct locator block, p; ! 36: struct BTreeNode newblock, temp, newroot; ! 37: short rblock, tline; ! 38: long newpage, tpage; ! 39: long get_tid(), new_page(); ! 40: int save; ! 41: char replbatch[MAXNAME + 4]; ! 42: FILE *fp; ! 43: TID oldtid, newtid; ! 44: long count, page, childpage; ! 45: extern char *Fileset; ! 46: extern DESC Btreesec; ! 47: ! 48: # ifdef xATR1 ! 49: if (tTf(24,0)) ! 50: printf("inserting lid %ld into btree at rootpage %d", lid, rootpage); ! 51: # endif ! 52: ! 53: /* find location of desired lid in B-Tree */ ! 54: if (get_tid(rootpage, lid, &block) < -1) ! 55: return(-1); ! 56: ! 57: if (newroot.depth = create) ! 58: { ! 59: if (save = block.offset) ! 60: newroot.prevtree = block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[save -1]]; ! 61: else ! 62: { ! 63: if (!block.page.prevtree) ! 64: newroot.prevtree = 0; ! 65: else ! 66: { ! 67: get_node(block.page.prevtree, &temp); ! 68: newroot.prevtree = temp.node.leafnode.tid_pos[temp.node.leafnode.tid_loc[temp.nelmts - 1]]; ! 69: } ! 70: } ! 71: if (save <= block.page.nelmts - 1 && block.page.nelmts) ! 72: newroot.nexttree = block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[save]]; ! 73: else ! 74: { ! 75: if (!block.page.nexttree) ! 76: newroot.nexttree = 0; ! 77: else ! 78: { ! 79: get_node(block.page.nexttree, &temp); ! 80: newroot.nexttree = temp.node.leafnode.tid_pos[temp.node.leafnode.tid_loc[0]]; ! 81: } ! 82: } ! 83: *tid = new_page(tree); ! 84: if (block.pageno == RT) ! 85: get_node(RT, &block.page); ! 86: if (newroot.prevtree) ! 87: { ! 88: get_node(newroot.prevtree, &temp); ! 89: temp.nexttree = *tid; ! 90: write_node(newroot.prevtree, &temp); ! 91: } ! 92: if (newroot.nexttree) ! 93: { ! 94: get_node(newroot.nexttree, &temp); ! 95: temp.prevtree = *tid; ! 96: write_node(newroot.nexttree, &temp); ! 97: } ! 98: stuff_page(&newroot.prttree, &block.pageno); ! 99: newroot.nodetype = 'L'; ! 100: newroot.nelmts = 0; ! 101: newroot.parent = 0; ! 102: newroot.node.leafnode.prevleaf = 0; ! 103: newroot.node.leafnode.nextleaf = 0; ! 104: for (i = 0; i < MAXLEAVES; ++i) ! 105: newroot.node.leafnode.tid_loc[i] = newroot.node.leafnode.back_ptr[i] = i; ! 106: } ! 107: ! 108: if (block.page.nelmts != MAXLEAVES) ! 109: /* insert tid into its proper position in leaf */ ! 110: { ! 111: save = block.page.node.leafnode.tid_loc[block.page.nelmts]; ! 112: /* move other tids down to make room for new tid */ ! 113: for (i = block.page.nelmts - 1; i >= block.offset; --i) ! 114: { ! 115: block.page.node.leafnode.tid_loc[i + 1] = ! 116: block.page.node.leafnode.tid_loc[i]; ! 117: block.page.node.leafnode.back_ptr[block.page.node.leafnode.tid_loc[i]] = i + 1; ! 118: } ! 119: block.page.node.leafnode.tid_loc[block.offset] = save; ! 120: block.page.node.leafnode.tid_pos[save] = *tid; ! 121: block.page.node.leafnode.back_ptr[save] = block.offset; ! 122: ++block.page.nelmts; ! 123: write_node(block.pageno, &block.page); ! 124: if (create) ! 125: newroot.prttree.line_id = save; ! 126: ! 127: /* trace up B-Tree, incrementing key values */ ! 128: tracepath(rootpage, &block, 1); ! 129: ! 130: tpage = block.pageno; ! 131: tline = save; ! 132: } ! 133: ! 134: else ! 135: /* leaf is full, must be split */ ! 136: { ! 137: /* determine where to split leaf */ ! 138: start = MAXLEAVES / 2; ! 139: rblock = 0; ! 140: ! 141: if (block.offset > start) ! 142: /* new tid will be inserted in the new leaf */ ! 143: { ! 144: ++start; ! 145: rblock = 1; ! 146: } ! 147: ! 148: /* readjust all values in the old leaf and assign them for ! 149: ** the new leaf */ ! 150: ! 151: block.page.nelmts = start; /* assume new tid will be ! 152: ** inserted into new leaf */ ! 153: newpage = new_page(tree); ! 154: newblock.nodetype = 'L'; ! 155: for (i = 0; i < MAXLEAVES; ++i) ! 156: newblock.node.leafnode.tid_loc[i] = newblock.node.leafnode.back_ptr[i] = i; ! 157: newblock.nelmts = MAXLEAVES + 1 - start; ! 158: newblock.parent = block.page.parent; ! 159: newblock.depth = 0; ! 160: ! 161: if (newblock.node.leafnode.nextleaf = block.page.node.leafnode.nextleaf) ! 162: { ! 163: get_node(newblock.node.leafnode.nextleaf, &temp); ! 164: temp.node.leafnode.prevleaf = newpage; ! 165: write_node(newblock.node.leafnode.nextleaf, &temp); ! 166: } ! 167: block.page.node.leafnode.nextleaf = newpage; ! 168: newblock.node.leafnode.prevleaf = block.pageno; ! 169: ! 170: /* create file for storing tids that must be replaced in btree ! 171: ** secondary relation ! 172: */ ! 173: if (!bequal("_SYS", tree, 4) && !create) ! 174: { ! 175: concat(REPL_IN, Fileset, replbatch); ! 176: if ((fp = fopen(replbatch, "w")) == NULL) ! 177: syserr("can't open batch file in insert_btree"); ! 178: count = 0; ! 179: stuff_page(&oldtid, &block.pageno); ! 180: stuff_page(&newtid, &newpage); ! 181: } ! 182: ! 183: /* copy the right half of the old leaf onto the new leaf */ ! 184: for (i = 0, j = start; j < MAXLEAVES || rblock == 1; ++i) ! 185: { ! 186: if (j == block.offset && rblock == 1) ! 187: /* current position in new leaf corresponds to position ! 188: ** of new tid */ ! 189: { ! 190: newblock.node.leafnode.tid_pos[newblock.node.leafnode.tid_loc[i]] = *tid; ! 191: tline = newblock.node.leafnode.tid_loc[i]; ! 192: /* indicate that tid has been inserted */ ! 193: rblock = -1; ! 194: } ! 195: else ! 196: { ! 197: childpage = newblock.node.leafnode.tid_pos[newblock.node.leafnode.tid_loc[i]] = ! 198: block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[j]]; ! 199: if (create) ! 200: { ! 201: get_node(childpage, &temp); ! 202: stuff_page(&temp.prttree, &newpage); ! 203: temp.prttree.line_id = newblock.node.leafnode.tid_loc[i]; ! 204: write_node(childpage, &temp); ! 205: } ! 206: if (!bequal("_SYS", tree, 4) && !create) ! 207: { ! 208: oldtid.line_id = block.page.node.leafnode.tid_loc[j]; ! 209: newtid.line_id = newblock.node.leafnode.tid_loc[i]; ! 210: if (fwrite(&oldtid, 1, LIDSIZE, fp) != LIDSIZE) ! 211: syserr("write error in insert_btree"); ! 212: if (fwrite(&newtid, 1, LIDSIZE, fp) != LIDSIZE) ! 213: syserr("write error in insert_btree"); ! 214: ++count; ! 215: } ! 216: ++j; ! 217: } ! 218: } ! 219: if (!bequal("_SYS", tree, 4) && !create) ! 220: { ! 221: fclose(fp); ! 222: repl_btree(replbatch, count); ! 223: } ! 224: ! 225: if (!rblock) ! 226: /* new tid belongs in old leaf, insert it into its proper ! 227: ** position */ ! 228: { ! 229: save = block.page.node.leafnode.tid_loc[block.page.nelmts]; ! 230: for (i = block.page.nelmts - 1; i >= block.offset; --i) ! 231: { ! 232: block.page.node.leafnode.tid_loc[i + 1] = ! 233: block.page.node.leafnode.tid_loc[i]; ! 234: block.page.node.leafnode.back_ptr[block.page.node.leafnode.tid_loc[i]] = i + 1; ! 235: } ! 236: block.page.node.leafnode.tid_loc[block.offset] = save; ! 237: block.page.node.leafnode.tid_pos[save] = *tid; ! 238: block.page.node.leafnode.back_ptr[save] = block.offset; ! 239: tline = save; ! 240: /* readjust element counts to reflect that tid has been ! 241: ** placed in the old leaf */ ! 242: ++block.page.nelmts; ! 243: --newblock.nelmts; ! 244: } ! 245: ! 246: if (block.pageno == rootpage) ! 247: { ! 248: /* split leaf was the root, a new level to the B-Tree ! 249: ** must be added */ ! 250: rootsplit(tree, rootpage, &block, newpage, block.page.nelmts, newblock.nelmts); ! 251: newblock.parent = rootpage; ! 252: write_node(block.pageno, &block.page); ! 253: newblock.node.leafnode.prevleaf = block.pageno; ! 254: write_node(newpage, &newblock); ! 255: ! 256: if (create) ! 257: { ! 258: for (i = 0; i < block.page.nelmts; ++ i) ! 259: { ! 260: get_node(block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]], &temp); ! 261: stuff_page(&temp.prttree, &block.pageno); ! 262: write_node(block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]], &temp); ! 263: } ! 264: } ! 265: /* btree page has changed */ ! 266: if (!bequal("_SYS", tree, 4) && !create) ! 267: { ! 268: concat(REPL_IN, Fileset, replbatch); ! 269: if ((fp = fopen(replbatch, "w")) == NULL) ! 270: syserr("can't open batch file in insert_btree"); ! 271: count = 0; ! 272: page = 0l; ! 273: stuff_page(&oldtid, &page); ! 274: stuff_page(&newtid, &block.pageno); ! 275: for (i = 0; i < block.page.nelmts; ++i) ! 276: { ! 277: if (rblock || block.page.node.leafnode.tid_loc[i] != tline) ! 278: { ! 279: oldtid.line_id = newtid.line_id = block.page.node.leafnode.tid_loc[i]; ! 280: if (fwrite(&oldtid, 1, LIDSIZE, fp) != LIDSIZE) ! 281: syserr("write error in insert_btree"); ! 282: if (fwrite(&newtid, 1, LIDSIZE, fp) != LIDSIZE) ! 283: syserr("write error in insert_btree"); ! 284: ++count; ! 285: } ! 286: } ! 287: fclose(fp); ! 288: repl_btree(replbatch, count); ! 289: } ! 290: } ! 291: else ! 292: /* insert the pointer and key associated with new leaf into the ! 293: ** parent of the old leaf */ ! 294: { ! 295: write_node(block.pageno, &block.page); ! 296: write_node(newpage, &newblock); ! 297: p.pageno = block.page.parent; ! 298: parentkey(block.pageno, &p); ! 299: p.page.node.intnode.key[p.offset] = block.page.nelmts; ! 300: insert_key(tree, rootpage, newpage, newblock.nelmts, &p); ! 301: } ! 302: tpage = (rblock) ? newpage : block.pageno; ! 303: } ! 304: stuff_page(tidpos, &tpage); ! 305: tidpos->line_id = tline; ! 306: ! 307: if (create) ! 308: write_node(*tid, &newroot); ! 309: ! 310: } ! 311: ! 312: /* ! 313: ** Takes a pair of tids from a file and sequentially replaces the ! 314: ** old tid with the new tid in the secondary btree relation ! 315: */ ! 316: ! 317: repl_btree(replbatch, count) ! 318: register char *replbatch; ! 319: long count; ! 320: { ! 321: register int i, j; ! 322: TID uptid; ! 323: DESC d; ! 324: char tids[2 * LIDSIZE], key[2 * LIDSIZE], newkey[2 * LIDSIZE]; ! 325: extern DESC Btreesec; ! 326: ! 327: if (count > 0) ! 328: { ! 329: /* set up descriptor for sort */ ! 330: d.reloff[1] = 0; ! 331: d.reloff[2] = LIDSIZE; ! 332: d.relfrmt[1] = d.relfrmt[2] = INT; ! 333: d.relfrml[1] = d.relfrml[2] = LIDSIZE; ! 334: d.relgiven[1] = 1; ! 335: d.relgiven[2] = 2; ! 336: d.reldum.relspec = M_ORDER; ! 337: d.reldum.relatts = 2; ! 338: d.reldum.relwid = 2 * LIDSIZE; ! 339: sortfile(replbatch, &d, FALSE); ! 340: if ((Repl_outfp = fopen(ztack(REPL_OUT, Fileset), "r")) == NULL) ! 341: syserr("can't open replace file after sort in insertbtreee\n"); ! 342: clearkeys(&Btreesec); ! 343: for (i = 0; i < count; ++i) ! 344: { ! 345: if (fread(tids, 1, 2 * LIDSIZE, Repl_outfp) != 2 * LIDSIZE) ! 346: syserr("read error in insert_btree"); ! 347: setkey(&Btreesec, key, tids, 2); ! 348: if (getequal(&Btreesec, key, newkey, &uptid)) ! 349: { ! 350: printup(&Btreesec, key); ! 351: syserr("getequal error in insert_btree"); ! 352: } ! 353: /* place new tid in place */ ! 354: setkey(&Btreesec, newkey, tids + LIDSIZE, 2); ! 355: if (j = replace(&Btreesec, &uptid, newkey, TRUE)) ! 356: if (j == 1) ! 357: continue; ! 358: else ! 359: syserr("bad replace in insert_btree"); ! 360: } ! 361: fclose(Repl_outfp); ! 362: unlink(replbatch); ! 363: unlink(ztack(REPL_OUT, Fileset)); ! 364: } ! 365: } ! 366: ! 367: /* Insert a key/ptr pair into a node, splitting nodes if necessary and ! 368: ** adjusting values up the tree. ! 369: ** ! 370: ** Parameters : ! 371: ** tree - BTree filename (I) ! 372: ** p - page number of newly formed node (I) ! 373: ** k - key value of newly formed node (I) ! 374: ** pkey - information about the node whose ptr/key pair is to ! 375: ** be inserted (I, O) ! 376: */ ! 377: ! 378: insert_key(tree, rootpage, p, k, pkey) ! 379: ! 380: char *tree; ! 381: long rootpage; ! 382: long p, k; ! 383: register struct locator *pkey; ! 384: { ! 385: register int i, j, start; ! 386: struct BTreeNode newblock, temp; ! 387: long newpage, oldkey, newkey; ! 388: struct locator prt; ! 389: short rblock; ! 390: long new_page(); ! 391: ! 392: if (pkey->page.nelmts != MAXPTRS) ! 393: /* insert pointer/key pair into proper position in node by moving ! 394: ** other pairs down node */ ! 395: { ! 396: for (i = pkey->page.nelmts - 1; i >= pkey->offset + 1; --i) ! 397: { ! 398: pkey->page.node.intnode.ptr[i + 1] = ! 399: pkey->page.node.intnode.ptr[i]; ! 400: pkey->page.node.intnode.key[i + 1] = ! 401: pkey->page.node.intnode.key[i]; ! 402: } ! 403: ++pkey->page.nelmts; ! 404: pkey->page.node.intnode.ptr[pkey->offset + 1] = p; ! 405: pkey->page.node.intnode.key[pkey->offset + 1] = k; ! 406: ! 407: write_node(pkey->pageno, &pkey->page); ! 408: ! 409: /* trace up B-Tree incrementing keys */ ! 410: tracepath(rootpage, pkey, 1); ! 411: } ! 412: ! 413: else ! 414: /* node is full, must be split */ ! 415: { ! 416: /* determine where split will be made */ ! 417: start = MAXPTRS / 2; ! 418: rblock = 0; ! 419: ! 420: if (pkey->offset + 1 > start) ! 421: /* ptr/key pair will be inserted in new node */ ! 422: { ! 423: ++start; ! 424: rblock = 1; ! 425: } ! 426: ! 427: /* readjust old node values and create new node values */ ! 428: pkey->page.nelmts = start; ! 429: newpage = new_page(tree); ! 430: newblock.nodetype = 'I'; ! 431: newblock.nelmts = MAXPTRS + 1 - start; ! 432: newblock.parent = pkey->page.parent; ! 433: newblock.depth = 0; ! 434: ! 435: /* copy right side of old node into new node */ ! 436: ! 437: for (i = 0, j = start; j < MAXPTRS || rblock == 1; ++i) ! 438: { ! 439: if (j == pkey->offset + 1 && rblock == 1) ! 440: /* node position corresponds to that of new ptr/key pair */ ! 441: { ! 442: newblock.node.intnode.ptr[i] = p; ! 443: newblock.node.intnode.key[i] = k; ! 444: /* make sure children of newblock have proper ! 445: ** parent */ ! 446: get_node(p, &temp); ! 447: temp.parent = newpage; ! 448: write_node(p, &temp); ! 449: ! 450: rblock = -1; ! 451: } ! 452: else ! 453: { ! 454: newblock.node.intnode.ptr[i] = ! 455: pkey->page.node.intnode.ptr[j]; ! 456: newblock.node.intnode.key[i] = ! 457: pkey->page.node.intnode.key[j]; ! 458: /* make sure children of newblock have proper ! 459: ** parent */ ! 460: get_node(newblock.node.intnode.ptr[i], &temp); ! 461: temp.parent = newpage; ! 462: write_node(newblock.node.intnode.ptr[i], &temp); ! 463: ++j; ! 464: } ! 465: } ! 466: ! 467: if (!rblock) ! 468: /* insert new ptr/key pair into proper position in old node */ ! 469: { ! 470: for (i = pkey->page.nelmts - 1; i >= pkey->offset + 1; --i) ! 471: { ! 472: pkey->page.node.intnode.ptr[i + 1] = ! 473: pkey->page.node.intnode.ptr[i]; ! 474: pkey->page.node.intnode.key[i + 1] = ! 475: pkey->page.node.intnode.key[i]; ! 476: } ! 477: pkey->page.node.intnode.ptr[pkey->offset + 1] = p; ! 478: pkey->page.node.intnode.key[pkey->offset + 1] = k; ! 479: ++pkey->page.nelmts; ! 480: --newblock.nelmts; ! 481: } ! 482: ! 483: /* calculate the key values of the old and new nodes */ ! 484: oldkey = 0; ! 485: for (i = 0; i < pkey->page.nelmts; ++i) ! 486: oldkey += pkey->page.node.intnode.key[i]; ! 487: newkey = 0; ! 488: for (i = 0; i < newblock.nelmts; ++i) ! 489: newkey += newblock.node.intnode.key[i]; ! 490: ! 491: if (pkey->pageno == rootpage) ! 492: { ! 493: /* split node was root, add a new level to B-Tree */ ! 494: rootsplit(tree, rootpage, pkey, newpage, oldkey, newkey); ! 495: newblock.parent = rootpage; ! 496: write_node(pkey->pageno, &pkey->page); ! 497: write_node(newpage, &newblock); ! 498: } ! 499: ! 500: else ! 501: /* recursively add ptr/key pair corresponding to new node into ! 502: ** the parent of the old node */ ! 503: { ! 504: write_node(pkey->pageno, &pkey->page); ! 505: write_node(newpage, &newblock); ! 506: prt.pageno = pkey->page.parent; ! 507: parentkey(pkey->pageno, &prt); ! 508: prt.page.node.intnode.key[prt.offset] = oldkey; ! 509: insert_key(tree, rootpage, newpage, newkey, &prt); ! 510: } ! 511: } ! 512: } ! 513: ! 514: /* Form a new root with two children since the old root was split. ! 515: ** ! 516: ** Parameters : ! 517: ** tree - BTree filename (I) ! 518: ** oldroot - split root (I, O) ! 519: ** rpageno - page number of new root's right child (I) ! 520: ** rkey - key of new root's right child (I) ! 521: */ ! 522: ! 523: rootsplit(tree, rootpage, oldroot, rpageno, lkey, rkey) ! 524: ! 525: char *tree; ! 526: long rootpage; ! 527: register struct locator *oldroot; ! 528: long rpageno, lkey, rkey; ! 529: { ! 530: struct BTreeNode newroot, temp; ! 531: long i; ! 532: ! 533: /* get a new page for the former root */ ! 534: oldroot->pageno = new_page(tree); ! 535: ! 536: newroot.depth = oldroot->page.depth; ! 537: newroot.prevtree = oldroot->page.prevtree; ! 538: newroot.nexttree = oldroot->page.nexttree; ! 539: bmove(&oldroot->page.prttree, &newroot.prttree, LIDSIZE); ! 540: newroot.nodetype = 'I'; ! 541: newroot.nelmts = 2; ! 542: newroot.parent = oldroot->page.parent; ! 543: oldroot->page.parent = rootpage; ! 544: oldroot->page.depth = 0; ! 545: newroot.node.intnode.key[0] = lkey; ! 546: newroot.node.intnode.ptr[0] = oldroot->pageno; ! 547: newroot.node.intnode.key[1] = rkey; ! 548: newroot.node.intnode.ptr[1] = rpageno; ! 549: ! 550: write_node(rootpage, &newroot); ! 551: ! 552: if (oldroot->page.nodetype == 'I') ! 553: /* make sure the children of the oldroot have the correct parent */ ! 554: for (i = 0; i < oldroot->page.nelmts; ++i) ! 555: { ! 556: get_node(oldroot->page.node.intnode.ptr[i], &temp); ! 557: temp.parent = oldroot->pageno; ! 558: write_node(oldroot->page.node.intnode.ptr[i], &temp); ! 559: } ! 560: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.