static void tree_node_destroy (DirectTree *tree, DirectNode *node) { if (node) { tree_node_destroy (tree, node->left); tree_node_destroy (tree, node->right); if (node->value) D_FREE(node->value); D_FREE(node); } }
/** * Destroys and frees the node and all children * * @param parent Parent node to be destroyed */ static void tree_node_destroy (struct MeshTunnelTreeNode *parent) { struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *next; #if MESH_TREE_DEBUG struct GNUNET_PeerIdentity id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying node %u\n", parent->peer); GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: (%s)\n", GNUNET_i2s (&id)); #endif n = parent->children_head; while (NULL != n) { next = n->next; tree_node_destroy (n); n = next; } GNUNET_PEER_change_rc (parent->peer, -1); if (NULL != parent->parent) GNUNET_CONTAINER_DLL_remove (parent->parent->children_head, parent->parent->children_tail, parent); GNUNET_free (parent); }
/** * Delete the current path to the peer, including all now unused relays. * The destination peer is NOT destroyed, it is returned in order to either set * a new path to it or destroy it explicitly, taking care of it's child nodes. * * @param t Tunnel tree where to delete the path from. * @param peer_id Short ID of the destination peer whose path we want to remove. * @param cb Callback to use to notify about disconnected peers. * @param cbcls Closure for cb. * * @return pointer to the pathless node. * NULL when not found */ struct MeshTunnelTreeNode * tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, MeshTreeCallback cb, void *cbcls) { struct MeshTunnelTreeNode *parent; struct MeshTunnelTreeNode *node; struct MeshTunnelTreeNode *n; #if MESH_TREE_DEBUG struct GNUNET_PeerIdentity id; GNUNET_PEER_resolve (peer_id, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting path to %s.\n", GNUNET_i2s (&id)); #endif if (peer_id == t->root->peer) return NULL; for (n = t->disconnected_head; NULL != n; n = n->next) { if (n->peer == peer_id) { /* Was already pathless, waiting for reconnection */ GNUNET_CONTAINER_DLL_remove (t->disconnected_head, t->disconnected_tail, n); return n; } } n = tree_find_peer (t, peer_id); if (NULL == n) return NULL; node = n; parent = n->parent; GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, n); n->parent = NULL; while (MESH_PEER_RELAY == parent->status && NULL == parent->children_head) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting node %s.\n", GNUNET_i2s (&id)); #endif n = parent->parent; tree_node_destroy (parent); parent = n; } #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Not deleted peer %s.\n", GNUNET_i2s (&id)); #endif tree_mark_peers_disconnected (t, node, cb, cbcls); return node; }
static void destroy_node_without_reporting (FMTreeModel *model, TreeNode *node) { abandon_node_ref_count (model, node); stop_monitoring_directory (model, node); node->inserted = FALSE; destroy_children_without_reporting (model, node); g_hash_table_remove (node->root->file_to_node_map, node->file); tree_node_destroy (model, node); }
/** * Destroy the whole tree and free all used memory and Peer_Ids * * @param t Tree to be destroyed */ void tree_destroy (struct MeshTunnelTree *t) { #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying tree\n"); #endif tree_node_destroy (t->root); GNUNET_CONTAINER_multihashmap_iterate (t->first_hops, &iterate_free, NULL); GNUNET_CONTAINER_multihashmap_destroy (t->first_hops); GNUNET_free (t); }
/** * Deletes a peer from a tunnel, liberating all unused resources on the path to * it. It shouldn't have children, if it has they will be destroyed as well. * If the tree is not local and no longer has any paths, the root node will be * destroyed and marked as NULL. * * @param t Tunnel tree to use. * @param peer Short ID of the peer to remove from the tunnel tree. * @param cb Callback to notify client of disconnected peers. * @param cbcls Closure for cb. * * @return GNUNET_OK or GNUNET_SYSERR */ int tree_del_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer, MeshTreeCallback cb, void *cbcls) { struct MeshTunnelTreeNode *n; n = tree_del_path (t, peer, cb, cbcls); if (NULL == n) { GNUNET_break (0); return GNUNET_YES; } GNUNET_break_op (NULL == n->children_head); tree_node_destroy (n); if (NULL == t->root->children_head && t->me != t->root) { tree_node_destroy (t->root); t->root = NULL; return GNUNET_NO; } return GNUNET_YES; }
void direct_tree_destroy( DirectTree *tree ) { unsigned int i; for (i = 0; i < 96; i++) { if (tree->fast_keys[i]) D_FREE( tree->fast_keys[i] ); } tree_node_destroy( tree, tree->root ); D_FREE( tree ); }