{
unsigned char off = 0;
+ printk("\t%s\n", __func__);
sd->len = 0;
mni_node_init(dst, mas_pop_node(mas), src->type);
if (src->insert_off) {
struct ma_node_state *state;
+ printk("%s\n", __func__);
/* Offset into the destination data where the insert ends */
insert_end = sd->insert + part->size - 1;
to = left;
node_off = 0; /* src */
part_off = 0;
- printk("sd off %u in %u in_end %u\n", sd->offset, sd->insert, insert_end);
do {
unsigned char copied = 0;
if (sd->offset >= sd->insert && sd->offset <= insert_end) {
copied = min(part->size - part_off, sd->space);
state->part = part;
+ printk("insert part at %u first entry is %p\n", sd->offset, part->slots[0]);
mns_mni_init(state, to, part_off, copied);
state->use_part = true;
part_off += copied;
bool can_rebalance_right(struct ma_state *tmp_mas, struct ma_node_info *parent,
struct ma_node_info *src2, struct split_data *sd)
{
+ printk("\t%s %u %u\n", __func__, parent->insert_off, parent->end);
if (parent->insert_off >= parent->end) /* No right node */
return false;
tmp_mas->offset++;
+ printk("Check %p[%u]\n", tmp_mas->node, 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);
+ printk("split is %u\n", sd->split);
if (!sd->split) {
mas_ascend(tmp_mas);
tmp_mas->offset--;
bool can_rebalance_left(struct ma_state *tmp_mas, struct ma_node_info *parent,
struct ma_node_info *src2, struct split_data *sd)
{
+ printk("\t%s %u %u\n", __func__, parent->insert_off, parent->end);
if (!parent->insert_off) /* No left node */
return false;
tmp_mas->offset--;
+ printk("Check %p[%u]\n", tmp_mas->node, 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);
+ printk("split is %u\n", sd->split);
if (!sd->split) {
mas_ascend(tmp_mas);
tmp_mas->offset++;
}
#if 1
+
+static void mas_wr_rebalance_two(struct ma_wr_state *wr_mas,
+ struct ma_node_info *left,
+ struct ma_node_info *right,
+ struct ma_node_info *src,
+ struct ma_node_info *src2,
+ struct ma_node_part *part,
+ struct split_data *sd,
+ bool left_store)
+{
+ if (!left_store) {
+ printk("store right->n");
+ left->min = src2->min;
+ right->max = src->max;
+ sd->offset = src2->end + 1;
+ sd->space = sd->split - src2->end;
+ sd->states[sd->len].info = src2;
+ /* The first state to copy is the left node */
+ mns_mni_init(&sd->states[sd->len], left, 0, src2->end + 1);
+ sd->len++;
+ } else {
+ printk("store left\n");
+ sd->space = sd->split;
+ sd->offset = 0;
+ left->min = src->min;
+ right->max = src2->max;
+ }
+
+ mt_wr_split_data(src, left, right, part, sd);
+ if (left_store) {
+ char len;
+
+ sd->split = (sd->new_end + 1) / 2;
+ printk("sd is at offset %u splut %u\n", sd->offset, sd->split);
+ len = sd->split - sd->offset;
+ sd->states[sd->len].info = src2;
+ printk("cp right->%u + %u to left\n", 0, len);
+ mns_mni_init(&sd->states[sd->len], left, 0, len);
+ sd->len++;
+ printk("cp the right->to right->%u + %u\n", len, src2->end + 1);
+ /* Stored to the left, copy the last of the right->in src2 */
+ sd->states[sd->len].info = src2;
+ mns_mni_init(&sd->states[sd->len], right, len, src2->end + 1 - len);
+ sd->len++;
+ }
+
+ mns_assemble(sd->states, sd->len);
+ mni_finalise(left);
+ mni_finalise(right);
+ mni_node_part_init(part, left, right);
+ part->skip = 2;
+}
+
+static void mas_wr_rebalance_reduce(struct ma_wr_state *wr_mas,
+ struct ma_node_info *left,
+ struct ma_node_info *src,
+ struct ma_node_info *src2,
+ struct ma_node_part *part,
+ struct split_data *sd,
+ bool left_store)
+{
+ if (!left_store) {
+ printk("store right->n");
+ left->min = src2->min;
+ left->max = src->max;
+ sd->offset = src2->end + 1;
+ sd->space = sd->split - src2->end;
+ sd->states[sd->len].info = src2;
+ /* The first state to copy is the left node */
+ mns_mni_init(&sd->states[sd->len], left, 0, src2->end + 1);
+ sd->len++;
+ } else {
+ printk("store left\n");
+ sd->space = sd->split;
+ sd->offset = 0;
+ left->min = src->min;
+ left->max = src2->max;
+ }
+
+ mt_wr_split_data(src, left, NULL, part, sd);
+ if (left_store) {
+ sd->states[sd->len].info = src2;
+ printk("cp right->%u + %u to left\n", 0, src2->end + 1);
+ mns_mni_init(&sd->states[sd->len], left, 0, src2->end + 1);
+ sd->len++;
+ }
+
+ mns_assemble(sd->states, sd->len);
+ mni_finalise(left);
+ mni_node_part_init(part, left, NULL);
+ part->skip = 2;
+}
+
static void mas_wr_rebalance(struct ma_wr_state *wr_mas)
{
struct ma_state *mas;
* compact to the left side.
*/
mt_dump(mas->tree, mt_dump_dec);
- printk("Rebalance %p offset %u\n", mas->node, mas->offset);
+ printk("Rebalance %p offset %u - %u\n", mas->node, mas->offset, wr_mas->offset_end);
printk("Store %lu - %lu\n", mas->index, mas->last);
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;
+ do {
+ printk("\tloop\n");
+ tmp_mas = *mas;
+ mas_wr_ascend_init(&tmp_mas, &parent);
+ if (can_rebalance_right(&tmp_mas, &parent, &src2, &sd)) {
+ printk("rebalance right, split is %u\n", sd.split);
+ printk("rebalance with %p\n", src2.node);
+ /* Left will be src, right will be src2 */
+ sd.insert = mas->offset;
+ printk("insert is at %u\n", sd.insert);
+ left_store = true;
+ } else {
+ /* Won't fail here */
+ MAS_BUG_ON(mas, can_rebalance_left(&tmp_mas, &parent, &src2, &sd) == false);
+ printk("rebalance left, split is %u\n", sd.split);
+ printk("rebalance with %p\n", src2.node);
+ /* Left will be src2, right will be src */
+ sd.insert = mas->offset + src2.end + 1;
+ }
- tmp_mas = *mas;
- mas_wr_ascend_init(&tmp_mas, &parent);
- if (can_rebalance_right(&tmp_mas, &parent, &src2, &sd)) {
- printk("rebalance right, split is %u\n", sd.split);
- printk("rebalance with %p\n", src2.node);
- /* Left will be src, right will be src2 */
- sd.insert = mas->offset;
- left_store = true;
- } else {
- /* Won't fail here */
- MAS_BUG_ON(mas, can_rebalance_left(&tmp_mas, &parent, &src2, &sd));
- printk("rebalance left, split is %u\n", sd.split);
- printk("rebalance with %p\n", src2.node);
- /* Left will be src2, right will be src */
- sd.insert = mas->offset + src2.end + 1;
- }
-
- sd.new_end += src2.end + 1;
- if (sd.new_end < mt_min_slots[left.type]) {
- printk("Not enough tdata\n");
- exit(0);
- }
- if (sd.split < mt_min_slots[left.type]) {
- printk("Too small split\n");
- exit(0);
- }
- if (sd.new_end - sd.split < mt_min_slots[left.type]) {
- printk("Too big split\n");
- exit(0);
- }
- printk("Total data is %u\n", sd.new_end);
- printk("sd insert is %u\n", sd.insert);
- if (sd.new_end < mt_slots[left.type]) {
- printk("Shrinking parent\n");
- //mt_wr_split_data(&src, &left, /* right = */ NULL, &part, &sd);
- if (parent.end <= mt_min_slots[parent.type])
- printk("Have to go again\n");
+ printk("rebalance %p %p\n", src.node, src2.node);
+ sd.new_end += src2.end + 1;
+ if (sd.new_end < mt_min_slots[left.type]) {
+ printk("Not enough tdata\n");
+ exit(0);
+ }
+ if (sd.split < mt_min_slots[left.type]) {
+ printk("Too small split\n");
+ exit(0);
+ }
+ if (sd.new_end - sd.split < mt_min_slots[left.type]) {
+ printk("Too big split\n");
+ exit(0);
+ }
+ printk("Total data is %u\n", sd.new_end);
+ printk("sd insert is %u\n", sd.insert);
+ if (sd.new_end >= mt_slots[left.type]) {
+ mni_node_init(&right, mas_pop_node(mas), mte_node_type(mas->node));
+ mas_wr_rebalance_two(wr_mas, &left, &right, &src, &src2, &part, &sd, left_store);
+ mas_ascend(mas);
+ mas->end = parent.end;
+ mas->offset = parent.insert_off;
+ printk("Replacing 2 nodes, break\n");
+ printk("mas is %p\n", mas->node);
+ break;
+ }
- exit(0);
- /* Single entry replacing two, may need to rebalance again */
- }
+ printk("REDUCE %p %p\n", src.node, src2.node);
+ mas_wr_rebalance_reduce(wr_mas, &left, &src, &src2, &part, &sd, left_store);
- mni_node_init(&right, mas_pop_node(mas), wr_mas->type);
- if (!left_store) {
- printk("store right\n");
- left.min = src2.min;
- right.max = src.max;
- sd.offset = src2.end + 1;
- sd.space = sd.split - src2.end;
- sd.states[sd.len].info = &src2;
- /* The first state to copy is the left node */
- mns_mni_init(&sd.states[sd.len], &left, 0, src2.end + 1);
- sd.len++;
- } else {
- printk("store left\n");
- sd.space = sd.split;
- sd.offset = 0;
- left.min = src.min;
- right.max = src2.max;
- }
+ /* Must go again */
+ mas_ascend(mas);
+ mas->end = parent.end;
+ mas->offset = parent.insert_off;
+ printk("\tmas is now at %p[%u]\n", mas->node, mas->offset);
+ sd.len = 0;
+ sd.new_end = mas->end + part.size - part.skip + 1;
+ sd.offset = mas->offset;
+ sd.src_ins_end = mas->offset + 1;
+ if (ma_is_root(parent.node)) {
+ printk("Parent IS root, so abort rest\n");
+ if (parent.end != 1)
+ break; /* Converged */
+
+ printk("left needs to be new root\n");
+ src.enode = mas->node;
+ left.node->parent = mas_mn(mas)->parent;
+ mas->node = left.enode;
+ mas->depth = mas_mt_height(mas) - 1;
+ mas_set_height(mas);
+ goto new_root;
+ }
+ if (mas->end - 1 > mt_min_slots[parent.type]) {
+ printk("Decrease %p to %u\n", parent.node, parent.end - 1);
- mt_wr_split_data(&src, &left, &right, &part, &sd);
- if (left_store) {
- char len;
+ break; /* Converged */
+ }
- sd.split = (sd.new_end + 1) / 2;
- printk("sd is at offset %u splut %u\n", sd.offset, sd.split);
- len = sd.split - sd.offset;
- sd.states[sd.len].info = &src2;
- printk("cp right %u + %u to left\n", 0, len);
- mns_mni_init(&sd.states[sd.len], &left, 0, len);
- sd.len++;
- printk("cp the right to right %u + %u\n", len, src2.end + 1);
- /* Stored to the left, copy the last of the right in src2 */
- sd.states[sd.len].info = &src2;
- mns_mni_init(&sd.states[sd.len], &right, len, src2.end + 1 - len);
- sd.len++;
- }
+ mni_mas_init(&src, mas);
+ src.end = mas->end;
+ mni_node_init(&left, mas_pop_node(mas), mte_node_type(mas->node));
+ printk("\nAGAIN, parent %p[%u] src %p\n", parent.node, parent.insert_off, src.node);
+ printk("height is %u\n", height);
+ } while (height--);
- mns_assemble(sd.states, sd.len);
- mni_finalise(&left);
- mni_finalise(&right);
- mni_node_part_init(&part, &left, &right);
- mas_ascend(mas);
- mas->end = parent.end;
- mas->offset = parent.insert_off;
- part.skip = 2;
mas_wr_converged(&parent, &new_parent, &part, mas, &sd);
src.enode = parent.enode;
- printk("Replace %p\n", parent.node);
+ printk("Replace %p with %p\n", parent.node, new_parent.enode);
mas->node = new_parent.enode;
+new_root:
mas_wmb_replace(mas, src.enode);
mtree_range_walk(mas);
mt_dump(mas->tree, mt_dump_dec);
mt_validate(mas->tree);
return;
- exit(0);
/*
* allocate left
* set alloc in left
printk("Rebalance\n");
mni_node_init(&right, mas_pop_node(mas), wr_mas->type);
sd.split = mas_wr_rebalance_calc(sd.new_end,
- src2.type);
+ src2.type);
/*
* Rebalance between nodes is possible, so the
* operation stops early.