static DirectNode * tree_node_insert (DirectTree *tree, DirectNode *node, void *key, void *value, int *inserted) { int cmp; int old_balance; if (!node) { *inserted = 1; return tree_node_new (tree, key, value); } cmp = key - node->key; if (cmp == 0) { node->value = value; return node; } if (cmp < 0) { if (node->left) { old_balance = node->left->balance; node->left = tree_node_insert (tree, node->left, key, value, inserted); if ((old_balance != node->left->balance) && node->left->balance) node->balance -= 1; } else { *inserted = 1; node->left = tree_node_new (tree, key, value); node->balance -= 1; } } else if (cmp > 0) { if (node->right) { old_balance = node->right->balance; node->right = tree_node_insert (tree, node->right, key, value, inserted); if ((old_balance != node->right->balance) && node->right->balance) node->balance += 1; } else { *inserted = 1; node->right = tree_node_new (tree, key, value); node->balance += 1; } } if (*inserted && (node->balance < -1 || node->balance > 1)) node = tree_node_balance (node); return node; }
static TreeNode * create_node_for_file (FMTreeModelRoot *root, NemoFile *file) { TreeNode *node; g_assert (get_node_from_file (root, file) == NULL); node = tree_node_new (file, root); g_hash_table_insert (root->file_to_node_map, node->file, node); return node; }
static void add_reg_key(struct regedit *regedit, struct tree_node *node, bool subkey) { char *name; const char *msg; if (!subkey && !node->parent) { return; } msg = "Enter name of new key"; if (subkey) { msg = "Enter name of new subkey"; } dialog_input(regedit, &name, "New Key", msg); if (name) { WERROR rv; struct registry_key *new_key; struct tree_node *new_node; struct tree_node *list; struct tree_node *parent; if (subkey) { parent = node; list = node->child_head; } else { parent = node->parent; list = tree_node_first(node); SMB_ASSERT(list != NULL); } rv = reg_key_add_name(regedit, parent->key, name, NULL, NULL, &new_key); if (W_ERROR_IS_OK(rv)) { /* The list of subkeys may not be present in cache yet, so if not, don't bother allocating a new node for the key. */ if (list) { new_node = tree_node_new(parent, parent, name, new_key); SMB_ASSERT(new_node); tree_node_append_last(list, new_node); } list = tree_node_first(node); tree_view_clear(regedit->keys); tree_view_update(regedit->keys, list); } else { dialog_notice(regedit, DIA_ALERT, "New Key", "Failed to create key."); } talloc_free(name); } }
/** * Create a new tree. * * @param peer A short peer id of the root of the tree. * * @return A newly allocated and initialized tunnel tree. */ struct MeshTunnelTree * tree_new (GNUNET_PEER_Id peer) { struct MeshTunnelTree *tree; tree = GNUNET_malloc (sizeof (struct MeshTunnelTree)); tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); tree->root = tree_node_new (NULL, peer); tree->root->status = MESH_PEER_ROOT; if (1 == peer) { tree->me = tree->root; } return tree; }
/* load all available hives */ static struct tree_node *load_hives(TALLOC_CTX *mem_ctx, struct registry_context *ctx) { const char *hives[] = { "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_PERFORMANCE_DATA", "HKEY_USERS", "HKEY_CURRENT_CONFIG", "HKEY_DYN_DATA", "HKEY_PERFORMANCE_TEXT", "HKEY_PERFORMANCE_NLSTEXT", NULL }; struct tree_node *root, *prev, *node; struct registry_key *key; WERROR rv; size_t i; root = NULL; prev = NULL; for (i = 0; hives[i] != NULL; ++i) { rv = reg_get_predefined_key_by_name(ctx, hives[i], &key); if (!W_ERROR_IS_OK(rv)) { continue; } node = tree_node_new(mem_ctx, NULL, hives[i], key); if (node == NULL) { return NULL; } if (root == NULL) { root = node; } if (prev) { tree_node_append(prev, node); } prev = node; } return root; }
static WatchTree * tree_node_get_child (WatchTree *node, const StringRef *ref, gboolean create) { WatchTree *child; if (!node->children) node->children = g_hash_table_new_full (string_ref_hash, string_ref_equal, NULL, tree_node_free); child = g_hash_table_lookup (node->children, ref); if (!child && create) { child = tree_node_new (node->full_path, ref); g_hash_table_add (node->children, child); } return child; }
/** * Integrate a stand alone path into the tunnel tree. * If the peer toward which the new path is already in the tree, the peer * and its children will be maked as disconnected and the callback * will be called on each one of them. They will be maked as online only after * receiving a PATH ACK for the new path for each one of them, so the caller * should take care of sending a new CREATE PATH message for each disconnected * peer. * * @param t Tunnel where to add the new path. * @param p Path to be integrated. * @param cb Callback to use to notify about peers temporarily disconnecting. * @param cbcls Closure for cb. * * @return GNUNET_OK in case of success. * GNUNET_SYSERR in case of error. * * TODO: optimize * - go backwards on path looking for each peer in the present tree * - do not disconnect peers until new path is created & connected */ int tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, MeshTreeCallback cb, void *cbcls) { struct MeshTunnelTreeNode *parent; struct MeshTunnelTreeNode *oldnode; struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *c; struct GNUNET_PeerIdentity id; int me; unsigned int i; #if MESH_TREE_DEBUG GNUNET_PEER_resolve (p->peers[p->length - 1], &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding path [%u] towards peer %s.\n", p->length, GNUNET_i2s (&id)); #endif GNUNET_assert (0 != p->length); parent = n = t->root; if (n->peer != p->peers[0]) { GNUNET_break (0); return GNUNET_SYSERR; } if (1 == p->length) return GNUNET_OK; oldnode = tree_del_path (t, p->peers[p->length - 1], cb, cbcls); /* Look for the first node that is not already present in the tree * * Assuming that the tree is somewhat balanced, O(log n * log N). * - Length of the path is expected to be log N (size of whole network). * - Each level of the tree is expected to have log n children (size of tree). */ me = t->root->peer == 1 ? 0 : -1; for (i = 1; i < p->length; i++) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (p->peers[i], &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Looking for peer %s.\n", GNUNET_i2s (&id)); #endif parent = n; if (p->peers[i] == 1) me = i; for (c = n->children_head; NULL != c; c = c->next) { if (c->peer == p->peers[i]) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Found in children of %s.\n", GNUNET_i2s (&id)); #endif n = c; break; } } /* If we couldn't find a child equal to path[i], we have reached the end * of the common path. */ if (parent == n) break; } #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: All childen visited.\n"); #endif /* Add the rest of the path as a branch from parent. */ while (i < p->length) { #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding peer %u to %u.\n", p->peers[i], parent->peer); GNUNET_PEER_resolve (p->peers[i], &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding peer %s.\n", GNUNET_i2s (&id)); GNUNET_PEER_resolve (parent->peer, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: to %s.\n", GNUNET_i2s (&id)); #endif if (i == p->length - 1 && NULL != oldnode) { #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Putting old node into place.\n"); #endif oldnode->parent = parent; GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail, oldnode); tree_node_update_first_hops (t, oldnode, NULL); n = oldnode; } else { #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Creating new node.\n"); #endif n = tree_node_new (parent, p->peers[i]); n->status = MESH_PEER_RELAY; } if (n->peer == 1) { t->me = n; me = i; } i++; parent = n; } n->status = MESH_PEER_SEARCHING; GNUNET_break (-1 != me); /* Add info about first hop into hashmap. */ if (-1 != me && me < p->length - 1) { #if MESH_TREE_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: finding first hop (own pos %d/%u)\n", me, p->length - 1); #endif GNUNET_PEER_resolve (p->peers[me + 1], &id); tree_update_first_hops (t, p->peers[me + 1], &id); } #if MESH_TREE_DEBUG else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: was last in path, not updating first hops (%d/%u)\n", me, p->length - 1); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: New node added.\n"); #endif if (NULL == t->me) t->me = tree_find_peer (t, 1); return GNUNET_OK; }
static void add_reg_key(struct regedit *regedit, struct tree_node *node, bool subkey) { const char *name; const char *msg; if (!subkey && tree_node_is_top_level(node)) { return; } msg = "Enter name of new key"; if (subkey) { msg = "Enter name of new subkey"; } dialog_input(regedit, &name, "New Key", msg); if (name) { WERROR rv; struct registry_key *new_key; struct tree_node *new_node; struct tree_node *list; struct tree_node *parent; if (subkey) { parent = node; list = node->child_head; } else { parent = node->parent; list = tree_node_first(node); SMB_ASSERT(list != NULL); } rv = reg_key_add_name(regedit, parent->key, name, NULL, NULL, &new_key); if (W_ERROR_IS_OK(rv)) { /* The list of subkeys may not be present in cache yet, so if not, don't bother allocating a new node for the key. */ if (list) { new_node = tree_node_new(parent, parent, name, new_key); SMB_ASSERT(new_node); tree_node_insert_sorted(list, new_node); } else { /* Reopen the parent key to make sure the new subkey will be noticed. */ tree_node_reopen_key(regedit->registry_context, parent); } list = tree_node_first(node); tree_view_clear(regedit->keys); tree_view_update(regedit->keys, list); if (!subkey) { node = new_node; } tree_view_set_current_node(regedit->keys, node); load_values(regedit); } else { msg = get_friendly_werror_msg(rv); dialog_notice(regedit, DIA_ALERT, "New Key", "Failed to create key: %s", msg); } talloc_free(discard_const(name)); } }