Beispiel #1
0
/*
 * given a path all the way to a leaf, insert a value into it
 */
static void
leaf_insert(PyObject *value, bt_path_t *path) {
    bt_leaf_t *leaf = path->lineage[path->depth];
    int index = path->indexes[path->depth];

    /* put the value in place */
    if (index < leaf->filled)
        memmove(leaf->values + index + 1, leaf->values + index,
                (leaf->filled - index) * sizeof(PyObject *));
    memcpy(leaf->values + index, &value, sizeof(PyObject *));

    leaf->filled++;

    /* now if the node is overfilled, correct it */
    if (leaf->filled > path->tree->order)
        shrink_node(path);
    else
        node_sizechange(path);
}
Beispiel #2
0
/*
 * shrink a node by at least 1 to preserve the btree invariants
 */
static void
shrink_node(bt_path_t *path) {
    int parent_index = -1;
    bt_branch_t *parent = NULL;
    bt_node_t *sibling;
    bt_node_t *node = path->lineage[path->depth];

    int middle;
    PyObject *median;

    /* if we aren't the root, try passing an item to a neighbor */
    if (path->depth) {
        parent_index = path->indexes[path->depth - 1];
        parent = (bt_branch_t *)path->lineage[path->depth - 1];

        /* try passing it left first */
        if (parent_index) {
            sibling = parent->children[parent_index - 1];
            if (sibling->filled < path->tree->order) {
                node_pass_left(path, 1);
                return;
            }
        }

        /* try passing it right */
        if (parent_index < parent->filled) {
            sibling = parent->children[parent_index + 1];

            if (sibling->filled < path->tree->order) {
                node_pass_right(path, 1);
                return;
            }
        }
    }

    /*
     * fallback plan: split the current node into two
     */

    /* pull the median value, it's going up to the parent node */
    middle = node->filled / 2;
    median = node->values[middle];

    /* put the second half of the node's data in a new sibling */
    sibling = allocate_node(
            path->depth < path->tree->depth, path->tree->order);
    sibling->filled = node->filled - middle - 1;
    memcpy(sibling->values, node->values + middle + 1,
            sizeof(PyObject *) * sibling->filled);
    if (path->depth < path->tree->depth)
        memcpy(((bt_branch_t *)sibling)->children,
                ((bt_branch_t *)node)->children + middle + 1,
                sizeof(bt_node_t *) * (node->filled - middle));

    /* cut off the original node's data in the middle */
    node->filled = middle;

    /* the node's size has changed */
    path->lineage[path->depth] = node;
    node_sizechange(path);

    /* the new sibling's size has changed */
    path->indexes[path->depth - 1]++;
    path->lineage[path->depth] = sibling;
    node_sizechange(path);

    /*
     * push the median value up to the parent
     */

    if (!(path->depth)) {
        /* if we were the root, we're going to need a parent now */
        parent = (bt_branch_t *)allocate_node(1, path->tree->order);

        /* insert the siblings as children, and the median value */
        parent->children[0] = node;
        parent->children[1] = sibling;
        parent->values[0] = median;
        parent->filled = 1;
        path->tree->root = (bt_node_t *)parent;
        path->tree->depth++;
    } else {
        /* if we need to, make space in the parent's arrays */
        if (parent_index < parent->filled) {
            memmove(parent->values + parent_index + 1,
                    parent->values + parent_index,
                    sizeof(PyObject *) * (parent->filled - parent_index));
            memmove(parent->children + parent_index + 2,
                    parent->children + parent_index + 1,
                    sizeof(bt_node_t *) * (parent->filled - parent_index));
        }

        parent->values[parent_index] = median;
        parent->children[parent_index + 1] = sibling;
        parent->filled += 1;
    }

    /* the parent's size has changed in either of the above branches */
    path->depth--;
    node_sizechange(path);

    /* now if the parent node is overflowed then it too needs to shrink */
    if (parent->filled > path->tree->order)
        shrink_node(path);
}
Beispiel #3
0
/**
 * perform the topological sorting on the graph.  Returned is the head to a
 * topologically sorted list of nodes
 */
