58 #include "mysys_priv.h"
65 #define DEFAULT_ALLOC_SIZE 8192
66 #define DEFAULT_ALIGN_SIZE 8192
70 tree_walk_action,
void *);
72 tree_walk_action,
void *);
86 void init_tree(
TREE *tree, ulong default_alloc_size, ulong memory_limit,
88 tree_element_free free_element,
const void *custom_arg)
90 DBUG_ENTER(
"init_tree");
91 DBUG_PRINT(
"enter",(
"tree: 0x%lx size: %d", (
long) tree, size));
93 if (default_alloc_size < DEFAULT_ALLOC_SIZE)
94 default_alloc_size= DEFAULT_ALLOC_SIZE;
95 default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE);
96 memset(&tree->null_element, 0,
sizeof(tree->null_element));
97 tree->root= &tree->null_element;
99 tree->size_of_element=size > 0 ? (uint) size : 0;
100 tree->memory_limit=memory_limit;
101 tree->free=free_element;
103 tree->elements_in_tree=0;
104 tree->custom_arg = custom_arg;
105 tree->null_element.colour=BLACK;
106 tree->null_element.left=tree->null_element.right=0;
108 if (!free_element && size >= 0 &&
109 ((uint) size <=
sizeof(
void*) || ((uint) size & (
sizeof(
void*)-1))))
119 if (!default_alloc_size)
120 default_alloc_size=1;
125 tree->offset_to_key=0;
126 tree->size_of_element+=
sizeof(
void*);
128 if (!(tree->with_delete=with_delete))
130 init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0);
131 tree->mem_root.min_malloc=(
sizeof(
TREE_ELEMENT)+tree->size_of_element);
136 static void free_tree(
TREE *tree, myf free_flags)
138 DBUG_ENTER(
"free_tree");
139 DBUG_PRINT(
"enter",(
"tree: 0x%lx", (
long) tree));
143 if (tree->with_delete)
144 delete_tree_element(tree,tree->root);
149 if (tree->memory_limit)
150 (*tree->free)(NULL, free_init, tree->custom_arg);
151 delete_tree_element(tree,tree->root);
152 if (tree->memory_limit)
153 (*tree->free)(NULL, free_end, tree->custom_arg);
155 free_root(&tree->mem_root, free_flags);
158 tree->root= &tree->null_element;
159 tree->elements_in_tree=0;
165 void delete_tree(
TREE* tree)
167 free_tree(tree, MYF(0));
170 void reset_tree(
TREE* tree)
173 free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
179 if (element != &tree->null_element)
181 delete_tree_element(tree,element->left);
183 (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
184 delete_tree_element(tree,element->right);
185 if (tree->with_delete)
200 const void* custom_arg)
205 parent= tree->parents;
206 *parent = &tree->root; element= tree->root;
209 if (element == &tree->null_element ||
210 (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
215 *++parent= &element->right; element= element->right;
219 *++parent = &element->left; element= element->left;
222 if (element == &tree->null_element)
224 uint alloc_size=
sizeof(
TREE_ELEMENT)+key_size+tree->size_of_element;
225 tree->allocated+=alloc_size;
227 if (tree->memory_limit && tree->elements_in_tree
228 && tree->allocated > tree->memory_limit)
231 return tree_insert(tree, key, key_size, custom_arg);
234 key_size+=tree->size_of_element;
235 if (tree->with_delete)
236 element=(
TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
238 element=(
TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size);
242 element->left=element->right= &tree->null_element;
243 if (!tree->offset_to_key)
245 if (key_size ==
sizeof(
void*))
246 *((
void**) (element+1))=key;
249 *((
void**) (element+1))= (
void*) ((
void **) (element+1)+1);
250 memcpy((uchar*) *((
void **) (element+1)),key,
251 (
size_t) (key_size-
sizeof(
void*)));
255 memcpy((uchar*) element+tree->offset_to_key,key,(
size_t) key_size);
257 tree->elements_in_tree++;
258 rb_insert(tree,parent,element);
262 if (tree->flag & TREE_NO_DUPS)
266 if (! element->count)
269 DBUG_EXECUTE(
"check_tree", test_rb_tree(tree->root););
273 int tree_delete(
TREE *tree,
void *key, uint key_size,
const void *custom_arg)
275 int cmp,remove_colour;
277 if (!tree->with_delete)
280 parent= tree->parents;
281 *parent= &tree->root; element= tree->root;
284 if (element == &tree->null_element)
286 if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
291 *++parent= &element->right; element= element->right;
295 *++parent = &element->left; element= element->left;
298 if (element->left == &tree->null_element)
300 (**parent)=element->right;
301 remove_colour= element->colour;
303 else if (element->right == &tree->null_element)
305 (**parent)=element->left;
306 remove_colour= element->colour;
311 *++parent= &element->right; nod= element->right;
312 while (nod->left != &tree->null_element)
314 *++parent= &nod->left; nod= nod->left;
316 (**parent)=nod->right;
317 remove_colour= nod->colour;
318 org_parent[0][0]=nod;
319 org_parent[1]= &nod->right;
320 nod->left=element->left;
321 nod->right=element->right;
322 nod->colour=element->colour;
324 if (remove_colour == BLACK)
325 rb_delete_fixup(tree,parent);
327 (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
328 tree->allocated-=
sizeof(
TREE_ELEMENT) + tree->size_of_element + key_size;
330 tree->elements_in_tree--;
335 void *tree_search(
TREE *tree,
void *key,
const void *custom_arg)
342 if (element == &tree->null_element)
344 if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
346 return ELEMENT_KEY(tree,element);
348 element=element->right;
350 element=element->left;
354 void *tree_search_key(
TREE *tree,
const void *key,
356 enum ha_rkey_function flag,
const void *custom_arg)
360 TREE_ELEMENT **last_left_step_parent= NULL, **last_right_step_parent= NULL;
367 *parents = &tree->null_element;
368 while (element != &tree->null_element)
371 if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
375 case HA_READ_KEY_EXACT:
376 case HA_READ_KEY_OR_NEXT:
377 case HA_READ_BEFORE_KEY:
378 last_equal_element= parents;
381 case HA_READ_AFTER_KEY:
384 case HA_READ_PREFIX_LAST:
385 case HA_READ_PREFIX_LAST_OR_PREV:
386 last_equal_element= parents;
395 last_right_step_parent= parents;
396 element= element->right;
400 last_left_step_parent= parents;
401 element= element->left;
405 case HA_READ_KEY_EXACT:
406 case HA_READ_PREFIX_LAST:
407 *last_pos= last_equal_element;
409 case HA_READ_KEY_OR_NEXT:
410 *last_pos= last_equal_element ? last_equal_element : last_left_step_parent;
412 case HA_READ_AFTER_KEY:
413 *last_pos= last_left_step_parent;
415 case HA_READ_PREFIX_LAST_OR_PREV:
416 *last_pos= last_equal_element ? last_equal_element : last_right_step_parent;
418 case HA_READ_BEFORE_KEY:
419 *last_pos= last_right_step_parent;
424 return *last_pos ? ELEMENT_KEY(tree, **last_pos) : NULL;
435 *parents= &tree->null_element;
436 while (element != &tree->null_element)
439 element= ELEMENT_CHILD(element, child_offs);
442 return **last_pos != &tree->null_element ?
443 ELEMENT_KEY(tree, **last_pos) : NULL;
451 if (ELEMENT_CHILD(x, r_offs) != &tree->null_element)
453 x= ELEMENT_CHILD(x, r_offs);
455 while (ELEMENT_CHILD(x, l_offs) != &tree->null_element)
457 x= ELEMENT_CHILD(x, l_offs);
460 return ELEMENT_KEY(tree, x);
465 while (y != &tree->null_element && x == ELEMENT_CHILD(y, r_offs))
470 return y == &tree->null_element ? NULL : ELEMENT_KEY(tree, y);
478 ha_rows tree_record_pos(
TREE *tree,
const void *key,
479 enum ha_rkey_function flag,
const void *custom_arg)
484 double right= tree->elements_in_tree;
486 while (element != &tree->null_element)
488 if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
492 case HA_READ_KEY_EXACT:
493 case HA_READ_BEFORE_KEY:
496 case HA_READ_AFTER_KEY:
505 element= element->right;
506 left= (left + right) / 2;
510 element= element->left;
511 right= (left + right) / 2;
515 case HA_READ_KEY_EXACT:
516 case HA_READ_BEFORE_KEY:
517 return (ha_rows) right;
518 case HA_READ_AFTER_KEY:
519 return (ha_rows) left;
525 int tree_walk(
TREE *tree, tree_walk_action action,
void *argument, TREE_WALK visit)
528 case left_root_right:
529 return tree_walk_left_root_right(tree,tree->root,action,argument);
530 case right_root_left:
531 return tree_walk_right_root_left(tree,tree->root,action,argument);
536 static int tree_walk_left_root_right(
TREE *tree,
TREE_ELEMENT *element, tree_walk_action action,
void *argument)
541 if ((error=tree_walk_left_root_right(tree,element->left,action,
543 (error=(*action)(ELEMENT_KEY(tree,element),
544 (element_count) element->count,
546 error=tree_walk_left_root_right(tree,element->right,action,argument);
552 static int tree_walk_right_root_left(
TREE *tree,
TREE_ELEMENT *element, tree_walk_action action,
void *argument)
557 if ((error=tree_walk_right_root_left(tree,element->right,action,
559 (error=(*action)(ELEMENT_KEY(tree,element),
560 (element_count) element->count,
562 error=tree_walk_right_root_left(tree,element->left,action,argument);
596 while (leaf != tree->root && (par=parent[-1][0])->colour == RED)
598 if (par == (par2=parent[-2][0])->left)
601 if (y->colour == RED)
611 if (leaf == par->right)
613 left_rotate(parent[-1],par);
618 right_rotate(parent[-2],par2);
625 if (y->colour == RED)
635 if (leaf == par->left)
637 right_rotate(parent[-1],par);
642 left_rotate(parent[-2],par2);
647 tree->root->colour=BLACK;
655 while (x != tree->root && x->colour == BLACK)
657 if (x == (par=parent[-1][0])->left)
660 if (w->colour == RED)
664 left_rotate(parent[-1],par);
666 *++parent= &par->left;
669 if (w->left->colour == BLACK && w->right->colour == BLACK)
677 if (w->right->colour == BLACK)
679 w->left->colour=BLACK;
681 right_rotate(&par->right,w);
684 w->colour=par->colour;
686 w->right->colour=BLACK;
687 left_rotate(parent[-1],par);
695 if (w->colour == RED)
699 right_rotate(parent[-1],par);
700 parent[0]= &w->right;
701 *++parent= &par->right;
704 if (w->right->colour == BLACK && w->left->colour == BLACK)
712 if (w->left->colour == BLACK)
714 w->right->colour=BLACK;
716 left_rotate(&par->left,w);
719 w->colour=par->colour;
721 w->left->colour=BLACK;
722 right_rotate(parent[-1],par);
741 if (element->colour == RED &&
742 (element->left->colour == RED || element->right->colour == RED))
744 printf(
"Wrong tree: Found two red in a row\n");
747 count_l=test_rb_tree(element->left);
748 count_r=test_rb_tree(element->right);
749 if (count_l >= 0 && count_r >= 0)
751 if (count_l == count_r)
752 return count_l+(element->colour == BLACK);
753 printf(
"Wrong tree: Incorrect black-count: %d - %d\n",count_l,count_r);