} while (node_off <= src->end);
}
+
+static inline
+bool can_rebalance_right(struct ma_state *tmp_mas, struct ma_node_info *parent,
+ struct ma_node_info *src2, struct split_data *sd)
+{
+ if (parent->insert_off >= parent->end) /* No right node */
+ return false;
+
+ tmp_mas->offset++;
+ mas_descend(tmp_mas);
+ mni_mas_init(src2, tmp_mas);
+ mni_set_end(src2);
+ sd->split = mas_wr_rebalance_calc(src2->end + sd->new_end, src2->type);
+ if (!sd->split) {
+ mas_ascend(tmp_mas);
+ tmp_mas->offset--;
+ return false;
+ }
+ return true;
+}
+
+static inline
+bool can_rebalance_left(struct ma_state *tmp_mas, struct ma_node_info *parent,
+ struct ma_node_info *src2, struct split_data *sd)
+{
+ if (!parent->insert_off) /* No left node */
+ return false;
+
+ tmp_mas->offset--;
+ mas_descend(tmp_mas);
+ mni_mas_init(src2, tmp_mas);
+ mni_set_end(src2);
+ sd->split = mas_wr_rebalance_calc(src2->end + sd->new_end, src2->type);
+ if (!sd->split) {
+ mas_ascend(tmp_mas);
+ tmp_mas->offset++;
+ return false;
+ }
+
+ parent->insert_off--;
+ return true;
+}
/*
* mas_wr_try_rebalance() - Try to rebalance two nodes, this may not work out.
* @src: The source node state
mas_wr_ascend_init(&tmp_mas, &parent);
src->end = mas->end;
- if (!parent.insert_off) /* No left sibling */
- goto try_right; /* There must be a right sibling */
-
- /* Check for space in left sibling */
- tmp_mas.offset--;
- mas_descend(&tmp_mas);
- mni_mas_init(&src2, &tmp_mas);
- sd->split = mas_wr_rebalance_calc(src2.end + sd->new_end, src2.type);
-
- if (sd->split) {
- parent.insert_off--;
- /* Left will be src2, right will be src */
+ if (can_rebalance_left(&tmp_mas, &parent, &src2, sd)) {
left->min = src2.min;
right->max = src->max;
- } else {
- if (parent.end <= parent.insert_off)
- return false;
-
- mas_ascend(&tmp_mas);
-try_right:
- tmp_mas.offset = parent.insert_off + 1;
- mas_descend(&tmp_mas);
- mni_mas_init(&src2, &tmp_mas);
- mni_set_end(&src2);
- sd->split = mas_wr_rebalance_calc(src2.end + sd->new_end, src2.type);
- if (!sd->split)
- return false;
-
+ } else if (can_rebalance_right(&tmp_mas, &parent, &src2, sd)) {
sd->split = src2.end + sd->new_end - sd->split;
left_store = true;
/* Left will be src, right will be src2 */
left->min = src->min;
right->max = src2.max;
+ } else {
+ return false;
}
/* The rebalance operation will succeed. */
return true;
}
-#if 1
+#if 0
static void mas_wr_rebalance(struct ma_wr_state *wr_mas)
{
struct ma_state *mas;
height = mas_mt_height(mas);
mas->depth = height;
+ mni_mas_init(&src, mas);
+ src.end = mas->end;
+
+ mni_node_init(&left, mas_pop_node(mas), wr_mas->type);
+ if (mt_is_alloc(mas->tree))
+ left.is_alloc = true;
+
+ tmp_mas = *mas;
+ mas_wr_ascend_init(&tmp_mas, &parent);
+ if (mas_wr_try_right(&tmp_mas, &parent, &src2)) {
+ sd.insert = mas->offset;
+ } else {
+ /* Won't fail here */
+ MAS_BUG_ON(try_rebalance_left(&tmp_mas, &parent, &src2));
+ sd.insert = mas->offset + src2.end + 1;
+ }
+
+
/*
* allocate left
* set alloc in left
*
*/
- mni_mas_init(&src, mas);
- tmp_mas = *mas;
while (height--) {
printk("height %d\n", height);
mas_wr_ascend_init(&tmp_mas, &parent);
mas_wr_split(wr_mas);
break;
case wr_rebalance:
- //mas_wr_bnode(wr_mas);
- mas_wr_rebalance(wr_mas);
+ mas_wr_bnode(wr_mas);
+ //mas_wr_rebalance(wr_mas);
break;
case wr_exact_fit:
rcu_assign_pointer(wr_mas->slots[mas->offset], wr_mas->entry);