static struct copy_graph_node * topo_sort(
    struct copy_graph_node ** node_array,
    int count,
    struct add_list * add_list) {
    int j;
    struct copy_graph_node * topo_head = NULL;
    struct copy_stack * copy_top = NULL;

    for(j=count-1; j>=0; j--) {
        struct copy_graph_node * bottom_node;
        bottom_node = node_array[j];
        if(bottom_node->visited == FINISHED
                || bottom_node->visited == DELETED) {
            continue;
        }
        bottom_node->next = NULL;
        copy_top = (struct copy_stack * ) malloc(sizeof(struct copy_stack));
        update_extra_memory(sizeof(struct copy_stack));
        copy_top->below = NULL;
        copy_top->data = bottom_node;
        copy_top->data->visited = ON_STACK;


        while(copy_top != NULL) {
            struct copy_graph_node * current_node = copy_top->data;
            struct copy_graph_edge * current_edge = copy_top->data->edge;
            if(verbose >3) {
                rprintf(FINFO, "looking at node src=%d target=%.0f\n",
                        copy_top->data->u.copy->block,
                        (double)copy_top->data->u.copy->target);
            }

            if(!current_edge) {
                struct copy_stack * temp_copy_top;
                /* pop node off and put it on the front of the topo list*/
                current_node->visited = FINISHED;

                /* put on topo list as finished (if not deleted)*/
                //      rprintf(FINFO,"Putting on to topo list: %08x\n",current_node);
                current_node->next = topo_head;
                topo_head = current_node;

                /* pop off stack */
                temp_copy_top = copy_top->below;
                update_extra_memory(-sizeof(struct copy_stack));
                free(copy_top);
                copy_top = temp_copy_top;


                if(verbose >4) {
                    rprintf(FINFO, "finished node\n");
                }
            }
            else {
                /* remove edge from list */
                copy_top->data->edge = current_edge->next;
                current_edge->dest->references--;

                /* is its target already on stack? */
                if(current_edge->dest->visited == ON_STACK) {
                    /* resolve cycle */
                    stats.broken_cycles++;
                    cycles_broken++;
                    if(inplace==1) {
                        current_edge->dest->visited = DELETED;
                        buffer_add(add_list,current_edge->dest->u.copy->target,
                                   current_edge->dest->u.copy->length);
                        if(verbose >3 ) {
                            rprintf(FINFO,"Deleting copy src=%.0f len=%d\n",
                                    (double)current_edge->dest->u.copy->target,
                                    current_edge->dest->u.copy->length);
                        }
                    }
                    else if(inplace==2) {
                        struct copy_graph_node * best_src_node = current_node;
                        struct copy_graph_node * best_dest_node = current_edge->dest;
                        int min_edge_weight = edge_weight(best_src_node,best_dest_node);
                        struct copy_stack * current_stack_node = copy_top;

                        current_stack_node = copy_top;
                        /* iterate down through stack and find best edge to trim*/
                        while(current_stack_node->data != current_node) {
                            int temp_weight =
                                edge_weight(current_stack_node->below->data,
                                            current_stack_node->data);
                            if(temp_weight < min_edge_weight) {
                                best_src_node = current_stack_node->below->data;
                                best_dest_node = current_stack_node->data;
                                min_edge_weight = temp_weight;
                            }
                        }

                        /* restore stack to appropriate position */
                        current_stack_node = copy_top;
                        do {
                            struct copy_stack * temp_stack_node;
                            /*rprintf(FINFO,"Current_stack_node: %.8x data:%.8x\n",
                                        current_stack_node,
                                        current_stack_node->data);*/
                            current_stack_node->data->visited = UNVISITED;
                            if (current_stack_node->below
                                    && current_stack_node->below
                                    != best_src_node) {

                                current_edge = (struct copy_graph_edge *)
                                               malloc(sizeof(struct copy_graph_edge));
                                current_edge->dest = current_stack_node->data;
                                current_edge->next = current_stack_node->below->data->edge;
                                current_stack_node->below->data->edge = current_edge;

                            }
                            temp_stack_node = current_stack_node;
                            current_stack_node = current_stack_node->below;
                            update_extra_memory(-sizeof(struct copy_stack));
                            free(temp_stack_node);
                        } while(current_stack_node && current_stack_node->data != best_src_node);
                        copy_top = current_stack_node;

                        current_node = NULL;
                        current_edge = NULL;

                        if(copy_top) {
                            current_node = copy_top->data;
                            current_edge = copy_top->data->edge;
                        }

                        if(verbose > 3) {
                            rprintf(FINFO,"Trimming copy "
                                    "weight=%d\n",edge_weight(best_src_node,best_dest_node));
                        }
                        shrink_node(best_src_node,best_dest_node);
                        if(edge_weight(best_src_node,best_dest_node)>0) {
                            rprintf(FINFO, "dependency not fixed\n");
                        }

                    }
                }
                else if(current_edge->dest->visited == DELETED) {

                }
                else if(current_edge->dest->visited != FINISHED
                        && 0!=edge_weight(current_node,
                                          current_edge->dest)) {
                    struct copy_stack * new_copy_top;

                    /* push new node */
                    new_copy_top = (struct copy_stack *)
                                   malloc(sizeof(struct copy_stack));
                    update_extra_memory(sizeof(struct copy_stack));
                    new_copy_top->below = copy_top;
                    new_copy_top->data = current_edge->dest;
                    new_copy_top->data->visited = ON_STACK;
                    copy_top = new_copy_top;

                }
                /* free edge */
                if(current_edge) {
                    update_extra_memory(-sizeof(struct copy_graph_edge));
                    free(current_edge);
                }
            }
        }
    }
    return topo_head;
}