Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / opr / rbtree.c
1 /*
2 * Copyright (c) 2008 - 2010 Jason Evans <jasone@FreeBSD.org>
3 * Copyright (c) 2011 Your File System Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /* Left-leaning rbtree implementation. Originally derived from the FreeBSD
28 * CPP macro definitions by Jason Evans, but extensively modified to
29 * *) Be function, rather than macro based
30 * *) Use parent pointers, rather than calling an embeded comparison fn
31 * *) Use 'NULL' to represent empty nodes, rather than a magic pointer
32 */
33
34 #include <afsconfig.h>
35 #include <afs/param.h>
36
37 #ifdef KERNEL
38 # include "afs/sysincludes.h"
39 # include "afsincludes.h"
40 #else
41 # include <roken.h>
42 #endif
43
44 #include "rbtree.h"
45
46 struct {
47 struct opr_rbtree_node *left;
48 struct opr_rbtree_node *right;
49 struct opr_rbtree_node *parent;
50 int red;
51 } opr_rbtree_node;
52
53 struct {
54 struct opr_rbtree_node *root;
55 } opr_rbtree;
56
57 /* Update the parent pointers for a node which is being replaced.
58 *
59 * If the original node had no parent, then it was the root of the tree,
60 * and the replacement is too.
61 * Otherwise, the original node must have been either the left or right
62 * child of its parent, so update the left (or right) pointer to point
63 * to the replacement as appropriate.
64 */
65
66 static_inline void
67 update_parent_ptr(struct opr_rbtree *head, struct opr_rbtree_node *old,
68 struct opr_rbtree_node *replacement)
69 {
70 if (old->parent) {
71 if (old->parent->left == old)
72 old->parent->left = replacement;
73 else
74 old->parent->right = replacement;
75 } else
76 head->root = replacement;
77 }
78
79 void
80 opr_rbtree_init(struct opr_rbtree *head)
81 {
82 head->root = NULL;
83 }
84
85 struct opr_rbtree_node *
86 opr_rbtree_first(struct opr_rbtree *head)
87 {
88 struct opr_rbtree_node *node;
89
90 node = head->root;
91 if (node == NULL)
92 return node;
93
94 while (node->left != NULL)
95 node = node->left;
96
97 return node;
98 }
99
100 struct opr_rbtree_node *
101 opr_rbtree_last(struct opr_rbtree *head)
102 {
103 struct opr_rbtree_node *node;
104
105 node = head->root;
106
107 if (node == NULL)
108 return node;
109
110 while (node->right != NULL)
111 node = node->right;
112
113 return node;
114 }
115
116
117 struct opr_rbtree_node *
118 opr_rbtree_next(struct opr_rbtree_node *node)
119 {
120 struct opr_rbtree_node *parent;
121
122 /* Where there is a right child, the next node is to the right, then
123 * left as far as we can go */
124 if (node->right != NULL) {
125 node = node->right;
126 while (node->left != NULL)
127 node = node->left;
128
129 return node;
130 }
131
132 /* If there is no right hand child, then the next node is above us.
133 * Whenever our ancestor is a right-hand child, the next node is
134 * further up. When it is a left-hand child, it is our next node
135 */
136 while ((parent = node->parent) != NULL && node == parent->right)
137 node = parent;
138
139 return parent;
140 }
141
142 struct opr_rbtree_node *
143 opr_rbtree_prev(struct opr_rbtree_node *node)
144 {
145 struct opr_rbtree_node *parent;
146
147 if (node->left != NULL) {
148 node = node->left;
149 while (node->right != NULL)
150 node = node->right;
151
152 return node;
153 }
154
155 /* Same ancestor logic as for 'next', but in reverse */
156 while ((parent = node->parent) != NULL && node == parent->left)
157 node = parent;
158
159 return parent;
160 }
161
162 static_inline void
163 rotateright(struct opr_rbtree *head, struct opr_rbtree_node *node)
164 {
165 struct opr_rbtree_node *left = node->left;
166
167 node->left = left->right;
168 if (left->right)
169 left->right->parent = node;
170
171 left->right = node;
172 left->parent = node->parent;
173
174 update_parent_ptr(head, node, left);
175
176 node->parent = left;
177 }
178
179 static_inline void
180 rotateleft(struct opr_rbtree *head, struct opr_rbtree_node *node)
181 {
182 struct opr_rbtree_node *right = node->right;
183
184 node->right = right->left;
185 if (right->left)
186 right->left->parent = node;
187
188 right->left = node;
189 right->parent = node->parent;
190
191 update_parent_ptr(head, node, right);
192
193 node->parent = right;
194 }
195
196 static_inline void
197 swapnode(struct opr_rbtree_node **a, struct opr_rbtree_node **b)
198 {
199 struct opr_rbtree_node *tmp;
200
201 tmp = *a;
202 *a = *b;
203 *b = tmp;
204 }
205
206 static void
207 insert_recolour(struct opr_rbtree *head, struct opr_rbtree_node *node)
208 {
209 struct opr_rbtree_node *parent, *gramps;
210
211 while ((parent = node->parent) && parent->red) {
212 gramps = parent->parent;
213
214 if (parent == gramps->left) {
215 struct opr_rbtree_node *uncle = gramps->right;
216
217 if (uncle && uncle->red) {
218 uncle->red = 0;
219 parent->red = 0;
220 gramps->red = 1;
221 node = gramps;
222 continue;
223 }
224
225 if (parent->right == node) {
226 rotateleft(head, parent);
227 swapnode(&parent, &node);
228 }
229
230 parent->red = 0;
231 gramps->red = 1;
232 rotateright(head, gramps);
233 } else {
234 struct opr_rbtree_node *uncle = gramps->left;
235
236 if (uncle && uncle->red) {
237 uncle->red = 0;
238 parent->red = 0;
239 gramps->red = 1;
240 node = gramps;
241 continue;
242 }
243
244 if (parent->left == node) {
245 rotateright(head, parent);
246 swapnode(&parent, &node);
247 }
248
249 parent->red = 0;
250 gramps->red = 1;
251 rotateleft(head, gramps);
252 }
253 }
254
255 head->root->red = 0;
256 }
257
258 void
259 opr_rbtree_insert(struct opr_rbtree *head,
260 struct opr_rbtree_node *parent,
261 struct opr_rbtree_node **childptr,
262 struct opr_rbtree_node *node)
263 {
264 /* Link node 'node' into the tree at position 'parent', using either the
265 * left or right pointers */
266
267 node->parent = parent;
268 node->left = node->right = NULL;
269 node->red = 1;
270 *childptr = node;
271
272 /* Rebalance the tree for the newly inserted node */
273 insert_recolour(head, node);
274 }
275
276 static void
277 remove_recolour(struct opr_rbtree *head, struct opr_rbtree_node *parent,
278 struct opr_rbtree_node *node)
279 {
280 struct opr_rbtree_node *other;
281
282 while ((node == NULL || !node->red) && node != head->root) {
283 if (parent->left == node) {
284 other = parent->right;
285 if (other->red) {
286 other->red = 0;
287 parent->red = 1;
288 rotateleft(head, parent);
289 other = parent->right;
290 }
291 if ((other->left == NULL || !other->left->red) &&
292 (other->right == NULL || !other->right->red)) {
293 other->red = 1;
294 node = parent;
295 parent = node->parent;
296 } else {
297 if (other->right == NULL || !other->right->red) {
298 other->left->red = 0;
299 other->red = 1;
300 rotateright(head, other);
301 other = parent->right;
302 }
303 other->red = parent->red;
304 parent->red = 0;
305 other->right->red = 0;
306 rotateleft(head, parent);
307 node = head->root;
308 break;
309 }
310 } else {
311 other = parent->left;
312 if (other->red) {
313 other->red = 0;
314 parent->red = 1;
315 rotateright(head, parent);
316 other = parent->left;
317 }
318 if ((other->left == NULL || !other->left->red) &&
319 (other->right == NULL || !other->right->red)) {
320 other->red = 1;
321 node = parent;
322 parent = node->parent;
323 } else {
324 if (other->left == NULL || !other->left->red) {
325 other->right->red = 0;
326 other->red = 1;
327 rotateleft(head, other);
328 other = parent->left;
329 }
330 other->red = parent->red;
331 parent->red = 0;
332 other->left->red = 0;
333 rotateright(head, parent);
334 node = head->root;
335 break;
336 }
337 }
338 }
339 if (node)
340 node->red = 0;
341 }
342
343 void
344 opr_rbtree_remove(struct opr_rbtree *head, struct opr_rbtree_node *node)
345 {
346 struct opr_rbtree_node *child, *parent;
347 int red;
348
349
350 if (node->left == NULL && node->right == NULL) {
351 /* A node with no non-leaf children */
352 update_parent_ptr(head, node, NULL);
353
354 if (!node->red)
355 remove_recolour(head, node->parent, NULL);
356
357 return;
358 }
359
360 if (node->left != NULL && node->right != NULL) {
361 /* A node with two children.
362 *
363 * Move the next node in the tree (which will be a leaf node)
364 * onto our tree current position, then rebalance as required
365 */
366 struct opr_rbtree_node *old, *left;
367
368 old = node;
369
370 /* Set node to the next node in the tree from the current
371 * position, where the next node is the left-most leaf node
372 * in our right child */
373 node = node->right;
374 while ((left = node->left) != NULL)
375 node = left;
376
377 /* Move 'node' into the position occupied by 'old', which is being
378 * removed */
379
380 update_parent_ptr(head, old, node);
381
382 child = node->right;
383 parent = node->parent;
384 red = node->red;
385
386 /* As we're logically just copying the value, must preserve the
387 * old node's colour */
388 node->red = old->red;
389
390 /* ... and the old node's linkage */
391 if (parent == old)
392 parent = node;
393 else {
394 if (child)
395 child->parent = parent;
396 parent->left = child;
397
398 node->right = old->right;
399 old->right->parent = node;
400 }
401
402 node->parent = old->parent;
403 node->left = old->left;
404 old->left->parent = node;
405
406 /* If the node being removed was black, then we must recolour the
407 * tree to maintain balance */
408 if (!red)
409 remove_recolour(head, parent, child);
410
411 return;
412 }
413
414 /* Only remaining option - node with a single child */
415
416 if (node->left == NULL)
417 child = node->right;
418 else
419 child = node->left;
420
421 child->parent = node->parent;
422
423 update_parent_ptr(head, node, child);
424
425 if (!node->red)
426 remove_recolour(head, node->parent, child);
427 }
428
429 void
430 opr_rbtree_replace(struct opr_rbtree *head,
431 struct opr_rbtree_node *old,
432 struct opr_rbtree_node *replacement)
433 {
434 /* Update our parent's pointer to us */
435 update_parent_ptr(head, old, replacement);
436
437 /* And our children's pointers to us */
438 if (old->left)
439 old->left->parent = replacement;
440 if (old->right)
441 old->right->parent = replacement;
442
443 /* Copy over parent, left, right and colour */
444 *replacement = *old;
445 }