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: }

Defined functions

insert_btree defined in line 7; used 2 times
insert_key defined in line 378; used 2 times
repl_btree defined in line 317; used 3 times
rootsplit defined in line 523; used 2 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1494
Valid CSS Valid XHTML 1.0 Strict