Whamcloud - gitweb
LU-1030 osc: new IO engine implementation
[fs/lustre-release.git] / libcfs / libcfs / posix / rbtree.c
1 /*
2   Red Black Trees
3   (C) 1999  Andrea Arcangeli <andrea@suse.de>
4   (C) 2002  David Woodhouse <dwmw2@infradead.org>
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20   linux/lib/rbtree.c
21 */
22
23 #include <libcfs/libcfs.h>
24
25 static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
26 {
27         struct rb_node *right = node->rb_right;
28         struct rb_node *parent = rb_parent(node);
29
30         node->rb_right = right->rb_left;
31         if (node->rb_right != NULL)
32                 rb_set_parent(right->rb_left, node);
33         right->rb_left = node;
34
35         rb_set_parent(right, parent);
36
37         if (parent) {
38                 if (node == parent->rb_left)
39                         parent->rb_left = right;
40                 else
41                         parent->rb_right = right;
42         } else
43                 root->rb_node = right;
44         rb_set_parent(node, right);
45 }
46
47 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
48 {
49         struct rb_node *left = node->rb_left;
50         struct rb_node *parent = rb_parent(node);
51
52         node->rb_left = left->rb_right;
53         if (node->rb_left != NULL)
54                 rb_set_parent(left->rb_right, node);
55         left->rb_right = node;
56
57         rb_set_parent(left, parent);
58
59         if (parent) {
60                 if (node == parent->rb_right)
61                         parent->rb_right = left;
62                 else
63                         parent->rb_left = left;
64         } else
65                 root->rb_node = left;
66         rb_set_parent(node, left);
67 }
68
69 void rb_insert_color(struct rb_node *node, struct rb_root *root)
70 {
71         struct rb_node *parent, *gparent;
72
73         while ((parent = rb_parent(node)) != NULL && rb_is_red(parent)) {
74                 gparent = rb_parent(parent);
75
76                 if (parent == gparent->rb_left) {
77                         register struct rb_node *uncle = gparent->rb_right;
78                         if (uncle && rb_is_red(uncle)) {
79                                 rb_set_black(uncle);
80                                 rb_set_black(parent);
81                                 rb_set_red(gparent);
82                                 node = gparent;
83                                 continue;
84                         }
85
86                         if (parent->rb_right == node) {
87                                 register struct rb_node *tmp;
88                                 __rb_rotate_left(parent, root);
89                                 tmp = parent;
90                                 parent = node;
91                                 node = tmp;
92                         }
93
94                         rb_set_black(parent);
95                         rb_set_red(gparent);
96                         __rb_rotate_right(gparent, root);
97                 } else {
98                         register struct rb_node *uncle = gparent->rb_left;
99                         if (uncle && rb_is_red(uncle)) {
100                                 rb_set_black(uncle);
101                                 rb_set_black(parent);
102                                 rb_set_red(gparent);
103                                 node = gparent;
104                                 continue;
105                         }
106
107                         if (parent->rb_left == node) {
108                                 register struct rb_node *tmp;
109                                 __rb_rotate_right(parent, root);
110                                 tmp = parent;
111                                 parent = node;
112                                 node = tmp;
113                         }
114
115                         rb_set_black(parent);
116                         rb_set_red(gparent);
117                         __rb_rotate_left(gparent, root);
118                 }
119         }
120
121         rb_set_black(root->rb_node);
122 }
123
124 static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
125                              struct rb_root *root)
126 {
127         struct rb_node *ptr;
128
129         while ((!node || rb_is_black(node)) && node != root->rb_node) {
130                 if (parent->rb_left == node) {
131                         ptr = parent->rb_right;
132                         if (rb_is_red(ptr)) {
133                                 rb_set_black(ptr);
134                                 rb_set_red(parent);
135                                 __rb_rotate_left(parent, root);
136                                 ptr = parent->rb_right;
137                         }
138                         if ((!ptr->rb_left || rb_is_black(ptr->rb_left)) &&
139                             (!ptr->rb_right || rb_is_black(ptr->rb_right))) {
140                                 rb_set_red(ptr);
141                                 node = parent;
142                                 parent = rb_parent(node);
143                         } else {
144                                 if (!ptr->rb_right ||
145                                     rb_is_black(ptr->rb_right)) {
146                                         rb_set_black(ptr->rb_left);
147                                         rb_set_red(ptr);
148                                         __rb_rotate_right(ptr, root);
149                                         ptr = parent->rb_right;
150                                 }
151                                 rb_set_color(ptr, rb_color(parent));
152                                 rb_set_black(parent);
153                                 rb_set_black(ptr->rb_right);
154                                 __rb_rotate_left(parent, root);
155                                 node = root->rb_node;
156                                 break;
157                         }
158                 } else {
159                         ptr = parent->rb_left;
160                         if (rb_is_red(ptr)) {
161                                 rb_set_black(ptr);
162                                 rb_set_red(parent);
163                                 __rb_rotate_right(parent, root);
164                                 ptr = parent->rb_left;
165                         }
166                         if ((!ptr->rb_left || rb_is_black(ptr->rb_left)) &&
167                             (!ptr->rb_right || rb_is_black(ptr->rb_right))) {
168                                 rb_set_red(ptr);
169                                 node = parent;
170                                 parent = rb_parent(node);
171                         } else {
172                                 if (!ptr->rb_left ||
173                                     rb_is_black(ptr->rb_left)) {
174                                         rb_set_black(ptr->rb_right);
175                                         rb_set_red(ptr);
176                                         __rb_rotate_left(ptr, root);
177                                         ptr = parent->rb_left;
178                                 }
179                                 rb_set_color(ptr, rb_color(parent));
180                                 rb_set_black(parent);
181                                 rb_set_black(ptr->rb_left);
182                                 __rb_rotate_right(parent, root);
183                                 node = root->rb_node;
184                                 break;
185                         }
186                 }
187         }
188         if (node)
189                 rb_set_black(node);
190 }
191
192 void rb_erase(struct rb_node *node, struct rb_root *root)
193 {
194         struct rb_node *child, *parent;
195         int color;
196
197         if (!node->rb_left)
198                 child = node->rb_right;
199         else if (!node->rb_right)
200                 child = node->rb_left;
201         else {
202                 struct rb_node *old = node, *left;
203
204                 node = node->rb_right;
205                 while ((left = node->rb_left) != NULL)
206                         node = left;
207
208                 if (rb_parent(old)) {
209                         if (rb_parent(old)->rb_left == old)
210                                 rb_parent(old)->rb_left = node;
211                         else
212                                 rb_parent(old)->rb_right = node;
213                 } else
214                         root->rb_node = node;
215
216                 child = node->rb_right;
217                 parent = rb_parent(node);
218                 color = rb_color(node);
219
220                 if (parent == old) {
221                         parent = node;
222                 } else {
223                         if (child)
224                                 rb_set_parent(child, parent);
225                         parent->rb_left = child;
226
227                         node->rb_right = old->rb_right;
228                         rb_set_parent(old->rb_right, node);
229                 }
230
231                 node->rb_parent_color = old->rb_parent_color;
232                 node->rb_left = old->rb_left;
233                 rb_set_parent(old->rb_left, node);
234
235                 goto color;
236         }
237
238         parent = rb_parent(node);
239         color = rb_color(node);
240
241         if (child)
242                 rb_set_parent(child, parent);
243         if (parent) {
244                 if (parent->rb_left == node)
245                         parent->rb_left = child;
246                 else
247                         parent->rb_right = child;
248         } else
249                 root->rb_node = child;
250
251  color:
252         if (color == RB_BLACK)
253                 __rb_erase_color(child, parent, root);
254 }
255
256 /*
257  * This function returns the first node (in sort order) of the tree.
258  */
259 struct rb_node *rb_first(const struct rb_root *root)
260 {
261         struct rb_node  *n;
262
263         n = root->rb_node;
264         if (!n)
265                 return NULL;
266         while (n->rb_left)
267                 n = n->rb_left;
268         return n;
269 }
270
271 struct rb_node *rb_last(const struct rb_root *root)
272 {
273         struct rb_node  *n;
274
275         n = root->rb_node;
276         if (!n)
277                 return NULL;
278         while (n->rb_right)
279                 n = n->rb_right;
280         return n;
281 }
282
283 struct rb_node *rb_next(const struct rb_node *node)
284 {
285         struct rb_node *parent;
286
287         if (rb_parent(node) == node)
288                 return NULL;
289
290         /* If we have a right-hand child, go down and then left as far
291            as we can. */
292         if (node->rb_right) {
293                 node = node->rb_right;
294                 while (node->rb_left)
295                         node = node->rb_left;
296                 return (struct rb_node *)node;
297         }
298
299         /* No right-hand children.  Everything down and left is
300            smaller than us, so any 'next' node must be in the general
301            direction of our parent. Go up the tree; any time the
302            ancestor is a right-hand child of its parent, keep going
303            up. First time it's a left-hand child of its parent, said
304            parent is our 'next' node. */
305         while ((parent = rb_parent(node)) && node == parent->rb_right)
306                 node = parent;
307
308         return parent;
309 }
310
311 struct rb_node *rb_prev(const struct rb_node *node)
312 {
313         struct rb_node *parent;
314
315         if (rb_parent(node) == node)
316                 return NULL;
317
318         /* If we have a left-hand child, go down and then right as far
319            as we can. */
320         if (node->rb_left) {
321                 node = node->rb_left;
322                 while (node->rb_right)
323                         node = node->rb_right;
324                 return (struct rb_node *)node;
325         }
326
327         /* No left-hand children. Go up till we find an ancestor which
328            is a right-hand child of its parent */
329         while ((parent = rb_parent(node)) && node == parent->rb_left)
330                 node = parent;
331
332         return parent;
333 }