|
|
1.1 root 1: # include <stdio.h>
2: # include <btree.h>
3: # include <ingres.h>
4: # include <batch.h>
5: # include <sccs.h>
6:
7: SCCSID(@(#)delete_btree.c 8.1 12/31/84)
8:
9: /* DELETE_BTREE -- BTree deletion routine
10: **
11: ** Deletes a tid from a leaf node and adjusts all values up the tree
12: **
13: ** Parameters :
14: ** tree - BTree filename (I)
15: ** lid - lid to be deleted (I)
16: **
17: ** Returns :
18: ** > 0 success
19: ** < 0 bad lid
20: */
21:
22: delete_btree(lid, level)
23: long lid[];
24: register int level;
25:
26: {
27: register int i, j;
28: struct locator tid[MAXLID];
29: register int save;
30: int num[MAXLID];
31: int del[MAXLID];
32: long page[MAXLID + 1], t;
33: struct BTreeNode temp;
34:
35: # ifdef xATR1
36: if(tTf(24,0))
37: printf("deleting lid %ld from tree ", lid);
38: # endif
39:
40: page[0] = RT;
41: for (i = 0; i < level; ++i)
42: {
43: if ((t = get_tid(page[i], lid[i], &tid[i])) < 0)
44: return(-1);
45: del[i] = 0;
46: num[i] = tid[i].page.nelmts;
47: page[i+1] = t;
48: }
49:
50: del[level-1] = 1;
51: for (i = level - 2; i >= 0; --i)
52: {
53: if (num[i + 1] == 1 && del[i + 1] == 1)
54: del[i] = 1;
55: }
56:
57: for (i = 0; i < level; ++i)
58: {
59: if (del[i])
60: {
61: ++Repl_cnt[i];
62: for (j = i - 1; j >= 0; --j)
63: Prev_lid[j] = lid[j];
64: /* remove tid from leaf */
65: if (tid[i].offset != tid[i].page.nelmts - 1)
66: {
67: save = tid[i].page.node.leafnode.tid_loc[tid[i].offset];
68: for (j = tid[i].offset; j < tid[i].page.nelmts; ++j)
69: {
70: tid[i].page.node.leafnode.tid_loc[j] =
71: tid[i].page.node.leafnode.tid_loc[j + 1];
72: tid[i].page.node.leafnode.back_ptr[tid[i].page.node.leafnode.tid_loc[j]] = j;
73: }
74: tid[i].page.node.leafnode.tid_loc[tid[i].page.nelmts - 1] = save;
75: tid[i].page.node.leafnode.back_ptr[save] = tid[i].page.nelmts - 1;
76: }
77: --tid[i].page.nelmts;
78:
79: if (tid[i].page.nelmts != 0)
80: {
81: write_node(tid[i].pageno, &tid[i].page);
82: /* leaf is now empty as a result of deletion, decrement keys
83: ** up tree */
84: tracepath(page[i], &tid[i], -1);
85: }
86:
87: else if (tid[i].pageno != page[i])
88: {
89: /* key/ptr pair corresponding to empty leaf must be removed */
90: delete_key(page[i], &tid[i]);
91: }
92: else if (lid[i] == 1 && page[i] != RT)
93: {
94: if (tid[i].page.prevtree)
95: {
96: get_node(tid[i].page.prevtree, &temp);
97: temp.nexttree = tid[i].page.nexttree;
98: write_node(tid[i].page.prevtree, &temp);
99: }
100: if (tid[i].page.nexttree)
101: {
102: get_node(tid[i].page.nexttree, &temp);
103: temp.prevtree = tid[i].page.prevtree;
104: write_node(tid[i].page.nexttree, &temp);
105: }
106: return_page(page[i]);
107: }
108: else
109: write_node(page[i], &tid[i].page);
110: }
111: }
112: return(0);
113: }
114:
115: /* Returns an empty page to the empty file space list. Removes key/ptr
116: ** pair corresponding to empty node from tree. Combines and distributes
117: ** pairs if a node has less than the minimum number of values. Adjusts
118: ** all values up the tree.
119: **
120: ** Parameters :
121: ** tree - BTree filename (I)
122: ** empty - empty node (I)
123: */
124:
125: delete_key(rootpage, empty)
126:
127: long rootpage;
128: register struct locator *empty;
129: {
130: struct locator prt, gprt, sibling;
131: register int i;
132: struct BTreeNode new, temp;
133: long pkey, skey;
134: extern char *Fileset;
135: char replbatch[MAXNAME + 4];
136: FILE *fp;
137: long count, page;
138: TID oldtid, newtid;
139:
140: /* find parent corresponding to empty node, and remove ptr/key pair
141: ** from parent */
142: prt.pageno = empty->page.parent;
143: parentkey(empty->pageno, &prt);
144: if (prt.offset != prt.page.nelmts - 1)
145: {
146: for (i = prt.offset; i < prt.page.nelmts; ++i)
147: {
148: prt.page.node.intnode.ptr[i] =
149: prt.page.node.intnode.ptr[i + 1];
150: prt.page.node.intnode.key[i] =
151: prt.page.node.intnode.key[i + 1];
152: }
153: }
154: --prt.page.nelmts;
155:
156: if (empty->page.nodetype == 'L')
157: /* adjust previous and next fields of leaves */
158: {
159: if (empty->page.node.leafnode.nextleaf != 0)
160: {
161: get_node(empty->page.node.leafnode.nextleaf, &temp);
162: temp.node.leafnode.prevleaf = empty->page.node.leafnode.prevleaf;
163: write_node(empty->page.node.leafnode.nextleaf, &temp);
164: }
165: if (empty->page.node.leafnode.prevleaf != 0)
166: {
167: get_node(empty->page.node.leafnode.prevleaf, &temp);
168: temp.node.leafnode.nextleaf = empty->page.node.leafnode.nextleaf;
169: write_node(empty->page.node.leafnode.prevleaf, &temp);
170: }
171: }
172:
173: /* return empty node to empty file space */
174: return_page(empty->pageno);
175:
176: if (prt.page.nelmts >= (int) ((float) MAXPTRS / 2 + 0.5))
177: {
178: write_node(prt.pageno, &prt.page);
179: /* node still has proper number of elements, decrement key
180: ** values up the tree */
181: tracepath(rootpage, &prt, -1);
182: }
183:
184: else if (prt.pageno == rootpage && prt.page.nelmts < 2)
185: /* root has only one child, a leaf; root becomes leaf node */
186: {
187: /* move leaf values into root; root's position always remains
188: ** the same */
189: get_node(prt.page.node.intnode.ptr[0], &new);
190: new.parent = prt.page.parent;
191: write_node(rootpage, &new);
192: return_page(prt.page.node.intnode.ptr[0]);
193: if (new.nodetype == 'I')
194: {
195: for (i = 0; i < new.nelmts; ++i)
196: {
197: get_node(new.node.intnode.ptr[i], &temp);
198: temp.parent = rootpage;
199: write_node(new.node.intnode.ptr[i], &temp);
200: }
201: }
202: else
203: {
204: /* btree tid is being changed, must be reflected in
205: ** secondary btree relation
206: */
207: concat(REPL_IN, Fileset, replbatch);
208: if ((fp = fopen(replbatch, "w")) == NULL)
209: syserr("can't open replbatch in delete_btree");
210: count = 0;
211: page = 0l;
212: stuff_page(&newtid, &page);
213: stuff_page(&oldtid, &prt.page.node.intnode.ptr[0]);
214: for (i = 0; i < new.nelmts; ++i)
215: {
216: oldtid.line_id = newtid.line_id = new.node.leafnode.tid_loc[i];
217: if (fwrite(&oldtid, 1, LIDSIZE, fp) != LIDSIZE)
218: syserr("write error in delete_btree");
219: if (fwrite(&newtid, 1, LIDSIZE, fp) != LIDSIZE)
220: syserr("write error in delete_btree");
221: ++count;
222: }
223: fclose(fp);
224: repl_btree(replbatch, count);
225: unlink(replbatch);
226: unlink(ztack(REPL_OUT, Fileset));
227: }
228: }
229:
230: else if (prt.pageno != rootpage)
231: {
232: /* find the grandparent of the empty node */
233: gprt.pageno = prt.page.parent;
234: parentkey(prt.pageno, &gprt);
235: if (gprt.page.nelmts - 1 != gprt.offset)
236: {
237: /* determine the right sibling of the parent node */
238: sibling.pageno = gprt.page.node.intnode.ptr[gprt.offset + 1];
239: get_node(sibling.pageno, &sibling.page);
240:
241: if (sibling.page.nelmts > MAXPTRS / 2 + 1)
242: /* distribute key/ptr pairs of parent and right sibling
243: ** between the two nodes (since there are sufficient
244: ** pairs to guarantee that both will have at the least
245: ** the minimum number of required children) */
246: {
247: distribute(&prt, &sibling, &pkey, &skey);
248: /* adjust key values in grandparent */
249: gprt.page.node.intnode.key[gprt.offset] = pkey;
250: gprt.page.node.intnode.key[gprt.offset + 1] = skey;
251: write_node(gprt.pageno, &gprt.page);
252: tracepath(rootpage, &gprt, -1);
253: return;
254: }
255: }
256: if (gprt.offset != 0)
257: {
258: /* determine the left sibling of the parent node */
259: sibling.pageno = gprt.page.node.intnode.ptr[gprt.offset - 1];
260: get_node(sibling.pageno, &sibling.page);
261:
262: if (sibling.page.nelmts > MAXPTRS / 2 + 1)
263: /* distribute key/ptr pairs of parent and left sibling
264: ** between the two nodes */
265: {
266: distribute(&sibling, &prt, &skey, &pkey);
267: gprt.page.node.intnode.key[gprt.offset - 1] = skey;
268: gprt.page.node.intnode.key[gprt.offset] = pkey;
269: write_node(gprt.pageno, &gprt.page);
270: tracepath(rootpage, &gprt, -1);
271: return;
272: }
273: }
274:
275: if (gprt.page.nelmts - 1 != gprt.offset)
276: /* combine parent node with its right sibling */
277: {
278: sibling.pageno = gprt.page.node.intnode.ptr[gprt.offset + 1];
279: get_node(sibling.pageno, &sibling.page);
280: combine(&prt, &sibling);
281: }
282: else
283: /* combine parent node with its left sibling */
284: {
285: sibling.pageno = gprt.page.node.intnode.ptr[gprt.offset - 1];
286: get_node(sibling.pageno, &sibling.page);
287: combine(&sibling, &prt);
288: /* grandparent should point to newly combined block,
289: ** the left sibling */
290: --gprt.offset;
291: }
292:
293: get_node(gprt.page.node.intnode.ptr[gprt.offset], &new);
294: if (gprt.pageno == rootpage && gprt.page.nelmts == 2)
295: /* root has only one child, reduce B-Tree level */
296: {
297: /* only child becomes root */
298: new.parent = gprt.page.parent;
299: write_node(rootpage, &new);
300:
301: /* make sure "new's" children's parent is the root */
302: for (i = 0; i < new.nelmts; ++i)
303: {
304: get_node(new.node.intnode.ptr[i], &temp);
305: temp.parent = rootpage;
306: write_node(new.node.intnode.ptr[i], &temp);
307: }
308: /* both of root's children empty */
309: return_page(gprt.page.node.intnode.ptr[gprt.offset + 1]);
310: return_page(gprt.page.node.intnode.ptr[gprt.offset]);
311: }
312:
313: else
314: {
315: /* adjust key value in grandparent node */
316: pkey = 0;
317: for (i = 0; i < new.nelmts; ++i)
318: pkey += new.node.intnode.key[i];
319: gprt.page.node.intnode.key[gprt.offset] = pkey;
320: write_node(gprt.pageno, &gprt.page);
321:
322: /* remove ptr/key pair corresponding to empty node */
323: gprt.pageno = gprt.page.node.intnode.ptr[gprt.offset + 1];
324: get_node(gprt.pageno, &gprt.page);
325: delete_key(rootpage, &gprt);
326: }
327:
328: }
329: }
330:
331: /* Divides key/ptr pairs between the left and right nodes, so both will
332: ** have the proper number of elements.
333: **
334: ** Parameters :
335: ** tree - BTree filename (I)
336: ** left - left node (I, O)
337: ** right - "left's" right sibling (I, O)
338: ** lkey - key value of the parent of left node (O)
339: ** rkey - key value of the parent of right node (O)
340: */
341:
342: distribute(left, right, lkey, rkey)
343:
344: register struct locator *left, *right;
345: int *lkey, *rkey;
346: {
347: register int i, move;
348: struct BTreeNode temp;
349:
350: if (right->page.nelmts > left->page.nelmts)
351: /* move elements from the right node to the left node */
352: {
353: move = MAXPTRS / 2 - left->page.nelmts;
354:
355: for (i = 1; i <= move; ++i)
356: /* move first part of right node into the end of the left node */
357: {
358: left->page.node.intnode.ptr[i + left->page.nelmts] =
359: right->page.node.intnode.ptr[i - 1];
360: left->page.node.intnode.key[i + left->page.nelmts] =
361: right->page.node.intnode.key[i - 1];
362: /* adjust parents of children whose parents have been
363: ** moved */
364: get_node(left->page.node.intnode.ptr[i + left->page.nelmts], &temp);
365: temp.parent = left->pageno;
366: write_node(left->page.node.intnode.ptr[i + left->page.nelmts], &temp);
367: }
368: left->page.nelmts += move;
369:
370: for (i = move; i < right->page.nelmts; ++i)
371: /* flush right node values to the left */
372: {
373: right->page.node.intnode.ptr[i - move] =
374: right->page.node.intnode.ptr[i];
375: right->page.node.intnode.key[i - move] =
376: right->page.node.intnode.key[i];
377: }
378: right->page.nelmts -= move;
379: }
380:
381: else
382: /* move left node values to the right node */
383: {
384: move = MAXPTRS / 2 - right->page.nelmts + 1;
385:
386: /* move right node values to the right to make room for left
387: ** node values */
388: for (i = right->page.nelmts - 1; i >= 0; --i)
389: {
390: right->page.node.intnode.ptr[i + move] =
391: right->page.node.intnode.ptr[i];
392: right->page.node.intnode.key[i + move] =
393: right->page.node.intnode.key[i];
394: }
395:
396: /* move latter part of left node into the now free space at the
397: ** beginning of the right node */
398: for (i = 0; i < move; ++i)
399: {
400: right->page.node.intnode.ptr[i] =
401: left->page.node.intnode.ptr[left->page.nelmts - move + i];
402: right->page.node.intnode.key[i] =
403: left->page.node.intnode.key[left->page.nelmts - move + i];
404: /* adjust parents of children whose parents have been
405: ** moved */
406: get_node(right->page.node.intnode.ptr[i], &temp);
407: temp.parent = right->pageno;
408: write_node(right->page.node.intnode.ptr[i], &temp);
409: }
410: left->page.nelmts -= move;
411: right->page.nelmts += move;
412: }
413:
414: /* calculate key values for parents of the left and right nodes */
415: *lkey = 0;
416: for (i = 0; i < left->page.nelmts; ++i)
417: *lkey += left->page.node.intnode.key[i];
418: *rkey = 0;
419: for (i = 0; i < right->page.nelmts; ++i)
420: *rkey += right->page.node.intnode.key[i];
421: write_node(left->pageno, &left->page);
422: write_node(right->pageno, &right->page);
423: }
424:
425: /* Combines left and right nodes together to form one node.
426: **
427: ** Parameters :
428: ** tree - BTree filename (I)
429: ** left - left node (I, O)
430: ** right - "left's" right sibling (I)
431: */
432:
433: combine(left, right)
434:
435: register struct locator *left, *right;
436: {
437: register int i;
438: struct BTreeNode temp;
439:
440: /* move all ptr/key values in the right node to the end of the left node */
441: for (i = 0; i < right->page.nelmts; ++i)
442: {
443: left->page.node.intnode.ptr[left->page.nelmts + i] =
444: right->page.node.intnode.ptr[i];
445: left->page.node.intnode.key[left->page.nelmts + i] =
446: right->page.node.intnode.key[i];
447: /* adjust parents of children whose parents have been moved */
448: get_node(left->page.node.intnode.ptr[left->page.nelmts + i], &temp);
449: temp.parent = left->pageno;
450: write_node(left->page.node.intnode.ptr[left->page.nelmts + i], &temp);
451: }
452: left->page.nelmts += right->page.nelmts;
453: write_node(left->pageno, &left->page);
454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.