]>
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 **************************************************************************/
35 /* to allow use by user-level utilities */
37 #ifdef STAND_ALONE_DEBUG
41 #if defined(STAND_ALONE_DEBUG) || defined(AVL_USER_MODE_DEBUG)
55 register avl64tree_desc_t
*tree
,
56 register avl64node_t
*np
)
58 register avl64node_t
*back
= np
->avl_back
;
59 register avl64node_t
*forw
= np
->avl_forw
;
60 register avl64node_t
*nextino
= np
->avl_nextino
;
61 register int bal
= np
->avl_balance
;
63 ASSERT(bal
!= AVL_BALANCE
|| (!back
&& !forw
) || (back
&& forw
));
64 ASSERT(bal
!= AVL_FORW
|| forw
);
65 ASSERT(bal
!= AVL_BACK
|| back
);
68 ASSERT(AVL_START(tree
, np
) < AVL_START(tree
, forw
));
69 ASSERT(np
->avl_forw
->avl_parent
== np
);
70 ASSERT(back
|| bal
== AVL_FORW
);
72 ASSERT(bal
!= AVL_FORW
);
73 ASSERT(bal
== AVL_BALANCE
|| back
);
74 ASSERT(bal
== AVL_BACK
|| !back
);
78 ASSERT(AVL_START(tree
, np
) > AVL_START(tree
, back
));
79 ASSERT(np
->avl_back
->avl_parent
== np
);
80 ASSERT(forw
|| bal
== AVL_BACK
);
82 ASSERT(bal
!= AVL_BACK
);
83 ASSERT(bal
== AVL_BALANCE
|| forw
);
84 ASSERT(bal
== AVL_FORW
|| !forw
);
90 ASSERT(AVL_END(tree
, np
) <= AVL_START(tree
, nextino
));
95 register avl64tree_desc_t
*tree
,
96 register avl64node_t
*root
)
98 register avl64node_t
*nlast
, *nnext
, *np
;
99 __uint64_t offset
= 0;
102 nlast
= nnext
= root
;
104 ASSERT(!nnext
|| nnext
->avl_parent
== NULL
);
108 avl64_checknode(tree
, nnext
);
109 end
= AVL_END(tree
, nnext
);
112 if ((np
= nnext
->avl_forw
) && np
!= nlast
) {
117 nnext
= nnext
->avl_parent
;
123 if (np
= nnext
->avl_back
) {
124 if (AVL_END(tree
, np
) > offset
) {
131 nnext
= nnext
->avl_forw
;
133 nnext
= np
->avl_parent
;
138 #else /* ! AVL_DEBUG */
139 #define avl64_checktree(t,x)
140 #endif /* AVL_DEBUG */
144 * Reset balance for np up through tree.
145 * ``direction'' is the way that np's balance
146 * is headed after the deletion of one of its children --
147 * e.g., deleting a avl_forw child sends avl_balance toward AVL_BACK.
148 * Called only when deleting a node from the tree.
152 avl64tree_desc_t
*tree
,
153 register avl64node_t
*np
,
154 register int direction
)
156 register avl64node_t
**rootp
= &tree
->avl_root
;
157 register avl64node_t
*parent
;
158 register avl64node_t
*child
;
159 register avl64node_t
*tmp
;
163 ASSERT(direction
== AVL_BACK
|| direction
== AVL_FORW
);
165 if (np
->avl_balance
== AVL_BALANCE
) {
166 np
->avl_balance
= direction
;
170 parent
= np
->avl_parent
;
173 * If balance is being restored, no local node
174 * reorganization is necessary, but may be at
175 * a higher node. Reset direction and continue.
177 if (direction
!= np
->avl_balance
) {
178 np
->avl_balance
= AVL_BALANCE
;
180 if (parent
->avl_forw
== np
)
181 direction
= AVL_BACK
;
183 direction
= AVL_FORW
;
192 * Imbalance. If a avl_forw node was removed, direction
193 * (and, by reduction, np->avl_balance) is/was AVL_BACK.
195 if (np
->avl_balance
== AVL_BACK
) {
197 ASSERT(direction
== AVL_BACK
);
198 child
= np
->avl_back
;
199 bal
= child
->avl_balance
;
201 if (bal
!= AVL_FORW
) /* single LL */ {
203 * np gets pushed down to lesser child's
208 * child-> B deleted A -D
211 cmn_err(CE_CONT, "!LL delete b 0x%x c 0x%x\n",
215 np
->avl_back
= child
->avl_forw
;
217 child
->avl_forw
->avl_parent
= np
;
218 child
->avl_forw
= np
;
221 if (parent
->avl_forw
== np
) {
222 parent
->avl_forw
= child
;
223 direction
= AVL_BACK
;
225 ASSERT(parent
->avl_back
== np
);
226 parent
->avl_back
= child
;
227 direction
= AVL_FORW
;
230 ASSERT(*rootp
== np
);
233 np
->avl_parent
= child
;
234 child
->avl_parent
= parent
;
236 if (bal
== AVL_BALANCE
) {
237 np
->avl_balance
= AVL_BACK
;
238 child
->avl_balance
= AVL_FORW
;
241 np
->avl_balance
= AVL_BALANCE
;
242 child
->avl_balance
= AVL_BALANCE
;
244 avl64_checktree(tree
, *rootp
);
249 /* child->avl_balance == AVL_FORW double LR rotation
251 * child's avl_forw node gets promoted up, along with
252 * its avl_forw subtree
261 cmn_err(CE_CONT, "!LR delete b 0x%x c 0x%x t 0x%x\n",
262 np, child, child->avl_forw);
265 tmp
= child
->avl_forw
;
266 bal
= tmp
->avl_balance
;
268 child
->avl_forw
= tmp
->avl_back
;
270 tmp
->avl_back
->avl_parent
= child
;
272 tmp
->avl_back
= child
;
273 child
->avl_parent
= tmp
;
275 np
->avl_back
= tmp
->avl_forw
;
277 tmp
->avl_forw
->avl_parent
= np
;
281 child
->avl_balance
= AVL_BACK
;
283 child
->avl_balance
= AVL_BALANCE
;
286 np
->avl_balance
= AVL_FORW
;
288 np
->avl_balance
= AVL_BALANCE
;
293 ASSERT(np
->avl_balance
== AVL_FORW
&& direction
== AVL_FORW
);
295 child
= np
->avl_forw
;
296 bal
= child
->avl_balance
;
298 if (bal
!= AVL_BACK
) /* single RR */ {
300 * np gets pushed down to greater child's
305 * deleted D <-child +B E
308 cmn_err(CE_CONT, "!RR delete b 0x%x c 0x%x\n",
312 np
->avl_forw
= child
->avl_back
;
314 child
->avl_back
->avl_parent
= np
;
315 child
->avl_back
= np
;
318 if (parent
->avl_forw
== np
) {
319 parent
->avl_forw
= child
;
320 direction
= AVL_BACK
;
322 ASSERT(parent
->avl_back
== np
);
323 parent
->avl_back
= child
;
324 direction
= AVL_FORW
;
327 ASSERT(*rootp
== np
);
330 np
->avl_parent
= child
;
331 child
->avl_parent
= parent
;
333 if (bal
== AVL_BALANCE
) {
334 np
->avl_balance
= AVL_FORW
;
335 child
->avl_balance
= AVL_BACK
;
338 np
->avl_balance
= AVL_BALANCE
;
339 child
->avl_balance
= AVL_BALANCE
;
341 avl64_checktree(tree
, *rootp
);
346 /* child->avl_balance == AVL_BACK double RL rotation
347 cmn_err(CE_CONT, "!RL delete b 0x%x c 0x%x t 0x%x\n",
348 np, child, child->avl_back);
351 tmp
= child
->avl_back
;
352 bal
= tmp
->avl_balance
;
354 child
->avl_back
= tmp
->avl_forw
;
356 tmp
->avl_forw
->avl_parent
= child
;
358 tmp
->avl_forw
= child
;
359 child
->avl_parent
= tmp
;
361 np
->avl_forw
= tmp
->avl_back
;
363 tmp
->avl_back
->avl_parent
= np
;
367 child
->avl_balance
= AVL_FORW
;
369 child
->avl_balance
= AVL_BALANCE
;
372 np
->avl_balance
= AVL_BACK
;
374 np
->avl_balance
= AVL_BALANCE
;
376 np
->avl_parent
= tmp
;
377 tmp
->avl_balance
= AVL_BALANCE
;
378 tmp
->avl_parent
= parent
;
381 if (parent
->avl_forw
== np
) {
382 parent
->avl_forw
= tmp
;
383 direction
= AVL_BACK
;
385 ASSERT(parent
->avl_back
== np
);
386 parent
->avl_back
= tmp
;
387 direction
= AVL_FORW
;
390 ASSERT(*rootp
== np
);
396 avl64_checktree(tree
, *rootp
);
401 * Remove node from tree.
402 * avl_delete does the local tree manipulations,
403 * calls retreat() to rebalance tree up to its root.
407 register avl64tree_desc_t
*tree
,
408 register avl64node_t
*np
)
410 register avl64node_t
*forw
= np
->avl_forw
;
411 register avl64node_t
*back
= np
->avl_back
;
412 register avl64node_t
*parent
= np
->avl_parent
;
413 register avl64node_t
*nnext
;
418 * a left child exits, then greatest left descendent's nextino
419 * is pointing to np; make it point to np->nextino.
421 nnext
= np
->avl_back
;
423 if (!nnext
->avl_forw
)
424 break; /* can't find anything bigger */
425 nnext
= nnext
->avl_forw
;
428 if (np
->avl_parent
) {
430 * find nearest ancestor with lesser value. That ancestor's
431 * nextino is pointing to np; make it point to np->nextino
433 nnext
= np
->avl_parent
;
435 if (AVL_END(tree
, nnext
) <= AVL_END(tree
, np
))
437 nnext
= nnext
->avl_parent
;
443 ASSERT(nnext
->avl_nextino
== np
);
444 nnext
->avl_nextino
= np
->avl_nextino
;
446 * Something preceeds np; np cannot be firstino.
448 ASSERT(tree
->avl_firstino
!= np
);
452 * Nothing preceeding np; after deletion, np's nextino
453 * is firstino of tree.
455 ASSERT(tree
->avl_firstino
== np
);
456 tree
->avl_firstino
= np
->avl_nextino
;
461 * Degenerate cases...
471 forw
->avl_parent
= parent
;
473 if (parent
->avl_forw
== np
) {
474 parent
->avl_forw
= forw
;
475 retreat(tree
, parent
, AVL_BACK
);
477 ASSERT(parent
->avl_back
== np
);
478 parent
->avl_back
= forw
;
479 retreat(tree
, parent
, AVL_FORW
);
482 ASSERT(tree
->avl_root
== np
);
483 tree
->avl_root
= forw
;
485 avl64_checktree(tree
, tree
->avl_root
);
490 * Harder case: children on both sides.
491 * If back's avl_forw pointer is null, just have back
492 * inherit np's avl_forw tree, remove np from the tree
493 * and adjust balance counters starting at back.
495 * np-> xI xH (befor retreat())
503 if ((forw
= back
->avl_forw
) == NULL
) {
505 * AVL_FORW retreat below will set back's
506 * balance to AVL_BACK.
508 back
->avl_balance
= np
->avl_balance
;
509 back
->avl_forw
= forw
= np
->avl_forw
;
510 forw
->avl_parent
= back
;
511 back
->avl_parent
= parent
;
514 if (parent
->avl_forw
== np
)
515 parent
->avl_forw
= back
;
517 ASSERT(parent
->avl_back
== np
);
518 parent
->avl_back
= back
;
521 ASSERT(tree
->avl_root
== np
);
522 tree
->avl_root
= back
;
526 * back is taking np's place in the tree, and
527 * has therefore lost a avl_back node (itself).
529 retreat(tree
, back
, AVL_FORW
);
530 avl64_checktree(tree
, tree
->avl_root
);
535 * Hardest case: children on both sides, and back's
536 * avl_forw pointer isn't null. Find the immediately
537 * inferior buffer by following back's avl_forw line
538 * to the end, then have it inherit np's avl_forw tree.
542 * G J back-> G J (before retreat())
550 while (back
= forw
->avl_forw
)
554 * Will be adjusted by retreat() below.
556 forw
->avl_balance
= np
->avl_balance
;
559 * forw inherits np's avl_forw...
561 forw
->avl_forw
= np
->avl_forw
;
562 np
->avl_forw
->avl_parent
= forw
;
565 * ... forw's parent gets forw's avl_back...
567 back
= forw
->avl_parent
;
568 back
->avl_forw
= forw
->avl_back
;
570 forw
->avl_back
->avl_parent
= back
;
573 * ... forw gets np's avl_back...
575 forw
->avl_back
= np
->avl_back
;
576 np
->avl_back
->avl_parent
= forw
;
579 * ... and forw gets np's parent.
581 forw
->avl_parent
= parent
;
584 if (parent
->avl_forw
== np
)
585 parent
->avl_forw
= forw
;
587 parent
->avl_back
= forw
;
589 ASSERT(tree
->avl_root
== np
);
590 tree
->avl_root
= forw
;
594 * What used to be forw's parent is the starting
595 * point for rebalancing. It has lost a avl_forw node.
597 retreat(tree
, back
, AVL_BACK
);
598 avl64_checktree(tree
, tree
->avl_root
);
605 * Given range r [start, end), find any range which is contained in r.
606 * if checklen is non-zero, then only ranges of non-zero length are
607 * considered in finding a match.
611 register avl64tree_desc_t
*tree
,
612 register __uint64_t start
,
613 register __uint64_t end
,
616 register avl64node_t
*np
= tree
->avl_root
;
618 /* np = avl64_findadjacent(tree, start, AVL_SUCCEED); */
620 if (start
< AVL_START(tree
, np
)) {
625 /* if we were to add node with start, would
626 * have a growth of AVL_BACK
628 /* if succeeding node is needed, this is it.
632 if (start
>= AVL_END(tree
, np
)) {
637 /* if we were to add node with start, would
638 * have a growth of AVL_FORW;
640 /* we are looking for a succeeding node;
643 np
= np
->avl_nextino
;
646 /* AVL_START(tree, np) <= start < AVL_END(tree, np) */
650 if (checklen
== AVL_INCLUDE_ZEROLEN
) {
651 if (end
<= AVL_START(tree
, np
)) {
652 /* something follows start, but is
653 * is entierly after the range (end)
657 /* np may stradle [start, end) */
661 * find non-zero length region
663 while (np
&& (AVL_END(tree
, np
) - AVL_START(tree
, np
) == 0)
664 && (AVL_START(tree
, np
) < end
))
665 np
= np
->avl_nextino
;
667 if ((np
== NULL
) || (AVL_START(tree
, np
) >= end
))
672 * nothing succeeds start, all existing ranges are before start.
679 * Returns a pointer to range which contains value.
683 register avl64tree_desc_t
*tree
,
684 register __uint64_t value
)
686 register avl64node_t
*np
= tree
->avl_root
;
689 if (value
< AVL_START(tree
, np
)) {
693 if (value
>= AVL_END(tree
, np
)) {
697 ASSERT(AVL_START(tree
, np
) <= value
&&
698 value
< AVL_END(tree
, np
));
706 * Returns a pointer to node which contains exact value.
710 register avl64tree_desc_t
*tree
,
711 register __uint64_t value
)
713 register avl64node_t
*np
= tree
->avl_root
;
714 register __uint64_t nvalue
;
717 nvalue
= AVL_START(tree
, np
);
718 if (value
< nvalue
) {
722 if (value
== nvalue
) {
732 * Balance buffer AVL tree after attaching a new node to root.
733 * Called only by avl_insert.
737 register avl64node_t
**rootp
,
738 register avl64node_t
*np
,
742 * At this point, np points to the node to which
743 * a new node has been attached. All that remains is to
744 * propagate avl_balance up the tree.
747 register avl64node_t
*parent
= np
->avl_parent
;
748 register avl64node_t
*child
;
750 CERT(growth
== AVL_BACK
|| growth
== AVL_FORW
);
753 * If the buffer was already balanced, set avl_balance
754 * to the new direction. Continue if there is a
755 * parent after setting growth to reflect np's
756 * relation to its parent.
758 if (np
->avl_balance
== AVL_BALANCE
) {
759 np
->avl_balance
= growth
;
761 if (parent
->avl_forw
== np
)
764 ASSERT(parent
->avl_back
== np
);
774 if (growth
!= np
->avl_balance
) {
776 * Subtree is now balanced -- no net effect
777 * in the size of the subtree, so leave.
779 np
->avl_balance
= AVL_BALANCE
;
783 if (growth
== AVL_BACK
) {
785 child
= np
->avl_back
;
786 CERT(np
->avl_balance
== AVL_BACK
&& child
);
788 if (child
->avl_balance
== AVL_BACK
) { /* single LL */
790 * ``A'' just got inserted;
791 * np points to ``E'', child to ``C'',
792 * and it is already AVL_BACK --
793 * child will get promoted to top of subtree.
803 Note that child->avl_parent and
804 avl_balance get set in common code.
806 np
->avl_parent
= child
;
807 np
->avl_balance
= AVL_BALANCE
;
808 np
->avl_back
= child
->avl_forw
;
810 child
->avl_forw
->avl_parent
= np
;
811 child
->avl_forw
= np
;
816 * child's avl_forw node gets promoted to
817 * the top of the subtree.
828 register avl64node_t
*tmp
= child
->avl_forw
;
830 CERT(child
->avl_balance
== AVL_FORW
&& tmp
);
832 child
->avl_forw
= tmp
->avl_back
;
834 tmp
->avl_back
->avl_parent
= child
;
836 tmp
->avl_back
= child
;
837 child
->avl_parent
= tmp
;
839 np
->avl_back
= tmp
->avl_forw
;
841 tmp
->avl_forw
->avl_parent
= np
;
844 np
->avl_parent
= tmp
;
846 if (tmp
->avl_balance
== AVL_BACK
)
847 np
->avl_balance
= AVL_FORW
;
849 np
->avl_balance
= AVL_BALANCE
;
851 if (tmp
->avl_balance
== AVL_FORW
)
852 child
->avl_balance
= AVL_BACK
;
854 child
->avl_balance
= AVL_BALANCE
;
857 * Set child to point to tmp since it is
858 * now the top of the subtree, and will
859 * get attached to the subtree parent in
860 * the common code below.
865 } else /* growth == AVL_BACK */ {
868 * This code is the mirror image of AVL_FORW above.
871 child
= np
->avl_forw
;
872 CERT(np
->avl_balance
== AVL_FORW
&& child
);
874 if (child
->avl_balance
== AVL_FORW
) { /* single RR */
875 np
->avl_parent
= child
;
876 np
->avl_balance
= AVL_BALANCE
;
877 np
->avl_forw
= child
->avl_back
;
879 child
->avl_back
->avl_parent
= np
;
880 child
->avl_back
= np
;
885 register avl64node_t
*tmp
= child
->avl_back
;
887 ASSERT(child
->avl_balance
== AVL_BACK
&& tmp
);
889 child
->avl_back
= tmp
->avl_forw
;
891 tmp
->avl_forw
->avl_parent
= child
;
893 tmp
->avl_forw
= child
;
894 child
->avl_parent
= tmp
;
896 np
->avl_forw
= tmp
->avl_back
;
898 tmp
->avl_back
->avl_parent
= np
;
901 np
->avl_parent
= tmp
;
903 if (tmp
->avl_balance
== AVL_FORW
)
904 np
->avl_balance
= AVL_BACK
;
906 np
->avl_balance
= AVL_BALANCE
;
908 if (tmp
->avl_balance
== AVL_BACK
)
909 child
->avl_balance
= AVL_FORW
;
911 child
->avl_balance
= AVL_BALANCE
;
917 child
->avl_parent
= parent
;
918 child
->avl_balance
= AVL_BALANCE
;
921 if (parent
->avl_back
== np
)
922 parent
->avl_back
= child
;
924 parent
->avl_forw
= child
;
926 ASSERT(*rootp
== np
);
936 avl64_insert_find_growth(
937 register avl64tree_desc_t
*tree
,
938 register __uint64_t start
, /* range start at start, */
939 register __uint64_t end
, /* exclusive */
940 register int *growthp
) /* OUT */
942 avl64node_t
*root
= tree
->avl_root
;
943 register avl64node_t
*np
;
946 ASSERT(np
); /* caller ensures that there is atleast one node in tree */
949 CERT(np
->avl_parent
|| root
== np
);
950 CERT(!np
->avl_parent
|| root
!= np
);
951 CERT(!(np
->avl_back
) || np
->avl_back
->avl_parent
== np
);
952 CERT(!(np
->avl_forw
) || np
->avl_forw
->avl_parent
== np
);
953 CERT(np
->avl_balance
!= AVL_FORW
|| np
->avl_forw
);
954 CERT(np
->avl_balance
!= AVL_BACK
|| np
->avl_back
);
955 CERT(np
->avl_balance
!= AVL_BALANCE
||
956 np
->avl_back
== NULL
|| np
->avl_forw
);
957 CERT(np
->avl_balance
!= AVL_BALANCE
||
958 np
->avl_forw
== NULL
|| np
->avl_back
);
960 if (AVL_START(tree
, np
) >= end
) {
969 if (AVL_END(tree
, np
) <= start
) {
977 /* found exact match -- let caller decide if it is an error */
986 register avl64tree_desc_t
*tree
,
987 register avl64node_t
*parent
,
988 register avl64node_t
*newnode
,
991 register avl64node_t
*nnext
;
992 register __uint64_t start
= AVL_START(tree
, newnode
);
994 if (growth
== AVL_BACK
) {
996 parent
->avl_back
= newnode
;
998 * we are growing to the left; previous in-order to newnode is
999 * closest ancestor with lesser value. Before this
1000 * insertion, this ancestor will be pointing to
1001 * newnode's parent. After insertion, next in-order to newnode
1004 newnode
->avl_nextino
= parent
;
1007 if (AVL_END(tree
, nnext
) <= start
)
1009 nnext
= nnext
->avl_parent
;
1013 * nnext will be null if newnode is
1014 * the least element, and hence very first in the list.
1016 ASSERT(nnext
->avl_nextino
== parent
);
1017 nnext
->avl_nextino
= newnode
;
1021 parent
->avl_forw
= newnode
;
1022 newnode
->avl_nextino
= parent
->avl_nextino
;
1023 parent
->avl_nextino
= newnode
;
1030 register avl64tree_desc_t
*tree
,
1031 register avl64node_t
*newnode
)
1033 register avl64node_t
*np
;
1034 register __uint64_t start
= AVL_START(tree
, newnode
);
1035 register __uint64_t end
= AVL_END(tree
, newnode
);
1040 * Clean all pointers for sanity; some will be reset as necessary.
1042 newnode
->avl_nextino
= NULL
;
1043 newnode
->avl_parent
= NULL
;
1044 newnode
->avl_forw
= NULL
;
1045 newnode
->avl_back
= NULL
;
1046 newnode
->avl_balance
= AVL_BALANCE
;
1048 if ((np
= tree
->avl_root
) == NULL
) { /* degenerate case... */
1049 tree
->avl_root
= newnode
;
1050 tree
->avl_firstino
= newnode
;
1054 if ((np
= avl64_insert_find_growth(tree
, start
, end
, &growth
))
1056 if (start
!= end
) { /* non-zero length range */
1057 #ifdef AVL_USER_MODE
1058 printf("avl_insert: Warning! duplicate range [0x%llx,0x%llx)\n",
1059 (unsigned long long)start
, (unsigned long long)end
);
1062 "!avl_insert: Warning! duplicate range [0x%llx,0x%llx)\n",
1069 avl64_insert_grow(tree
, np
, newnode
, growth
);
1070 if (growth
== AVL_BACK
) {
1072 * Growing to left. if np was firstino, newnode will be firstino
1074 if (tree
->avl_firstino
== np
)
1075 tree
->avl_firstino
= newnode
;
1079 if (growth
== AVL_FORW
)
1081 * Cannot possibly be firstino; there is somebody to our left.
1086 newnode
->avl_parent
= np
;
1087 CERT(np
->avl_forw
== newnode
|| np
->avl_back
== newnode
);
1089 avl64_balance(&tree
->avl_root
, np
, growth
);
1091 avl64_checktree(tree
, tree
->avl_root
);
1098 * avl64_insert_immediate(tree, afterp, newnode):
1099 * insert newnode immediately into tree immediately after afterp.
1100 * after insertion, newnode is right child of afterp.
1103 avl64_insert_immediate(
1104 avl64tree_desc_t
*tree
,
1105 avl64node_t
*afterp
,
1106 avl64node_t
*newnode
)
1109 * Clean all pointers for sanity; some will be reset as necessary.
1111 newnode
->avl_nextino
= NULL
;
1112 newnode
->avl_parent
= NULL
;
1113 newnode
->avl_forw
= NULL
;
1114 newnode
->avl_back
= NULL
;
1115 newnode
->avl_balance
= AVL_BALANCE
;
1117 if (afterp
== NULL
) {
1118 tree
->avl_root
= newnode
;
1119 tree
->avl_firstino
= newnode
;
1123 ASSERT(afterp
->avl_forw
== NULL
);
1124 avl64_insert_grow(tree
, afterp
, newnode
, AVL_FORW
); /* grow to right */
1125 CERT(afterp
->avl_forw
== newnode
);
1126 avl64_balance(&tree
->avl_root
, afterp
, AVL_FORW
);
1127 avl64_checktree(tree
, tree
->avl_root
);
1132 * Returns first in order node
1135 avl64_firstino(register avl64node_t
*root
)
1137 register avl64node_t
*np
;
1139 if ((np
= root
) == NULL
)
1142 while (np
->avl_back
)
1147 #ifdef AVL_USER_MODE
1149 * leave this as a user-mode only routine until someone actually
1150 * needs it in the kernel
1154 * Returns last in order node
1157 avl64_lastino(register avl64node_t
*root
)
1159 register avl64node_t
*np
;
1161 if ((np
= root
) == NULL
)
1164 while (np
->avl_forw
)
1171 avl64_init_tree(avl64tree_desc_t
*tree
, avl64ops_t
*ops
)
1173 tree
->avl_root
= NULL
;
1174 tree
->avl_firstino
= NULL
;
1175 tree
->avl_ops
= ops
;
1180 avl64_printnode(avl64tree_desc_t
*tree
, avl64node_t
*np
, int nl
)
1182 printf("[%d-%d]%c", AVL_START(tree
, np
),
1183 (AVL_END(tree
, np
) - 1), nl
? '\n' : ' ');
1186 #ifdef STAND_ALONE_DEBUG
1188 struct avl_debug_node
{
1189 avl64node_t avl_node
;
1190 xfs_off_t avl_start
;
1191 unsigned int avl_size
;
1194 avl64ops_t avl_debug_ops
= {
1200 avl64_debug_start(avl64node_t
*node
)
1202 return (__uint64_t
)(struct avl_debug_node
*)node
->avl_start
;
1206 avl64_debug_end(avl64node_t
*node
)
1209 ((struct avl_debug_node
*)node
->avl_start
+
1210 (struct avl_debug_node
*)node
->avl_size
);
1213 avl_debug_node freenodes
[100];
1214 avl_debug_node
*freehead
= &freenodes
[0];
1216 static avl64node_t
*
1217 alloc_avl64_debug_node()
1219 freehead
->avl_balance
= AVL_BALANCE
;
1220 freehead
->avl_parent
= freehead
->avl_forw
= freehead
->avl_back
= NULL
;
1225 avl64_print(avl64tree_desc_t
*tree
, avl64node_t
*root
, int depth
)
1232 avl64_print(tree
, root
->avl_forw
, depth
+5);
1233 for (i
= 0; i
< depth
; i
++)
1235 avl64_printnode(tree
, root
,1);
1237 avl64_print(tree
, root
->avl_back
, depth
+5);
1244 avl64tree_desc_t tree
;
1245 char linebuf
[256], cmd
[256];
1247 avl64_init_tree(&tree
, &avl_debug_ops
);
1249 for (i
= 100; i
> 0; i
= i
- 10)
1251 np
= alloc__debug_avlnode();
1255 avl64_insert(&tree
, np
);
1257 avl64_print(&tree
, tree
.avl_root
, 0);
1259 for (np
= tree
.avl_firstino
; np
!= NULL
; np
= np
->avl_nextino
)
1260 avl64_printnode(&tree
, np
, 0);
1264 printf("Command [fpdir] : ");
1265 fgets(linebuf
, 256, stdin
);
1266 if (feof(stdin
)) break;
1268 if (sscanf(linebuf
, "%[fpdir]%d", cmd
, &i
) != 2)
1273 printf("end of range ? ");
1274 fgets(linebuf
, 256, stdin
);
1277 if (i
== j
) j
= i
+1;
1278 np
= avl64_findinrange(&tree
,i
,j
);
1280 avl64_printnode(&tree
, np
, 1);
1282 avl64_delete(&tree
, np
);
1284 printf("Cannot find %d\n", i
);
1287 avl64_print(&tree
, tree
.avl_root
, 0);
1288 for (np
= tree
.avl_firstino
;
1289 np
!= NULL
; np
= np
->avl_nextino
)
1290 avl64_printnode(&tree
, np
, 0);
1294 np
= alloc_avlnode();
1297 printf("size of range ? ");
1298 fgets(linebuf
, 256, stdin
);
1302 avl64_insert(&tree
, np
);
1305 avl64node_t
*b
, *e
, *t
;
1308 printf("End of range ? ");
1309 fgets(linebuf
, 256, stdin
);
1312 printf("checklen 0/1 ? ");
1313 fgets(linebuf
, 256, stdin
);
1314 checklen
= atoi(linebuf
);
1317 b
= avl64_findanyrange(&tree
, i
, j
, checklen
);
1319 printf("Found something\n");
1323 AVL_START(&tree
, t
) >= j
)
1325 avl64_printnode(&tree
, t
, 0);
1337 * Given a tree, find value; will find return range enclosing value,
1338 * or range immediately succeeding value,
1339 * or range immediately preceeding value.
1343 register avl64tree_desc_t
*tree
,
1344 register __uint64_t value
,
1347 register avl64node_t
*np
= tree
->avl_root
;
1350 if (value
< AVL_START(tree
, np
)) {
1355 /* if we were to add node with value, would
1356 * have a growth of AVL_BACK
1358 if (dir
== AVL_SUCCEED
) {
1359 /* if succeeding node is needed, this is it.
1363 if (dir
== AVL_PRECEED
) {
1365 * find nearest ancestor with lesser value.
1367 np
= np
->avl_parent
;
1369 if (AVL_END(tree
, np
) <= value
)
1371 np
= np
->avl_parent
;
1375 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1378 if (value
>= AVL_END(tree
, np
)) {
1383 /* if we were to add node with value, would
1384 * have a growth of AVL_FORW;
1386 if (dir
== AVL_SUCCEED
) {
1387 /* we are looking for a succeeding node;
1390 return(np
->avl_nextino
);
1392 if (dir
== AVL_PRECEED
) {
1393 /* looking for a preceeding node; this is it. */
1396 ASSERT(dir
== AVL_SUCCEED
|| dir
== AVL_PRECEED
);
1398 /* AVL_START(tree, np) <= value < AVL_END(tree, np) */
1405 #ifdef AVL_FUTURE_ENHANCEMENTS
1409 * Given range r [start, end), find all ranges in tree which are contained
1410 * in r. At return, startp and endp point to first and last of
1411 * a chain of elements which describe the contained ranges. Elements
1412 * in startp ... endp are in sort order, and can be accessed by
1413 * using avl_nextino.
1418 register avl64tree_desc_t
*tree
,
1419 register __uint64_t start
,
1420 register __uint64_t end
,
1421 avl64node_t
**startp
,
1424 register avl64node_t
*np
;
1426 np
= avl64_findadjacent(tree
, start
, AVL_SUCCEED
);
1427 if (np
== NULL
/* nothing succeding start */
1428 || (np
&& (end
<= AVL_START(tree
, np
))))
1429 /* something follows start,
1430 but... is entirely after end */
1439 /* see if end is in this region itself */
1440 if (end
<= AVL_END(tree
, np
) ||
1441 np
->avl_nextino
== NULL
||
1443 (end
<= AVL_START(tree
, np
->avl_nextino
)))) {
1447 /* have to munge for end */
1449 * note: have to look for (end - 1), since
1450 * findadjacent will look for exact value, and does not
1451 * care about the fact that end is actually one more
1452 * than the value actually being looked for; thus feed it one less.
1454 *endp
= avl64_findadjacent(tree
, (end
-1), AVL_PRECEED
);
1458 #endif /* AVL_FUTURE_ENHANCEMENTS */