]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/avl.c
1 /**************************************************************************
3 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * Further, this software is distributed without any warranty that it is
14 * free of the rightful claim of any third person regarding infringement
15 * or the like. Any license provided herein, whether implied or
16 * otherwise, applies only to this software file. Patent licenses, if
17 * any, provided herein do not apply to combinations of this program with
18 * other software, or any other product whatsoever.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write the Free Software Foundation, Inc., 59
22 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
24 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25 * Mountain View, CA 94043, or:
29 * For further information regarding this notice, see:
31 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 **************************************************************************/
45 register avltree_desc_t
*tree
,
46 register avlnode_t
*np
)
48 register avlnode_t
*back
= np
->avl_back
;
49 register avlnode_t
*forw
= np
->avl_forw
;
50 register avlnode_t
*nextino
= np
->avl_nextino
;
51 register int bal
= np
->avl_balance
;
53 ASSERT(bal
!= AVL_BALANCE
|| (!back
&& !forw
) || (back
&& forw
));
54 ASSERT(bal
!= AVL_FORW
|| forw
);
55 ASSERT(bal
!= AVL_BACK
|| back
);
58 ASSERT(AVL_START(tree
, np
) < AVL_START(tree
, forw
));
59 ASSERT(np
->avl_forw
->avl_parent
== np
);
60 ASSERT(back
|| bal
== AVL_FORW
);
62 ASSERT(bal
!= AVL_FORW
);
63 ASSERT(bal
== AVL_BALANCE
|| back
);
64 ASSERT(bal
== AVL_BACK
|| !back
);
68 ASSERT(AVL_START(tree
, np
) > AVL_START(tree
, back
));
69 ASSERT(np
->avl_back
->avl_parent
== np
);
70 ASSERT(forw
|| bal
== AVL_BACK
);
72 ASSERT(bal
!= AVL_BACK
);
73 ASSERT(bal
== AVL_BALANCE
|| forw
);
74 ASSERT(bal
== AVL_FORW
|| !forw
);
80 ASSERT(AVL_END(tree
, np
) <= AVL_START(tree
, nextino
));
85 register avltree_desc_t
*tree
,
86 register avlnode_t
*root
)
88 register avlnode_t
*nlast
, *nnext
, *np
;
89 __psunsigned_t offset
= 0;
94 ASSERT(!nnext
|| nnext
->avl_parent
== NULL
);
98 avl_checknode(tree
, nnext
);
99 end
= AVL_END(tree
, nnext
);
102 if ((np
= nnext
->avl_forw
) && np
!= nlast
) {
107 nnext
= nnext
->avl_parent
;
113 if (np
= nnext
->avl_back
) {
114 if (AVL_END(tree
, np
) > offset
) {
121 nnext
= nnext
->avl_forw
;
123 nnext
= np
->avl_parent
;
128 #else /* ! AVL_DEBUG */
129 #define avl_checktree(t,x)
130 #endif /* AVL_DEBUG */
134 * Reset balance for np up through tree.
135 * ``direction'' is the way that np's balance
136 * is headed after the deletion of one of its children --
137 * e.g., deleting a avl_forw child sends avl_balance toward AVL_BACK.
138 * Called only when deleting a node from the tree.
142 avltree_desc_t
*tree
,
143 register avlnode_t
*np
,
144 register int direction
)
146 register avlnode_t
**rootp
= &tree
->avl_root
;
147 register avlnode_t
*parent
;
148 register avlnode_t
*child
;
149 register avlnode_t
*tmp
;
153 ASSERT(direction
== AVL_BACK
|| direction
== AVL_FORW
);
155 if (np
->avl_balance
== AVL_BALANCE
) {
156 np
->avl_balance
= direction
;
160 parent
= np
->avl_parent
;
163 * If balance is being restored, no local node
164 * reorganization is necessary, but may be at
165 * a higher node. Reset direction and continue.
167 if (direction
!= np
->avl_balance
) {
168 np
->avl_balance
= AVL_BALANCE
;
170 if (parent
->avl_forw
== np
)
171 direction
= AVL_BACK
;
173 direction
= AVL_FORW
;
182 * Imbalance. If a avl_forw node was removed, direction
183 * (and, by reduction, np->avl_balance) is/was AVL_BACK.
185 if (np
->avl_balance
== AVL_BACK
) {
187 ASSERT(direction
== AVL_BACK
);
188 child
= np
->avl_back
;
189 bal
= child
->avl_balance
;
191 if (bal
!= AVL_FORW
) /* single LL */ {
193 * np gets pushed down to lesser child's
198 * child-> B deleted A -D
203 if (!(tree
->avl_flags
& AVLF_DUPLICITY
))
204 cmn_err(CE_CONT
, "!LL delete b 0x%x c 0x%x\n",
207 np
->avl_back
= child
->avl_forw
;
209 child
->avl_forw
->avl_parent
= np
;
210 child
->avl_forw
= np
;
213 if (parent
->avl_forw
== np
) {
214 parent
->avl_forw
= child
;
215 direction
= AVL_BACK
;
217 ASSERT(parent
->avl_back
== np
);
218 parent
->avl_back
= child
;
219 direction
= AVL_FORW
;
222 ASSERT(*rootp
== np
);
225 np
->avl_parent
= child
;
226 child
->avl_parent
= parent
;
228 if (bal
== AVL_BALANCE
) {
229 np
->avl_balance
= AVL_BACK
;
230 child
->avl_balance
= AVL_FORW
;
233 np
->avl_balance
= AVL_BALANCE
;
234 child
->avl_balance
= AVL_BALANCE
;
236 avl_checktree(tree
, *rootp
);
241 /* child->avl_balance == AVL_FORW double LR rotation
243 * child's avl_forw node gets promoted up, along with
244 * its avl_forw subtree
255 if (!(tree
->avl_flags
& AVLF_DUPLICITY
))
256 cmn_err(CE_CONT
, "!LR delete b 0x%x c 0x%x t 0x%x\n",
257 np
, child
, child
->avl_forw
);
259 tmp
= child
->avl_forw
;
260 bal
= tmp
->avl_balance
;
262 child
->avl_forw
= tmp
->avl_back
;
264 tmp
->avl_back
->avl_parent
= child
;
266 tmp
->avl_back
= child
;
267 child
->avl_parent
= tmp
;
269 np
->avl_back
= tmp
->avl_forw
;
271 tmp
->avl_forw
->avl_parent
= np
;
275 child
->avl_balance
= AVL_BACK
;
277 child
->avl_balance
= AVL_BALANCE
;
280 np
->avl_balance
= AVL_FORW
;
282 np
->avl_balance
= AVL_BALANCE
;
287 ASSERT(np
->avl_balance
== AVL_FORW
&& direction
== AVL_FORW
);
289 child
= np
->avl_forw
;
290 bal
= child
->avl_balance
;
292 if (bal
!= AVL_BACK
) /* single RR */ {
294 * np gets pushed down to greater child's
299 * deleted D <-child +B E
304 if (!(tree
->avl_flags
& AVLF_DUPLICITY
))
305 cmn_err(CE_CONT
, "!RR delete b 0x%x c 0x%x\n",
308 np
->avl_forw
= child
->avl_back
;
310 child
->avl_back
->avl_parent
= np
;
311 child
->avl_back
= np
;
314 if (parent
->avl_forw
== np
) {
315 parent
->avl_forw
= child
;
316 direction
= AVL_BACK
;
318 ASSERT(parent
->avl_back
== np
);
319 parent
->avl_back
= child
;
320 direction
= AVL_FORW
;
323 ASSERT(*rootp
== np
);
326 np
->avl_parent
= child
;
327 child
->avl_parent
= parent
;
329 if (bal
== AVL_BALANCE
) {
330 np
->avl_balance
= AVL_FORW
;
331 child
->avl_balance
= AVL_BACK
;
334 np
->avl_balance
= AVL_BALANCE
;
335 child
->avl_balance
= AVL_BALANCE
;
337 avl_checktree(tree
, *rootp
);
342 /* child->avl_balance == AVL_BACK double RL rotation */
344 if (!(tree
->avl_flags
& AVLF_DUPLICITY
))
345 cmn_err(CE_CONT
, "!RL delete b 0x%x c 0x%x t 0x%x\n",
346 np
, child
, child
->avl_back
);
348 tmp
= child
->avl_back
;
349 bal
= tmp
->avl_balance
;
351 child
->avl_back
= tmp
->avl_forw
;
353 tmp
->avl_forw
->avl_parent
= child
;
355 tmp
->avl_forw
= child
;
356 child
->avl_parent
= tmp
;
358 np
->avl_forw
= tmp
->avl_back
;
360 tmp
->avl_back
->avl_parent
= np
;
364 child
->avl_balance
= AVL_FORW
;
366 child
->avl_balance
= AVL_BALANCE
;
369 np
->avl_balance
= AVL_BACK
;
371 np
->avl_balance
= AVL_BALANCE
;
373 np
->avl_parent
= tmp
;
374 tmp
->avl_balance
= AVL_BALANCE
;
375 tmp
->avl_parent
= parent
;
378 if (parent
->avl_forw
== np
) {
379 parent
->avl_forw
= tmp
;
380 direction
= AVL_BACK
;
382 ASSERT(parent
->avl_back
== np
);
383 parent
->avl_back
= tmp
;
384 direction
= AVL_FORW
;
387 ASSERT(*rootp
== np
);
393 avl_checktree(tree
, *rootp
);
398 * Remove node from tree.
399 * avl_delete does the local tree manipulations,
400 * calls retreat() to rebalance tree up to its root.
404 register avltree_desc_t
*tree
,
405 register avlnode_t
*np
)
407 register avlnode_t
*forw
= np
->avl_forw
;
408 register avlnode_t
*back
= np
->avl_back
;
409 register avlnode_t
*parent
= np
->avl_parent
;
410 register avlnode_t
*nnext
;
415 * a left child exits, then greatest left descendent's nextino
416 * is pointing to np; make it point to np->nextino.
418 nnext
= np
->avl_back
;
420 if (!nnext
->avl_forw
)
421 break; /* can't find anything bigger */
422 nnext
= nnext
->avl_forw
;
425 if (np
->avl_parent
) {
427 * find nearest ancestor with lesser value. That ancestor's
428 * nextino is pointing to np; make it point to np->nextino
430 nnext
= np
->avl_parent
;
432 if (AVL_END(tree
, nnext
) <= AVL_END(tree
, np
))
434 nnext
= nnext
->avl_parent
;
440 ASSERT(nnext
->avl_nextino
== np
);
441 nnext
->avl_nextino
= np
->avl_nextino
;
443 * Something preceeds np; np cannot be firstino.
445 ASSERT(tree
->avl_firstino
!= np
);
449 * Nothing preceeding np; after deletion, np's nextino
450 * is firstino of tree.
452 ASSERT(tree
->avl_firstino
== np
);
453 tree
->avl_firstino
= np
->avl_nextino
;
458 * Degenerate cases...
468 forw
->avl_parent
= parent
;
470 if (parent
->avl_forw
== np
) {
471 parent
->avl_forw
= forw
;
472 retreat(tree
, parent
, AVL_BACK
);
474 ASSERT(parent
->avl_back
== np
);
475 parent
->avl_back
= forw
;
476 retreat(tree
, parent
, AVL_FORW
);
479 ASSERT(tree
->avl_root
== np
);
480 tree
->avl_root
= forw
;
482 avl_checktree(tree
, tree
->avl_root
);
487 * Harder case: children on both sides.
488 * If back's avl_forw pointer is null, just have back
489 * inherit np's avl_forw tree, remove np from the tree
490 * and adjust balance counters starting at back.
492 * np-> xI xH (befor retreat())
500 if ((forw
= back
->avl_forw
) == NULL
) {
502 * AVL_FORW retreat below will set back's
503 * balance to AVL_BACK.
505 back
->avl_balance
= np
->avl_balance
;
506 back
->avl_forw
= forw
= np
->avl_forw
;
507 forw
->avl_parent
= back
;
508 back
->avl_parent
= parent
;
511 if (parent
->avl_forw
== np
)
512 parent
->avl_forw
= back
;
514 ASSERT(parent
->avl_back
== np
);
515 parent
->avl_back
= back
;
518 ASSERT(tree
->avl_root
== np
);
519 tree
->avl_root
= back
;
523 * back is taking np's place in the tree, and
524 * has therefore lost a avl_back node (itself).
526 retreat(tree
, back
, AVL_FORW
);
527 avl_checktree(tree
, tree
->avl_root
);
532 * Hardest case: children on both sides, and back's
533 * avl_forw pointer isn't null. Find the immediately
534 * inferior buffer by following back's avl_forw line
535 * to the end, then have it inherit np's avl_forw tree.
539 * G J back-> G J (before retreat())
547 while ((back
= forw
->avl_forw
))
551 * Will be adjusted by retreat() below.
553 forw
->avl_balance
= np
->avl_balance
;
556 * forw inherits np's avl_forw...
558 forw
->avl_forw
= np
->avl_forw
;
559 np
->avl_forw
->avl_parent
= forw
;
562 * ... forw's parent gets forw's avl_back...
564 back
= forw
->avl_parent
;
565 back
->avl_forw
= forw
->avl_back
;
567 forw
->avl_back
->avl_parent
= back
;
570 * ... forw gets np's avl_back...
572 forw
->avl_back
= np
->avl_back
;
573 np
->avl_back
->avl_parent
= forw
;
576 * ... and forw gets np's parent.
578 forw
->avl_parent
= parent
;
581 if (parent
->avl_forw
== np
)
582 parent
->avl_forw
= forw
;
584 parent
->avl_back
= forw
;
586 ASSERT(tree
->avl_root
== np
);
587 tree
->avl_root
= forw
;
591 * What used to be forw's parent is the starting
592 * point for rebalancing. It has lost a avl_forw node.
594 retreat(tree
, back
, AVL_BACK
);
595 avl_checktree(tree
, tree
->avl_root
);
602 * Given range r [start, end), find any range which is contained in r.
603 * if checklen is non-zero, then only ranges of non-zero length are
604 * considered in finding a match.
608 register avltree_desc_t
*tree
,
609 register __psunsigned_t start
,
610 register __psunsigned_t end
,
613 register avlnode_t
*np
= tree
->avl_root
;
615 /* np = avl_findadjacent(tree, start, AVL_SUCCEED); */
617 if (start
< AVL_START(tree
, np
)) {
622 /* if we were to add node with start, would
623 * have a growth of AVL_BACK
625 /* if succeeding node is needed, this is it.
629 if (start
>= AVL_END(tree
, np
)) {
634 /* if we were to add node with start, would
635 * have a growth of AVL_FORW;
637 /* we are looking for a succeeding node;
640 np
= np
->avl_nextino
;
643 /* AVL_START(tree, np) <= start < AVL_END(tree, np) */
647 if (checklen
== AVL_INCLUDE_ZEROLEN
) {
648 if (end
<= AVL_START(tree
, np
)) {
649 /* something follows start, but is
650 * is entierly after the range (end)
654 /* np may stradle [start, end) */
658 * find non-zero length region
660 while (np
&& (AVL_END(tree
, np
) - AVL_START(tree
, np
) == 0)
661 && (AVL_START(tree
, np
) < end
))
662 np
= np
->avl_nextino
;
664 if ((np
== NULL
) || (AVL_START(tree
, np
) >= end
))
669 * nothing succeeds start, all existing ranges are before start.
676 * Returns a pointer to range which contains value.
680 register avltree_desc_t
*tree
,
681 register __psunsigned_t value
)
683 register avlnode_t
*np
= tree
->avl_root
;
686 if (value
< AVL_START(tree
, np
)) {
690 if (value
>= AVL_END(tree
, np
)) {
694 ASSERT(AVL_START(tree
, np
) <= value
&&
695 value
< AVL_END(tree
, np
));
703 * Returns a pointer to node which contains exact value.
707 register avltree_desc_t
*tree
,
708 register __psunsigned_t value
)
710 register avlnode_t
*np
= tree
->avl_root
;
711 register __psunsigned_t nvalue
;
714 nvalue
= AVL_START(tree
, np
);
715 if (value
< nvalue
) {
719 if (value
== nvalue
) {
729 * Balance buffer AVL tree after attaching a new node to root.
730 * Called only by avl_insert.
734 register avlnode_t
**rootp
,
735 register avlnode_t
*np
,
739 * At this point, np points to the node to which
740 * a new node has been attached. All that remains is to
741 * propagate avl_balance up the tree.
744 register avlnode_t
*parent
= np
->avl_parent
;
745 register avlnode_t
*child
;
747 CERT(growth
== AVL_BACK
|| growth
== AVL_FORW
);
750 * If the buffer was already balanced, set avl_balance
751 * to the new direction. Continue if there is a
752 * parent after setting growth to reflect np's
753 * relation to its parent.
755 if (np
->avl_balance
== AVL_BALANCE
) {
756 np
->avl_balance
= growth
;
758 if (parent
->avl_forw
== np
)
761 ASSERT(parent
->avl_back
== np
);
771 if (growth
!= np
->avl_balance
) {
773 * Subtree is now balanced -- no net effect
774 * in the size of the subtree, so leave.
776 np
->avl_balance
= AVL_BALANCE
;
780 if (growth
== AVL_BACK
) {
782 child
= np
->avl_back
;
783 CERT(np
->avl_balance
== AVL_BACK
&& child
);
785 if (child
->avl_balance
== AVL_BACK
) { /* single LL */
787 * ``A'' just got inserted;
788 * np points to ``E'', child to ``C'',
789 * and it is already AVL_BACK --
790 * child will get promoted to top of subtree.
800 Note that child->avl_parent and
801 avl_balance get set in common code.
803 np
->avl_parent
= child
;
804 np
->avl_balance
= AVL_BALANCE
;
805 np
->avl_back
= child
->avl_forw
;
807 child
->avl_forw
->avl_parent
= np
;
808 child
->avl_forw
= np
;
813 * child's avl_forw node gets promoted to
814 * the top of the subtree.
825 register avlnode_t
*tmp
= child
->avl_forw
;
827 CERT(child
->avl_balance
== AVL_FORW
&& tmp
);
829 child
->avl_forw
= tmp
->avl_back
;
831 tmp
->avl_back
->avl_parent
= child
;
833 tmp
->avl_back
= child
;
834 child
->avl_parent
= tmp
;
836 np
->avl_back
= tmp
->avl_forw
;
838 tmp
->avl_forw
->avl_parent
= np
;
841 np
->avl_parent
= tmp
;
843 if (tmp
->avl_balance
== AVL_BACK
)
844 np
->avl_balance
= AVL_FORW
;
846 np
->avl_balance
= AVL_BALANCE
;
848 if (tmp
->avl_balance
== AVL_FORW
)
849 child
->avl_balance
= AVL_BACK
;
851 child
->avl_balance
= AVL_BALANCE
;
854 * Set child to point to tmp since it is
855 * now the top of the subtree, and will
856 * get attached to the subtree parent in
857 * the common code below.
862 } else /* growth == AVL_BACK */ {
865 * This code is the mirror image of AVL_FORW above.
868 child
= np
->avl_forw
;
869 CERT(np
->avl_balance
== AVL_FORW
&& child
);
871 if (child
->avl_balance
== AVL_FORW
) { /* single RR */
872 np
->avl_parent
= child
;
873 np
->avl_balance
= AVL_BALANCE
;
874 np
->avl_forw
= child
->avl_back
;
876 child
->avl_back
->avl_parent
= np
;
877 child
->avl_back
= np
;
882 register avlnode_t
*tmp
= child
->avl_back
;
884 ASSERT(child
->avl_balance
== AVL_BACK
&& tmp
);
886 child
->avl_back
= tmp
->avl_forw
;
888 tmp
->avl_forw
->avl_parent
= child
;
890 tmp
->avl_forw
= child
;
891 child
->avl_parent
= tmp
;
893 np
->avl_forw
= tmp
->avl_back
;
895 tmp
->avl_back
->avl_parent
= np
;
898 np
->avl_parent
= tmp
;
900 if (tmp
->avl_balance
== AVL_FORW
)
901 np
->avl_balance
= AVL_BACK
;
903 np
->avl_balance
= AVL_BALANCE
;
905 if (tmp
->avl_balance
== AVL_BACK
)
906 child
->avl_balance
= AVL_FORW
;
908 child
->avl_balance
= AVL_BALANCE
;
914 child
->avl_parent
= parent
;
915 child
->avl_balance
= AVL_BALANCE
;
918 if (parent
->avl_back
== np
)
919 parent
->avl_back
= child
;
921 parent
->avl_forw
= child
;
923 ASSERT(*rootp
== np
);
933 avl_insert_find_growth(
934 register avltree_desc_t
*tree
,
935 register __psunsigned_t start
, /* range start at start, */
936 register __psunsigned_t end
, /* exclusive */
937 register int *growthp
) /* OUT */
939 avlnode_t
*root
= tree
->avl_root
;
940 register avlnode_t
*np
;
943 ASSERT(np
); /* caller ensures that there is atleast one node in tree */
946 CERT(np
->avl_parent
|| root
== np
);
947 CERT(!np
->avl_parent
|| root
!= np
);
948 CERT(!(np
->avl_back
) || np
->avl_back
->avl_parent
== np
);
949 CERT(!(np
->avl_forw
) || np
->avl_forw
->avl_parent
== np
);
950 CERT(np
->avl_balance
!= AVL_FORW
|| np
->avl_forw
);
951 CERT(np
->avl_balance
!= AVL_BACK
|| np
->avl_back
);
952 CERT(np
->avl_balance
!= AVL_BALANCE
||
953 np
->avl_back
== NULL
|| np
->avl_forw
);
954 CERT(np
->avl_balance
!= AVL_BALANCE
||
955 np
->avl_forw
== NULL
|| np
->avl_back
);
957 if (AVL_START(tree
, np
) >= end
) {
966 if (AVL_END(tree
, np
) <= start
) {
974 /* found exact match -- let caller decide if it is an error */
983 register avltree_desc_t
*tree
,
984 register avlnode_t
*parent
,
985 register avlnode_t
*newnode
,
988 register avlnode_t
*nnext
;
989 register __psunsigned_t start
= AVL_START(tree
, newnode
);
991 if (growth
== AVL_BACK
) {
993 parent
->avl_back
= newnode
;
995 * we are growing to the left; previous in-order to newnode is
996 * closest ancestor with lesser value. Before this
997 * insertion, this ancestor will be pointing to
998 * newnode's parent. After insertion, next in-order to newnode
1001 newnode
->avl_nextino
= parent
;
1004 if (AVL_END(tree
, nnext
) <= start
)
1006 nnext
= nnext
->avl_parent
;
1010 * nnext will be null if newnode is
1011 * the least element, and hence very first in the list.
1013 ASSERT(nnext
->avl_nextino
== parent
);
1014 nnext
->avl_nextino
= newnode
;
1018 parent
->avl_forw
= newnode
;
1019 newnode
->avl_nextino
= parent
->avl_nextino
;
1020 parent
->avl_nextino
= newnode
;
1027 register avltree_desc_t
*tree
,
1028 register avlnode_t
*newnode
)
1030 register avlnode_t
*np
;
1031 register __psunsigned_t start
= AVL_START(tree
, newnode
);
1032 register __psunsigned_t end
= AVL_END(tree
, newnode
);
1036 ASSERT(start
<= end
);
1039 * Clean all pointers for sanity; some will be reset as necessary.
1041 newnode
->avl_nextino
= NULL
;
1042 newnode
->avl_parent
= NULL
;
1043 newnode
->avl_forw
= NULL
;
1044 newnode
->avl_back
= NULL
;
1045 newnode
->avl_balance
= AVL_BALANCE
;
1047 if ((np
= tree
->avl_root
) == NULL
) { /* degenerate case... */
1048 tree
->avl_root
= newnode
;
1049 tree
->avl_firstino
= newnode
;
1053 if ((np
= avl_insert_find_growth(tree
, start
, end
, &growth
)) == NULL
) {
1054 if (start
!= end
) { /* non-zero length range */
1056 _("avl_insert: Warning! duplicate range [%llu,%llu]\n"),
1057 (unsigned long long)start
,
1058 (unsigned long long)end
);
1063 avl_insert_grow(tree
, np
, newnode
, growth
);
1064 if (growth
== AVL_BACK
) {
1066 * Growing to left. if np was firstino, newnode will be firstino
1068 if (tree
->avl_firstino
== np
)
1069 tree
->avl_firstino
= newnode
;
1073 if (growth
== AVL_FORW
)
1075 * Cannot possibly be firstino; there is somebody to our left.
1080 newnode
->avl_parent
= np
;
1081 CERT(np
->avl_forw
== newnode
|| np
->avl_back
== newnode
);
1083 avl_balance(&tree
->avl_root
, np
, growth
);
1085 avl_checktree(tree
, tree
->avl_root
);
1092 * avl_insert_immediate(tree, afterp, newnode):
1093 * insert newnode immediately into tree immediately after afterp.
1094 * after insertion, newnode is right child of afterp.
1097 avl_insert_immediate(
1098 avltree_desc_t
*tree
,
1103 * Clean all pointers for sanity; some will be reset as necessary.
1105 newnode
->avl_nextino
= NULL
;
1106 newnode
->avl_parent
= NULL
;
1107 newnode
->avl_forw
= NULL
;
1108 newnode
->avl_back
= NULL
;
1109 newnode
->avl_balance
= AVL_BALANCE
;
1111 if (afterp
== NULL
) {
1112 tree
->avl_root
= newnode
;
1113 tree
->avl_firstino
= newnode
;
1117 ASSERT(afterp
->avl_forw
== NULL
);
1118 avl_insert_grow(tree
, afterp
, newnode
, AVL_FORW
); /* grow to right */
1119 CERT(afterp
->avl_forw
== newnode
);
1120 avl_balance(&tree
->avl_root
, afterp
, AVL_FORW
);
1121 avl_checktree(tree
, tree
->avl_root
);
1126 * Returns first in order node
1129 avl_firstino(register avlnode_t
*root
)
1131 register avlnode_t
*np
;
1133 if ((np
= root
) == NULL
)
1136 while (np
->avl_back
)
1142 * Returns last in order node
1145 avl_lastino(register avlnode_t
*root
)
1147 register avlnode_t
*np
;
1149 if ((np
= root
) == NULL
)
1152 while (np
->avl_forw
)
1158 avl_init_tree(avltree_desc_t
*tree
, avlops_t
*ops
)
1160 tree
->avl_root
= NULL
;
1161 tree
->avl_firstino
= NULL
;
1162 tree
->avl_ops
= ops
;
1167 avl_printnode(avltree_desc_t
*tree
, avlnode_t
*np
, int nl
)
1169 printf("[%d-%d]%c", AVL_START(tree
, np
),
1170 (AVL_END(tree
, np
) - 1), nl
? '\n' : ' ');
1173 #ifdef STAND_ALONE_DEBUG
1175 struct avl_debug_node
{
1177 xfs_off_t avl_start
;
1178 unsigned int avl_size
;
1181 avlops_t avl_debug_ops
= {
1186 static __psunsigned_t
1187 avl_debug_start(avlnode_t
*node
)
1189 return (__psunsigned_t
)(struct avl_debug_node
*)node
->avl_start
;
1192 static __psunsigned_t
1193 avl_debug_end(avlnode_t
*node
)
1195 return (__psunsigned_t
)
1196 ((struct avl_debug_node
*)node
->avl_start
+
1197 (struct avl_debug_node
*)node
->avl_size
);
1200 avl_debug_node freenodes
[100];
1201 avl_debug_node
*freehead
= &freenodes
[0];
1204 alloc_avl_debug_node()
1206 freehead
->avl_balance
= AVL_BALANCE
;
1207 freehead
->avl_parent
= freehead
->avl_forw
= freehead
->avl_back
= NULL
;
1212 avl_print(avltree_desc_t
*tree
, avlnode_t
*root
, int depth
)
1219 avl_print(tree
, root
->avl_forw
, depth
+5);
1220 for (i
= 0; i
< depth
; i
++)
1222 avl_printnode(tree
, root
,1);
1224 avl_print(tree
, root
->avl_back
, depth
+5);
1231 avltree_desc_t tree
;
1232 char linebuf
[256], cmd
[256];
1234 avl_init_tree(&tree
, &avl_debug_ops
);
1236 for (i
= 100; i
> 0; i
= i
- 10)
1238 np
= alloc__debug_avlnode();
1242 avl_insert(&tree
, np
);
1244 avl_print(&tree
, tree
.avl_root
, 0);
1246 for (np
= tree
.avl_firstino
; np
!= NULL
; np
= np
->avl_nextino
)
1247 avl_printnode(&tree
, np
, 0);
1251 printf("Command [fpdir] : ");
1252 fgets(linebuf
, 256, stdin
);
1253 if (feof(stdin
)) break;
1255 if (sscanf(linebuf
, "%[fpdir]%d", cmd
, &i
) != 2)
1260 printf("end of range ? ");
1261 fgets(linebuf
, 256, stdin
);
1264 if (i
== j
) j
= i
+1;
1265 np
= avl_findinrange(&tree
,i
,j
);
1267 avl_printnode(&tree
, np
, 1);
1269 avl_delete(&tree
, np
);
1271 printf("Cannot find %d\n", i
);
1274 avl_print(&tree
, tree
.avl_root
, 0);
1275 for (np
= tree
.avl_firstino
;
1276 np
!= NULL
; np
= np
->avl_nextino
)
1277 avl_printnode(&tree
, np
, 0);
1281 np
= alloc_avlnode();
1284 printf("size of range ? ");
1285 fgets(linebuf
, 256, stdin
);
1289 avl_insert(&tree
, np
);
1292 avlnode_t
*b
, *e
, *t
;
1295 printf("End of range ? ");
1296 fgets(linebuf
, 256, stdin
);
1299 printf("checklen 0/1 ? ");
1300 fgets(linebuf
, 256, stdin
);
1301 checklen
= atoi(linebuf
);
1304 b
= avl_findanyrange(&tree
, i
, j
, checklen
);
1306 printf("Found something\n");
1310 AVL_START(&tree
, t
) >= j
)
1312 avl_printnode(&tree
, t
, 0);
1324 * Given a tree, find value; will find return range enclosing value,
1325 * or range immediately succeeding value,
1326 * or range immediately preceeding value.
1330 register avltree_desc_t
*tree
,
1331 register __psunsigned_t value
,
1334 register avlnode_t
*np
= tree
->avl_root
;
1337 if (value
< AVL_START(tree
, np
)) {
1342 /* if we were to add node with value, would
1343 * have a growth of AVL_BACK
1345 if (dir
== AVL_SUCCEED
) {
1346 /* if succeeding node is needed, this is it.
1350 if (dir
== AVL_PRECEED
) {
1352 * find nearest ancestor with lesser value.
1354 np
= np
->avl_parent
;
1356 if (AVL_END(tree
, np
) <= value
)
1358 np
= np
->avl_parent
;
1362 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1365 if (value
>= AVL_END(tree
, np
)) {
1370 /* if we were to add node with value, would
1371 * have a growth of AVL_FORW;
1373 if (dir
== AVL_SUCCEED
) {
1374 /* we are looking for a succeeding node;
1377 return(np
->avl_nextino
);
1379 if (dir
== AVL_PRECEED
) {
1380 /* looking for a preceeding node; this is it. */
1383 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1385 /* AVL_START(tree, np) <= value < AVL_END(tree, np) */
1395 * Given range r [start, end), find all ranges in tree which are contained
1396 * in r. At return, startp and endp point to first and last of
1397 * a chain of elements which describe the contained ranges. Elements
1398 * in startp ... endp are in sort order, and can be accessed by
1399 * using avl_nextino.
1404 register avltree_desc_t
*tree
,
1405 register __psunsigned_t start
,
1406 register __psunsigned_t end
,
1410 register avlnode_t
*np
;
1412 np
= avl_findadjacent(tree
, start
, AVL_SUCCEED
);
1413 if (np
== NULL
/* nothing succeding start */
1414 || (np
&& (end
<= AVL_START(tree
, np
))))
1415 /* something follows start,
1416 but... is entirely after end */
1425 /* see if end is in this region itself */
1426 if (end
<= AVL_END(tree
, np
) ||
1427 np
->avl_nextino
== NULL
||
1429 (end
<= AVL_START(tree
, np
->avl_nextino
)))) {
1433 /* have to munge for end */
1435 * note: have to look for (end - 1), since
1436 * findadjacent will look for exact value, and does not
1437 * care about the fact that end is actually one more
1438 * than the value actually being looked for; thus feed it one less.
1440 *endp
= avl_findadjacent(tree
, (end
-1), AVL_PRECEED
);