/* * Check whether @node is possible vroot of @object. */ static void handle_vroot(struct inode *object, znode * node) { file_plugin *fplug; coord_t coord; fplug = inode_file_plugin(object); assert("nikita-3353", fplug != NULL); assert("nikita-3354", fplug->owns_item != NULL); if (unlikely(node_is_empty(node))) return; coord_init_first_unit(&coord, node); /* * if leftmost item of @node belongs to @object, we cannot be sure * that @node is vroot of @object, because, some items of @object are * probably in the sub-tree rooted at the left neighbor of @node. */ if (fplug->owns_item(object, &coord)) return; coord_init_last_unit(&coord, node); /* mutatis mutandis for the rightmost item */ if (fplug->owns_item(object, &coord)) return; /* otherwise, @node is possible vroot of @object */ inode_set_vroot(object, node); }
void test_nodestore () { gint i; NodeStore *store; Part *part; Wire *wire; Node *node; Coords p_pos = {111.,22.}; Coords n_pos = {111.,33.}; Coords w_pos = {111.,7.}; Coords w_len = {0.,88.}; store = node_store_new (); part = part_new (); wire = wire_new (); // add one Pin with a offset that is on the wire when rotation N*Pi times Pin *pin = g_new (Pin, 1); pin->offset.x = n_pos.x - p_pos.x; pin->offset.y = n_pos.y - p_pos.y; GSList *list = NULL; list = g_slist_prepend (list, pin); part_set_pins (part, list); g_slist_free (list); item_data_set_pos (ITEM_DATA (part), &p_pos); item_data_set_pos (ITEM_DATA (wire), &w_pos); wire_set_length (wire, &w_len); node_store_add_part (store, part); node_store_add_wire (store, wire); { for (i=0; i<11; i++) item_data_rotate (ITEM_DATA (part), 90, NULL); item_data_set_pos (ITEM_DATA (part), &w_len); for (i=0; i<4; i++) item_data_rotate (ITEM_DATA (part), 90, NULL); item_data_set_pos (ITEM_DATA (part), &n_pos); for (i=0; i<7; i++) item_data_rotate (ITEM_DATA (part), -90, NULL); item_data_set_pos (ITEM_DATA (part), &p_pos); } g_assert (node_store_is_wire_at_pos (store, n_pos)); g_assert (node_store_is_pin_at_pos (store, n_pos)); node = node_store_get_node (store, n_pos); g_assert (!node_is_empty (node)); g_assert (node_needs_dot (node)); node_store_remove_part (store, part); node_store_remove_wire (store, wire); g_object_unref (store); }
static unsigned _bdd_mgr_get_free_index (bdd_mgr_t *mgr) { unsigned mask = mgr->capacity - 1; unsigned i = (mgr->last_used_alloc_idx + 1) & mask; assert (mgr->num_nodes < mgr->capacity - 1); while (!node_is_empty (mgr->nodes[i])) i = (i + 1) & mask; mgr->last_used_alloc_idx = i; return i; }
int node_store_remove_part (NodeStore *self, Part *part) { Node *node; SheetPos lookup_key; SheetPos pos; gdouble x, y; int i, num_pins; Pin *pins; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part != NULL, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); self->parts = g_list_remove (self->parts, part); self->items = g_list_remove (self->items, part); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { x = pos.x + pins[i].offset.x; y = pos.y + pins[i].offset.y; // Use the position of the pin as lookup key. lookup_key.x = x; lookup_key.y = y; node = g_hash_table_lookup (self->nodes, &lookup_key); if (node) { if (!node_remove_pin (node, &pins[i])) { g_warning ("Couldn't remove pin."); return FALSE; } // If the node is empty after removing the pin, // remove the node as well. if (node_is_empty (node)) { g_hash_table_remove (self->nodes, &lookup_key); g_object_unref (G_OBJECT (node)); } } else { return FALSE; } } return TRUE; }
int node_store_remove_wire (NodeStore *store, Wire *wire) { GSList *list; SheetPos lookup_key, pos, length; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire != NULL, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); if (item_data_get_store (ITEM_DATA (wire)) == NULL) { g_warning ("Trying to remove non-stored wire."); return FALSE; } wire_get_pos_and_length (wire, &pos, &length); store->wires = g_list_remove (store->wires, wire); store->items = g_list_remove (store->items, wire); // If the nodes that this wire passes through will be // empty when the wire is removed, remove the node as well. // We must work on a copy of the nodes list, since it // changes as we remove nodes. list = g_slist_copy (wire_get_nodes (wire)); for (; list; list = list->next) { Node *node = list->data; lookup_key = node->key; node_remove_wire (node, wire); wire_remove_node (wire, node); if (node_is_empty (node)) g_hash_table_remove (store->nodes, &lookup_key); } g_slist_free (list); return TRUE; }
/** * remove/unregister a part from the nodestore * this does _not_ free the part! */ gboolean node_store_remove_part (NodeStore *self, Part *part) { Node *node; Coords pin_pos; Coords part_pos; int i, num_pins; Pin *pins; g_return_val_if_fail (self, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); self->parts = g_list_remove (self->parts, part); self->items = g_list_remove (self->items, part); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { pin_pos.x = part_pos.x + pins[i].offset.x; pin_pos.y = part_pos.y + pins[i].offset.y; node = g_hash_table_lookup (self->nodes, &pin_pos); if (node) { if (!node_remove_pin (node, &pins[i])) { g_warning ("Could not remove pin[%i] from node %p.", i, node); return FALSE; } // If the node is empty after removing the pin, // remove the node as well. if (node_is_empty (node)) { g_hash_table_remove (self->nodes, &pin_pos); g_object_unref (G_OBJECT (node)); } } else { return FALSE; } } return TRUE; }
/** * removes/unregisters a wire from the nodestore * this does _not_ free the wire itself! */ gboolean node_store_remove_wire (NodeStore *store, Wire *wire) { GSList *copy, *iter; Coords lookup_key; g_return_val_if_fail (store, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); if (item_data_get_store (ITEM_DATA (wire)) == NULL) { g_warning ("Trying to remove not-stored wire %p.", wire); return FALSE; } store->wires = g_list_remove (store->wires, wire); store->items = g_list_remove (store->items, wire); // If the nodes that this wire passes through will be // empty when the wire is removed, remove the node as well. // FIXME if done properly, a list copy is _not_ necessary copy = g_slist_copy (wire_get_nodes (wire)); for (iter = copy; iter; iter = iter->next) { Node *node = iter->data; lookup_key = node->key; node_remove_wire (node, wire); wire_remove_node (wire, node); if (node_is_empty (node)) g_hash_table_remove (store->nodes, &lookup_key); } g_slist_free (copy); return TRUE; }
/* main function that handles common parts of tree traversal: starting (fake znode handling), restarts, error handling, completion */ static lookup_result traverse_tree(cbk_handle * h/* search handle */) { int done; int iterations; int vroot_used; assert("nikita-365", h != NULL); assert("nikita-366", h->tree != NULL); assert("nikita-367", h->key != NULL); assert("nikita-368", h->coord != NULL); assert("nikita-369", (h->bias == FIND_EXACT) || (h->bias == FIND_MAX_NOT_MORE_THAN)); assert("nikita-370", h->stop_level >= LEAF_LEVEL); assert("nikita-2949", !(h->flags & CBK_DKSET)); assert("zam-355", lock_stack_isclean(get_current_lock_stack())); done = 0; iterations = 0; vroot_used = 0; /* loop for restarts */ restart: assert("nikita-3024", reiser4_schedulable()); h->result = CBK_COORD_FOUND; /* connect_znode() needs it */ h->ld_key = *reiser4_min_key(); h->rd_key = *reiser4_max_key(); h->flags |= CBK_DKSET; h->error = NULL; if (!vroot_used && h->object != NULL) { vroot_used = 1; done = prepare_object_lookup(h); if (done == LOOKUP_REST) goto restart; else if (done == LOOKUP_DONE) return h->result; } if (h->parent_lh->node == NULL) { done = get_uber_znode(h->tree, ZNODE_READ_LOCK, ZNODE_LOCK_LOPRI, h->parent_lh); assert("nikita-1637", done != -E_DEADLOCK); h->block = h->tree->root_block; h->level = h->tree->height; h->coord->node = h->parent_lh->node; if (done != 0) return done; } /* loop descending a tree */ while (!done) { if (unlikely((iterations > REISER4_CBK_ITERATIONS_LIMIT) && IS_POW(iterations))) { warning("nikita-1481", "Too many iterations: %i", iterations); reiser4_print_key("key", h->key); ++iterations; } else if (unlikely(iterations > REISER4_MAX_CBK_ITERATIONS)) { h->error = "reiser-2018: Too many iterations. Tree corrupted, or (less likely) starvation occurring."; h->result = RETERR(-EIO); break; } switch (cbk_level_lookup(h)) { case LOOKUP_CONT: move_lh(h->parent_lh, h->active_lh); continue; default: wrong_return_value("nikita-372", "cbk_level"); case LOOKUP_DONE: done = 1; break; case LOOKUP_REST: hput(h); /* deadlock avoidance is normal case. */ if (h->result != -E_DEADLOCK) ++iterations; reiser4_preempt_point(); goto restart; } } /* that's all. The rest is error handling */ if (unlikely(h->error != NULL)) { warning("nikita-373", "%s: level: %i, " "lock_level: %i, stop_level: %i " "lock_mode: %s, bias: %s", h->error, h->level, h->lock_level, h->stop_level, lock_mode_name(h->lock_mode), bias_name(h->bias)); reiser4_print_address("block", &h->block); reiser4_print_key("key", h->key); print_coord_content("coord", h->coord); } /* `unlikely' error case */ if (unlikely(IS_CBKERR(h->result))) { /* failure. do cleanup */ hput(h); } else { assert("nikita-1605", WITH_DATA_RET (h->coord->node, 1, ergo((h->result == CBK_COORD_FOUND) && (h->bias == FIND_EXACT) && (!node_is_empty(h->coord->node)), coord_is_existing_item(h->coord)))); } return h->result; }
/* Execute actor for each item (or unit, depending on @through_units_p), starting from @coord, right-ward, until either: - end of the tree is reached - unformatted node is met - error occurred - @actor returns 0 or less Error code, or last actor return value is returned. This is used by plugin/dir/hashe_dir.c:reiser4_find_entry() to move through sequence of entries with identical keys and alikes. */ int reiser4_iterate_tree(reiser4_tree * tree /* tree to scan */ , coord_t *coord /* coord to start from */ , lock_handle * lh /* lock handle to start with and to * update along the way */ , tree_iterate_actor_t actor /* function to call on each * item/unit */ , void *arg /* argument to pass to @actor */ , znode_lock_mode mode /* lock mode on scanned nodes */ , int through_units_p /* call @actor on each item or on * each unit */ ) { int result; assert("nikita-1143", tree != NULL); assert("nikita-1145", coord != NULL); assert("nikita-1146", lh != NULL); assert("nikita-1147", actor != NULL); result = zload(coord->node); coord_clear_iplug(coord); if (result != 0) return result; if (!coord_is_existing_unit(coord)) { zrelse(coord->node); return -ENOENT; } while ((result = actor(tree, coord, lh, arg)) > 0) { /* move further */ if ((through_units_p && coord_next_unit(coord)) || (!through_units_p && coord_next_item(coord))) { do { lock_handle couple; /* move to the next node */ init_lh(&couple); result = reiser4_get_right_neighbor(&couple, coord->node, (int)mode, GN_CAN_USE_UPPER_LEVELS); zrelse(coord->node); if (result == 0) { result = zload(couple.node); if (result != 0) { done_lh(&couple); return result; } coord_init_first_unit(coord, couple.node); done_lh(lh); move_lh(lh, &couple); } else return result; } while (node_is_empty(coord->node)); } assert("nikita-1149", coord_is_existing_unit(coord)); } zrelse(coord->node); return result; }