/* * 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); }
/* * 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); }
/** * 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; }