]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/avl64.c
1 /**************************************************************************
3 * Copyright (c) 2000 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 avl64tree_desc_t
*tree
,
46 register avl64node_t
*np
)
48 register avl64node_t
*back
= np
->avl_back
;
49 register avl64node_t
*forw
= np
->avl_forw
;
50 register avl64node_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 avl64tree_desc_t
*tree
,
86 register avl64node_t
*root
)
88 register avl64node_t
*nlast
, *nnext
, *np
;
89 __uint64_t offset
= 0;
94 ASSERT(!nnext
|| nnext
->avl_parent
== NULL
);
98 avl64_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 avl64_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 avl64tree_desc_t
*tree
,
143 register avl64node_t
*np
,
144 register int direction
)
146 register avl64node_t
**rootp
= &tree
->avl_root
;
147 register avl64node_t
*parent
;
148 register avl64node_t
*child
;
149 register avl64node_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
201 cmn_err(CE_CONT, "!LL delete b 0x%x c 0x%x\n",
205 np
->avl_back
= child
->avl_forw
;
207 child
->avl_forw
->avl_parent
= np
;
208 child
->avl_forw
= np
;
211 if (parent
->avl_forw
== np
) {
212 parent
->avl_forw
= child
;
213 direction
= AVL_BACK
;
215 ASSERT(parent
->avl_back
== np
);
216 parent
->avl_back
= child
;
217 direction
= AVL_FORW
;
220 ASSERT(*rootp
== np
);
223 np
->avl_parent
= child
;
224 child
->avl_parent
= parent
;
226 if (bal
== AVL_BALANCE
) {
227 np
->avl_balance
= AVL_BACK
;
228 child
->avl_balance
= AVL_FORW
;
231 np
->avl_balance
= AVL_BALANCE
;
232 child
->avl_balance
= AVL_BALANCE
;
234 avl64_checktree(tree
, *rootp
);
239 /* child->avl_balance == AVL_FORW double LR rotation
241 * child's avl_forw node gets promoted up, along with
242 * its avl_forw subtree
251 cmn_err(CE_CONT, "!LR delete b 0x%x c 0x%x t 0x%x\n",
252 np, child, child->avl_forw);
255 tmp
= child
->avl_forw
;
256 bal
= tmp
->avl_balance
;
258 child
->avl_forw
= tmp
->avl_back
;
260 tmp
->avl_back
->avl_parent
= child
;
262 tmp
->avl_back
= child
;
263 child
->avl_parent
= tmp
;
265 np
->avl_back
= tmp
->avl_forw
;
267 tmp
->avl_forw
->avl_parent
= np
;
271 child
->avl_balance
= AVL_BACK
;
273 child
->avl_balance
= AVL_BALANCE
;
276 np
->avl_balance
= AVL_FORW
;
278 np
->avl_balance
= AVL_BALANCE
;
283 ASSERT(np
->avl_balance
== AVL_FORW
&& direction
== AVL_FORW
);
285 child
= np
->avl_forw
;
286 bal
= child
->avl_balance
;
288 if (bal
!= AVL_BACK
) /* single RR */ {
290 * np gets pushed down to greater child's
295 * deleted D <-child +B E
298 cmn_err(CE_CONT, "!RR delete b 0x%x c 0x%x\n",
302 np
->avl_forw
= child
->avl_back
;
304 child
->avl_back
->avl_parent
= np
;
305 child
->avl_back
= np
;
308 if (parent
->avl_forw
== np
) {
309 parent
->avl_forw
= child
;
310 direction
= AVL_BACK
;
312 ASSERT(parent
->avl_back
== np
);
313 parent
->avl_back
= child
;
314 direction
= AVL_FORW
;
317 ASSERT(*rootp
== np
);
320 np
->avl_parent
= child
;
321 child
->avl_parent
= parent
;
323 if (bal
== AVL_BALANCE
) {
324 np
->avl_balance
= AVL_FORW
;
325 child
->avl_balance
= AVL_BACK
;
328 np
->avl_balance
= AVL_BALANCE
;
329 child
->avl_balance
= AVL_BALANCE
;
331 avl64_checktree(tree
, *rootp
);
336 /* child->avl_balance == AVL_BACK double RL rotation
337 cmn_err(CE_CONT, "!RL delete b 0x%x c 0x%x t 0x%x\n",
338 np, child, child->avl_back);
341 tmp
= child
->avl_back
;
342 bal
= tmp
->avl_balance
;
344 child
->avl_back
= tmp
->avl_forw
;
346 tmp
->avl_forw
->avl_parent
= child
;
348 tmp
->avl_forw
= child
;
349 child
->avl_parent
= tmp
;
351 np
->avl_forw
= tmp
->avl_back
;
353 tmp
->avl_back
->avl_parent
= np
;
357 child
->avl_balance
= AVL_FORW
;
359 child
->avl_balance
= AVL_BALANCE
;
362 np
->avl_balance
= AVL_BACK
;
364 np
->avl_balance
= AVL_BALANCE
;
366 np
->avl_parent
= tmp
;
367 tmp
->avl_balance
= AVL_BALANCE
;
368 tmp
->avl_parent
= parent
;
371 if (parent
->avl_forw
== np
) {
372 parent
->avl_forw
= tmp
;
373 direction
= AVL_BACK
;
375 ASSERT(parent
->avl_back
== np
);
376 parent
->avl_back
= tmp
;
377 direction
= AVL_FORW
;
380 ASSERT(*rootp
== np
);
386 avl64_checktree(tree
, *rootp
);
391 * Remove node from tree.
392 * avl_delete does the local tree manipulations,
393 * calls retreat() to rebalance tree up to its root.
397 register avl64tree_desc_t
*tree
,
398 register avl64node_t
*np
)
400 register avl64node_t
*forw
= np
->avl_forw
;
401 register avl64node_t
*back
= np
->avl_back
;
402 register avl64node_t
*parent
= np
->avl_parent
;
403 register avl64node_t
*nnext
;
408 * a left child exits, then greatest left descendent's nextino
409 * is pointing to np; make it point to np->nextino.
411 nnext
= np
->avl_back
;
413 if (!nnext
->avl_forw
)
414 break; /* can't find anything bigger */
415 nnext
= nnext
->avl_forw
;
418 if (np
->avl_parent
) {
420 * find nearest ancestor with lesser value. That ancestor's
421 * nextino is pointing to np; make it point to np->nextino
423 nnext
= np
->avl_parent
;
425 if (AVL_END(tree
, nnext
) <= AVL_END(tree
, np
))
427 nnext
= nnext
->avl_parent
;
433 ASSERT(nnext
->avl_nextino
== np
);
434 nnext
->avl_nextino
= np
->avl_nextino
;
436 * Something preceeds np; np cannot be firstino.
438 ASSERT(tree
->avl_firstino
!= np
);
442 * Nothing preceeding np; after deletion, np's nextino
443 * is firstino of tree.
445 ASSERT(tree
->avl_firstino
== np
);
446 tree
->avl_firstino
= np
->avl_nextino
;
451 * Degenerate cases...
461 forw
->avl_parent
= parent
;
463 if (parent
->avl_forw
== np
) {
464 parent
->avl_forw
= forw
;
465 retreat(tree
, parent
, AVL_BACK
);
467 ASSERT(parent
->avl_back
== np
);
468 parent
->avl_back
= forw
;
469 retreat(tree
, parent
, AVL_FORW
);
472 ASSERT(tree
->avl_root
== np
);
473 tree
->avl_root
= forw
;
475 avl64_checktree(tree
, tree
->avl_root
);
480 * Harder case: children on both sides.
481 * If back's avl_forw pointer is null, just have back
482 * inherit np's avl_forw tree, remove np from the tree
483 * and adjust balance counters starting at back.
485 * np-> xI xH (befor retreat())
493 if ((forw
= back
->avl_forw
) == NULL
) {
495 * AVL_FORW retreat below will set back's
496 * balance to AVL_BACK.
498 back
->avl_balance
= np
->avl_balance
;
499 back
->avl_forw
= forw
= np
->avl_forw
;
500 forw
->avl_parent
= back
;
501 back
->avl_parent
= parent
;
504 if (parent
->avl_forw
== np
)
505 parent
->avl_forw
= back
;
507 ASSERT(parent
->avl_back
== np
);
508 parent
->avl_back
= back
;
511 ASSERT(tree
->avl_root
== np
);
512 tree
->avl_root
= back
;
516 * back is taking np's place in the tree, and
517 * has therefore lost a avl_back node (itself).
519 retreat(tree
, back
, AVL_FORW
);
520 avl64_checktree(tree
, tree
->avl_root
);
525 * Hardest case: children on both sides, and back's
526 * avl_forw pointer isn't null. Find the immediately
527 * inferior buffer by following back's avl_forw line
528 * to the end, then have it inherit np's avl_forw tree.
532 * G J back-> G J (before retreat())
540 while ((back
= forw
->avl_forw
))
544 * Will be adjusted by retreat() below.
546 forw
->avl_balance
= np
->avl_balance
;
549 * forw inherits np's avl_forw...
551 forw
->avl_forw
= np
->avl_forw
;
552 np
->avl_forw
->avl_parent
= forw
;
555 * ... forw's parent gets forw's avl_back...
557 back
= forw
->avl_parent
;
558 back
->avl_forw
= forw
->avl_back
;
560 forw
->avl_back
->avl_parent
= back
;
563 * ... forw gets np's avl_back...
565 forw
->avl_back
= np
->avl_back
;
566 np
->avl_back
->avl_parent
= forw
;
569 * ... and forw gets np's parent.
571 forw
->avl_parent
= parent
;
574 if (parent
->avl_forw
== np
)
575 parent
->avl_forw
= forw
;
577 parent
->avl_back
= forw
;
579 ASSERT(tree
->avl_root
== np
);
580 tree
->avl_root
= forw
;
584 * What used to be forw's parent is the starting
585 * point for rebalancing. It has lost a avl_forw node.
587 retreat(tree
, back
, AVL_BACK
);
588 avl64_checktree(tree
, tree
->avl_root
);
595 * Given range r [start, end), find any range which is contained in r.
596 * if checklen is non-zero, then only ranges of non-zero length are
597 * considered in finding a match.
601 register avl64tree_desc_t
*tree
,
602 register __uint64_t start
,
603 register __uint64_t end
,
606 register avl64node_t
*np
= tree
->avl_root
;
608 /* np = avl64_findadjacent(tree, start, AVL_SUCCEED); */
610 if (start
< AVL_START(tree
, np
)) {
615 /* if we were to add node with start, would
616 * have a growth of AVL_BACK
618 /* if succeeding node is needed, this is it.
622 if (start
>= AVL_END(tree
, np
)) {
627 /* if we were to add node with start, would
628 * have a growth of AVL_FORW;
630 /* we are looking for a succeeding node;
633 np
= np
->avl_nextino
;
636 /* AVL_START(tree, np) <= start < AVL_END(tree, np) */
640 if (checklen
== AVL_INCLUDE_ZEROLEN
) {
641 if (end
<= AVL_START(tree
, np
)) {
642 /* something follows start, but is
643 * is entierly after the range (end)
647 /* np may stradle [start, end) */
651 * find non-zero length region
653 while (np
&& (AVL_END(tree
, np
) - AVL_START(tree
, np
) == 0)
654 && (AVL_START(tree
, np
) < end
))
655 np
= np
->avl_nextino
;
657 if ((np
== NULL
) || (AVL_START(tree
, np
) >= end
))
662 * nothing succeeds start, all existing ranges are before start.
669 * Returns a pointer to range which contains value.
673 register avl64tree_desc_t
*tree
,
674 register __uint64_t value
)
676 register avl64node_t
*np
= tree
->avl_root
;
679 if (value
< AVL_START(tree
, np
)) {
683 if (value
>= AVL_END(tree
, np
)) {
687 ASSERT(AVL_START(tree
, np
) <= value
&&
688 value
< AVL_END(tree
, np
));
696 * Returns a pointer to node which contains exact value.
700 register avl64tree_desc_t
*tree
,
701 register __uint64_t value
)
703 register avl64node_t
*np
= tree
->avl_root
;
704 register __uint64_t nvalue
;
707 nvalue
= AVL_START(tree
, np
);
708 if (value
< nvalue
) {
712 if (value
== nvalue
) {
722 * Balance buffer AVL tree after attaching a new node to root.
723 * Called only by avl_insert.
727 register avl64node_t
**rootp
,
728 register avl64node_t
*np
,
732 * At this point, np points to the node to which
733 * a new node has been attached. All that remains is to
734 * propagate avl_balance up the tree.
737 register avl64node_t
*parent
= np
->avl_parent
;
738 register avl64node_t
*child
;
740 CERT(growth
== AVL_BACK
|| growth
== AVL_FORW
);
743 * If the buffer was already balanced, set avl_balance
744 * to the new direction. Continue if there is a
745 * parent after setting growth to reflect np's
746 * relation to its parent.
748 if (np
->avl_balance
== AVL_BALANCE
) {
749 np
->avl_balance
= growth
;
751 if (parent
->avl_forw
== np
)
754 ASSERT(parent
->avl_back
== np
);
764 if (growth
!= np
->avl_balance
) {
766 * Subtree is now balanced -- no net effect
767 * in the size of the subtree, so leave.
769 np
->avl_balance
= AVL_BALANCE
;
773 if (growth
== AVL_BACK
) {
775 child
= np
->avl_back
;
776 CERT(np
->avl_balance
== AVL_BACK
&& child
);
778 if (child
->avl_balance
== AVL_BACK
) { /* single LL */
780 * ``A'' just got inserted;
781 * np points to ``E'', child to ``C'',
782 * and it is already AVL_BACK --
783 * child will get promoted to top of subtree.
793 Note that child->avl_parent and
794 avl_balance get set in common code.
796 np
->avl_parent
= child
;
797 np
->avl_balance
= AVL_BALANCE
;
798 np
->avl_back
= child
->avl_forw
;
800 child
->avl_forw
->avl_parent
= np
;
801 child
->avl_forw
= np
;
806 * child's avl_forw node gets promoted to
807 * the top of the subtree.
818 register avl64node_t
*tmp
= child
->avl_forw
;
820 CERT(child
->avl_balance
== AVL_FORW
&& tmp
);
822 child
->avl_forw
= tmp
->avl_back
;
824 tmp
->avl_back
->avl_parent
= child
;
826 tmp
->avl_back
= child
;
827 child
->avl_parent
= tmp
;
829 np
->avl_back
= tmp
->avl_forw
;
831 tmp
->avl_forw
->avl_parent
= np
;
834 np
->avl_parent
= tmp
;
836 if (tmp
->avl_balance
== AVL_BACK
)
837 np
->avl_balance
= AVL_FORW
;
839 np
->avl_balance
= AVL_BALANCE
;
841 if (tmp
->avl_balance
== AVL_FORW
)
842 child
->avl_balance
= AVL_BACK
;
844 child
->avl_balance
= AVL_BALANCE
;
847 * Set child to point to tmp since it is
848 * now the top of the subtree, and will
849 * get attached to the subtree parent in
850 * the common code below.
855 } else /* growth == AVL_BACK */ {
858 * This code is the mirror image of AVL_FORW above.
861 child
= np
->avl_forw
;
862 CERT(np
->avl_balance
== AVL_FORW
&& child
);
864 if (child
->avl_balance
== AVL_FORW
) { /* single RR */
865 np
->avl_parent
= child
;
866 np
->avl_balance
= AVL_BALANCE
;
867 np
->avl_forw
= child
->avl_back
;
869 child
->avl_back
->avl_parent
= np
;
870 child
->avl_back
= np
;
875 register avl64node_t
*tmp
= child
->avl_back
;
877 ASSERT(child
->avl_balance
== AVL_BACK
&& tmp
);
879 child
->avl_back
= tmp
->avl_forw
;
881 tmp
->avl_forw
->avl_parent
= child
;
883 tmp
->avl_forw
= child
;
884 child
->avl_parent
= tmp
;
886 np
->avl_forw
= tmp
->avl_back
;
888 tmp
->avl_back
->avl_parent
= np
;
891 np
->avl_parent
= tmp
;
893 if (tmp
->avl_balance
== AVL_FORW
)
894 np
->avl_balance
= AVL_BACK
;
896 np
->avl_balance
= AVL_BALANCE
;
898 if (tmp
->avl_balance
== AVL_BACK
)
899 child
->avl_balance
= AVL_FORW
;
901 child
->avl_balance
= AVL_BALANCE
;
907 child
->avl_parent
= parent
;
908 child
->avl_balance
= AVL_BALANCE
;
911 if (parent
->avl_back
== np
)
912 parent
->avl_back
= child
;
914 parent
->avl_forw
= child
;
916 ASSERT(*rootp
== np
);
926 avl64_insert_find_growth(
927 register avl64tree_desc_t
*tree
,
928 register __uint64_t start
, /* range start at start, */
929 register __uint64_t end
, /* exclusive */
930 register int *growthp
) /* OUT */
932 avl64node_t
*root
= tree
->avl_root
;
933 register avl64node_t
*np
;
936 ASSERT(np
); /* caller ensures that there is atleast one node in tree */
939 CERT(np
->avl_parent
|| root
== np
);
940 CERT(!np
->avl_parent
|| root
!= np
);
941 CERT(!(np
->avl_back
) || np
->avl_back
->avl_parent
== np
);
942 CERT(!(np
->avl_forw
) || np
->avl_forw
->avl_parent
== np
);
943 CERT(np
->avl_balance
!= AVL_FORW
|| np
->avl_forw
);
944 CERT(np
->avl_balance
!= AVL_BACK
|| np
->avl_back
);
945 CERT(np
->avl_balance
!= AVL_BALANCE
||
946 np
->avl_back
== NULL
|| np
->avl_forw
);
947 CERT(np
->avl_balance
!= AVL_BALANCE
||
948 np
->avl_forw
== NULL
|| np
->avl_back
);
950 if (AVL_START(tree
, np
) >= end
) {
959 if (AVL_END(tree
, np
) <= start
) {
967 /* found exact match -- let caller decide if it is an error */
976 register avl64tree_desc_t
*tree
,
977 register avl64node_t
*parent
,
978 register avl64node_t
*newnode
,
981 register avl64node_t
*nnext
;
982 register __uint64_t start
= AVL_START(tree
, newnode
);
984 if (growth
== AVL_BACK
) {
986 parent
->avl_back
= newnode
;
988 * we are growing to the left; previous in-order to newnode is
989 * closest ancestor with lesser value. Before this
990 * insertion, this ancestor will be pointing to
991 * newnode's parent. After insertion, next in-order to newnode
994 newnode
->avl_nextino
= parent
;
997 if (AVL_END(tree
, nnext
) <= start
)
999 nnext
= nnext
->avl_parent
;
1003 * nnext will be null if newnode is
1004 * the least element, and hence very first in the list.
1006 ASSERT(nnext
->avl_nextino
== parent
);
1007 nnext
->avl_nextino
= newnode
;
1011 parent
->avl_forw
= newnode
;
1012 newnode
->avl_nextino
= parent
->avl_nextino
;
1013 parent
->avl_nextino
= newnode
;
1020 register avl64tree_desc_t
*tree
,
1021 register avl64node_t
*newnode
)
1023 register avl64node_t
*np
;
1024 register __uint64_t start
= AVL_START(tree
, newnode
);
1025 register __uint64_t end
= AVL_END(tree
, newnode
);
1030 * Clean all pointers for sanity; some will be reset as necessary.
1032 newnode
->avl_nextino
= NULL
;
1033 newnode
->avl_parent
= NULL
;
1034 newnode
->avl_forw
= NULL
;
1035 newnode
->avl_back
= NULL
;
1036 newnode
->avl_balance
= AVL_BALANCE
;
1038 if ((np
= tree
->avl_root
) == NULL
) { /* degenerate case... */
1039 tree
->avl_root
= newnode
;
1040 tree
->avl_firstino
= newnode
;
1044 if ((np
= avl64_insert_find_growth(tree
, start
, end
, &growth
))
1046 if (start
!= end
) { /* non-zero length range */
1048 "avl_insert: Warning! duplicate range [%llu,%llu]\n",
1049 (unsigned long long)start
,
1050 (unsigned long long)end
);
1055 avl64_insert_grow(tree
, np
, newnode
, growth
);
1056 if (growth
== AVL_BACK
) {
1058 * Growing to left. if np was firstino, newnode will be firstino
1060 if (tree
->avl_firstino
== np
)
1061 tree
->avl_firstino
= newnode
;
1065 if (growth
== AVL_FORW
)
1067 * Cannot possibly be firstino; there is somebody to our left.
1072 newnode
->avl_parent
= np
;
1073 CERT(np
->avl_forw
== newnode
|| np
->avl_back
== newnode
);
1075 avl64_balance(&tree
->avl_root
, np
, growth
);
1077 avl64_checktree(tree
, tree
->avl_root
);
1084 * avl64_insert_immediate(tree, afterp, newnode):
1085 * insert newnode immediately into tree immediately after afterp.
1086 * after insertion, newnode is right child of afterp.
1089 avl64_insert_immediate(
1090 avl64tree_desc_t
*tree
,
1091 avl64node_t
*afterp
,
1092 avl64node_t
*newnode
)
1095 * Clean all pointers for sanity; some will be reset as necessary.
1097 newnode
->avl_nextino
= NULL
;
1098 newnode
->avl_parent
= NULL
;
1099 newnode
->avl_forw
= NULL
;
1100 newnode
->avl_back
= NULL
;
1101 newnode
->avl_balance
= AVL_BALANCE
;
1103 if (afterp
== NULL
) {
1104 tree
->avl_root
= newnode
;
1105 tree
->avl_firstino
= newnode
;
1109 ASSERT(afterp
->avl_forw
== NULL
);
1110 avl64_insert_grow(tree
, afterp
, newnode
, AVL_FORW
); /* grow to right */
1111 CERT(afterp
->avl_forw
== newnode
);
1112 avl64_balance(&tree
->avl_root
, afterp
, AVL_FORW
);
1113 avl64_checktree(tree
, tree
->avl_root
);
1118 * Returns first in order node
1121 avl64_firstino(register avl64node_t
*root
)
1123 register avl64node_t
*np
;
1125 if ((np
= root
) == NULL
)
1128 while (np
->avl_back
)
1134 * Returns last in order node
1137 avl64_lastino(register avl64node_t
*root
)
1139 register avl64node_t
*np
;
1141 if ((np
= root
) == NULL
)
1144 while (np
->avl_forw
)
1150 avl64_init_tree(avl64tree_desc_t
*tree
, avl64ops_t
*ops
)
1152 tree
->avl_root
= NULL
;
1153 tree
->avl_firstino
= NULL
;
1154 tree
->avl_ops
= ops
;
1159 avl64_printnode(avl64tree_desc_t
*tree
, avl64node_t
*np
, int nl
)
1161 printf("[%d-%d]%c", AVL_START(tree
, np
),
1162 (AVL_END(tree
, np
) - 1), nl
? '\n' : ' ');
1165 #ifdef STAND_ALONE_DEBUG
1167 struct avl_debug_node
{
1168 avl64node_t avl_node
;
1169 xfs_off_t avl_start
;
1170 unsigned int avl_size
;
1173 avl64ops_t avl_debug_ops
= {
1179 avl64_debug_start(avl64node_t
*node
)
1181 return (__uint64_t
)(struct avl_debug_node
*)node
->avl_start
;
1185 avl64_debug_end(avl64node_t
*node
)
1188 ((struct avl_debug_node
*)node
->avl_start
+
1189 (struct avl_debug_node
*)node
->avl_size
);
1192 avl_debug_node freenodes
[100];
1193 avl_debug_node
*freehead
= &freenodes
[0];
1195 static avl64node_t
*
1196 alloc_avl64_debug_node()
1198 freehead
->avl_balance
= AVL_BALANCE
;
1199 freehead
->avl_parent
= freehead
->avl_forw
= freehead
->avl_back
= NULL
;
1204 avl64_print(avl64tree_desc_t
*tree
, avl64node_t
*root
, int depth
)
1211 avl64_print(tree
, root
->avl_forw
, depth
+5);
1212 for (i
= 0; i
< depth
; i
++)
1214 avl64_printnode(tree
, root
,1);
1216 avl64_print(tree
, root
->avl_back
, depth
+5);
1223 avl64tree_desc_t tree
;
1224 char linebuf
[256], cmd
[256];
1226 avl64_init_tree(&tree
, &avl_debug_ops
);
1228 for (i
= 100; i
> 0; i
= i
- 10)
1230 np
= alloc__debug_avlnode();
1234 avl64_insert(&tree
, np
);
1236 avl64_print(&tree
, tree
.avl_root
, 0);
1238 for (np
= tree
.avl_firstino
; np
!= NULL
; np
= np
->avl_nextino
)
1239 avl64_printnode(&tree
, np
, 0);
1243 printf("Command [fpdir] : ");
1244 fgets(linebuf
, 256, stdin
);
1245 if (feof(stdin
)) break;
1247 if (sscanf(linebuf
, "%[fpdir]%d", cmd
, &i
) != 2)
1252 printf("end of range ? ");
1253 fgets(linebuf
, 256, stdin
);
1256 if (i
== j
) j
= i
+1;
1257 np
= avl64_findinrange(&tree
,i
,j
);
1259 avl64_printnode(&tree
, np
, 1);
1261 avl64_delete(&tree
, np
);
1263 printf("Cannot find %d\n", i
);
1266 avl64_print(&tree
, tree
.avl_root
, 0);
1267 for (np
= tree
.avl_firstino
;
1268 np
!= NULL
; np
= np
->avl_nextino
)
1269 avl64_printnode(&tree
, np
, 0);
1273 np
= alloc_avlnode();
1276 printf("size of range ? ");
1277 fgets(linebuf
, 256, stdin
);
1281 avl64_insert(&tree
, np
);
1284 avl64node_t
*b
, *e
, *t
;
1287 printf("End of range ? ");
1288 fgets(linebuf
, 256, stdin
);
1291 printf("checklen 0/1 ? ");
1292 fgets(linebuf
, 256, stdin
);
1293 checklen
= atoi(linebuf
);
1296 b
= avl64_findanyrange(&tree
, i
, j
, checklen
);
1298 printf("Found something\n");
1302 AVL_START(&tree
, t
) >= j
)
1304 avl64_printnode(&tree
, t
, 0);
1316 * Given a tree, find value; will find return range enclosing value,
1317 * or range immediately succeeding value,
1318 * or range immediately preceeding value.
1322 register avl64tree_desc_t
*tree
,
1323 register __uint64_t value
,
1326 register avl64node_t
*np
= tree
->avl_root
;
1329 if (value
< AVL_START(tree
, np
)) {
1334 /* if we were to add node with value, would
1335 * have a growth of AVL_BACK
1337 if (dir
== AVL_SUCCEED
) {
1338 /* if succeeding node is needed, this is it.
1342 if (dir
== AVL_PRECEED
) {
1344 * find nearest ancestor with lesser value.
1346 np
= np
->avl_parent
;
1348 if (AVL_END(tree
, np
) <= value
)
1350 np
= np
->avl_parent
;
1354 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1357 if (value
>= AVL_END(tree
, np
)) {
1362 /* if we were to add node with value, would
1363 * have a growth of AVL_FORW;
1365 if (dir
== AVL_SUCCEED
) {
1366 /* we are looking for a succeeding node;
1369 return(np
->avl_nextino
);
1371 if (dir
== AVL_PRECEED
) {
1372 /* looking for a preceeding node; this is it. */
1375 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1377 /* AVL_START(tree, np) <= value < AVL_END(tree, np) */
1387 * Given range r [start, end), find all ranges in tree which are contained
1388 * in r. At return, startp and endp point to first and last of
1389 * a chain of elements which describe the contained ranges. Elements
1390 * in startp ... endp are in sort order, and can be accessed by
1391 * using avl_nextino.
1396 register avl64tree_desc_t
*tree
,
1397 register __uint64_t start
,
1398 register __uint64_t end
,
1399 avl64node_t
**startp
,
1402 register avl64node_t
*np
;
1404 np
= avl64_findadjacent(tree
, start
, AVL_SUCCEED
);
1405 if (np
== NULL
/* nothing succeding start */
1406 || (np
&& (end
<= AVL_START(tree
, np
))))
1407 /* something follows start,
1408 but... is entirely after end */
1417 /* see if end is in this region itself */
1418 if (end
<= AVL_END(tree
, np
) ||
1419 np
->avl_nextino
== NULL
||
1421 (end
<= AVL_START(tree
, np
->avl_nextino
)))) {
1425 /* have to munge for end */
1427 * note: have to look for (end - 1), since
1428 * findadjacent will look for exact value, and does not
1429 * care about the fact that end is actually one more
1430 * than the value actually being looked for; thus feed it one less.
1432 *endp
= avl64_findadjacent(tree
, (end
-1), AVL_PRECEED
);