static int upload_tree(struct test_tree *base, struct gui_tree *tree, struct tree_node *node) { int i = 0, n = 0; enum gui_tree_node_operation op; if (node->count) { i = 0; op = gui_panel_tree_begin_node(tree, node->name, &node->state); while (i < node->count) i += upload_tree(base, tree, node->children[i]); gui_panel_tree_end_node(tree); } else op = gui_panel_tree_leaf(tree, node->name, &node->state); switch (op) { case GUI_NODE_NOP: break; case GUI_NODE_CUT: tree_remove_node(node->parent, node); tree_push_node(base, node); return 0; case GUI_NODE_DELETE: tree_remove_node(node->parent, node); break; return 0; case GUI_NODE_PASTE: i = 0; n = base->count; while (i++ < n) tree_add_node(node, tree_pop_node(base)); case GUI_NODE_CLONE: default:break; } return 1; }
static void environment_destroy (sexpr env) { struct environment *t = (struct environment *)env; int_pointer hash = hash_murmur2_pt ((void *)&(t->environment), sizeof(t->environment), 0); free_pool_mem ((void *)env); tree_remove_node(&environment_tree, hash); }
/* * Walk up the tree and: * 1. release pseudo exportinfo if it has no child * 2. release visible in parent's exportinfo * 3. delete non-exported leaf nodes from tree * * Deleting of nodes will start only if the unshared * node was a leaf node. * Deleting of nodes will finish when we reach a node which * has children or is a real export, then we might still need * to continue releasing visibles, until we reach VROOT node. */ void treeclimb_unexport(struct exportinfo *exip) { treenode_t *tnode, *old_nd; treenode_t *connect_point = NULL; ASSERT(RW_WRITE_HELD(&exported_lock)); tnode = exip->exi_tree; /* * The unshared exportinfo was unlinked in unexport(). * Zeroing tree_exi ensures that we will skip it. */ tnode->tree_exi = NULL; if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */ tnode->tree_vis->vis_exported = 0; while (tnode != NULL) { /* Stop at VROOT node which is exported or has child */ if (TREE_ROOT(tnode) && (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL)) break; /* Release pseudo export if it has no child */ if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) && tnode->tree_child_first == NULL) { export_unlink(tnode->tree_exi); exi_rele(tnode->tree_exi); } /* Release visible in parent's exportinfo */ if (tnode->tree_vis != NULL) less_visible(vis2exi(tnode), tnode->tree_vis); /* Continue with parent */ old_nd = tnode; tnode = tnode->tree_parent; /* Remove itself, if this is a leaf and non-exported node */ if (old_nd->tree_child_first == NULL && !TREE_EXPORTED(old_nd)) { tree_remove_node(old_nd); connect_point = tnode; } } /* Update the change timestamp */ if (connect_point != NULL) tree_update_change(connect_point, NULL); }
static unsigned int test_tree_node_removal(unsigned int keys) { struct tree *t = tree_create (); unsigned int i; struct tree_node *n; for (i = 0; i < keys; i++) { tree_add_node_value (t, i, sentinelvalue(i)); } /* remove half the nodes */ for (i = 0; i < keys; i+=2) { tree_remove_node (t, i); } /* search for the nodes that should still be present */ for (i = 1; i < keys; i+=2) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 15; } if (n->key != i) { tree_destroy(t); return 16; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 17; } } /* search for the nodes that should be missing */ for (i = 0; i < keys; i+=2) { n = tree_get_node (t, i); if (n != (struct tree_node *)0) { tree_destroy(t); return 18; } } /* search for an arbitrary node that can't be present */ n = tree_get_node (t, keys + 1); if (n != (struct tree_node *)0) { tree_destroy(t); return 19; } /* we do the searches twice to stress the optimising algo once it's in */ /* search for the nodes that should still be present */ for (i = 1; i < keys; i+=2) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 20; } if (n->key != i) { tree_destroy(t); return 21; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 22; } } /* search for the nodes that should be missing */ for (i = 0; i < keys; i+=2) { n = tree_get_node (t, i); if (n != (struct tree_node *)0) { tree_destroy(t); return 23; } } /* remove the remaining nodes */ for (i = 1; i < keys; i+=2) { tree_remove_node (t, i); } if (t->root != (struct tree_node *)0) { tree_destroy(t); return 24; } tree_destroy(t); return 0; }