/* Remove given user/cache_info from the AVL trees * * @note The caller must hold uid2grp_user_lock for write. */ static void uid2grp_remove_user(struct cache_info *info) { uid_grplist_cache[info->uid % id_cache_size] = NULL; avltree_remove(&info->uid_node, &uid_tree); avltree_remove(&info->uname_node, &uname_tree); /* We decrement hold on group data when it is * removed from cache trees. */ uid2grp_release_group_data(info->gdata); gsh_free(info); }
static inline void gweakref_delete_impl(gweakref_table_t *wt, gweakref_t *ref, uint32_t flags) { struct avltree_node *node; gweakref_priv_t refk, *tref; gweakref_partition_t *wp; /* lookup up ref.ptr, delete iff ref.ptr is found and * ref.gen == found.gen */ refk.k = *ref; wp = gwt_partition_of_addr_k(wt, refk.k.ptr); if (!(flags & GWR_FLAG_WLOCKED)) pthread_rwlock_wrlock(&wp->lock); node = avltree_lookup(&refk.node_k, &wp->t); if (node) { /* found it, maybe */ tref = avltree_container_of(node, gweakref_priv_t, node_k); /* XXX generation mismatch would be in error, we think */ if (tref->k.gen == ref->gen) { /* unhook it */ avltree_remove(node, &wp->t); gsh_free(tref); if (wp->cache) wp->cache[cache_offsetof(wt, refk.k.ptr)] = NULL; } } if (!(flags & GWR_FLAG_WLOCKED)) pthread_rwlock_unlock(&wp->lock); }
void avl_unit_clear_tree(struct avltree *t) { avl_unit_val_t *v; struct avltree_node *node, *next_node; if (avltree_size(t) < 1) return; node = avltree_first(t); while (node) { next_node = avltree_next(node); v = avltree_container_of(node, avl_unit_val_t, node_k); avltree_remove(&v->node_k, &avl_tree_1); avl_unit_free_val(v); node = next_node; } }
void delete_long_val(struct avltree *t, unsigned long l) { struct avltree_node *node; avl_unit_val_t *v, *v2; /* new key, v */ v = avl_unit_new_val(l); v->key = l; /* find mapping */ node = avltree_lookup(&v->node_k, t); v2 = avltree_container_of(node, avl_unit_val_t, node_k); CU_ASSERT(v2->key == l); /* delete mapping */ avltree_remove(&v2->node_k, t); /* free original v */ avl_unit_free_val(v2); /* free search k, v */ avl_unit_free_val(v); }
void deletes_tree_10000(void) { struct avltree_node *node; avl_unit_val_t *v2, *v = avl_unit_new_val(0); int ix; for (ix = 1; ix < 10001; ++ix) { /* reuse key */ v->key = ix; /* find mapping */ node = avltree_lookup(&v->node_k, &avl_tree_10000); v2 = avltree_container_of(node, avl_unit_val_t, node_k); CU_ASSERT(v2->val == (ix + 1)); /* and remove it */ avltree_remove(&v2->node_k, &avl_tree_10000); avl_unit_free_val(v2); } /* free search k */ avl_unit_free_val(v); }
/** * * cache_inode_operate_cached_dirent: locates a dirent in the cached dirent, * and perform an operation on it. * * Looks up for an dirent in the cached dirent. Thus function searches only in * the entries listed in the dir_entries array. Some entries may be missing but * existing and not be cached (if no readdir was ever performed on the entry for * example. This function provides a way to operate on the dirent. * * @param pentry_parent [IN] directory entry to be searched. * @param name [IN] name for the searched entry. * @param newname [IN] newname if function is used to rename a dirent * @param pclient [INOUT] resource allocated by the client for the nfs management. * @param dirent_op [IN] operation (ADD, LOOKUP or REMOVE) to do on the dirent * if found. * @pstatus [OUT] returned status. * * @return the found entry if its exists and NULL if it is not in the dirent * cache. REMOVE always returns NULL. * */ cache_entry_t *cache_inode_operate_cached_dirent(cache_entry_t * pentry_parent, fsal_name_t * pname, fsal_name_t * newname, cache_inode_client_t * pclient, cache_inode_dirent_op_t dirent_op, cache_inode_status_t * pstatus) { cache_entry_t *pentry = NULL; cache_inode_dir_entry_t dirent_key[1], *dirent; struct avltree_node *dirent_node, *tmpnode; LRU_List_state_t vstate; /* Directory mutation generally invalidates outstanding * readdirs, hence any cached cookies, so in these cases we * clear the cookie avl */ /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* Sanity check */ if(pentry_parent->internal_md.type != DIRECTORY) { *pstatus = CACHE_INODE_BAD_TYPE; return NULL; } /* If no active entry, do nothing */ if (pentry_parent->object.dir.nbactive == 0) { *pstatus = CACHE_INODE_NOT_FOUND; return NULL; } FSAL_namecpy(&dirent_key->name, pname); dirent_node = avltree_lookup(&dirent_key->node_n, &pentry_parent->object.dir.dentries); if (! dirent_node) { *pstatus = CACHE_INODE_NOT_FOUND; /* Right error code (see above)? */ return NULL; } /* unpack avl node */ dirent = avltree_container_of(dirent_node, cache_inode_dir_entry_t, node_n); /* check state of cached dirent */ vstate = dirent->pentry->internal_md.valid_state; if (vstate == VALID || vstate == STALE) { if (vstate == STALE) LogDebug(COMPONENT_NFS_READDIR, "DIRECTORY: found STALE cache entry"); /* Entry was found */ pentry = dirent->pentry; *pstatus = CACHE_INODE_SUCCESS; } /* Did we find something */ if(pentry != NULL) { /* Yes, we did ! */ switch (dirent_op) { case CACHE_INODE_DIRENT_OP_REMOVE: avltree_remove(&dirent->node_n, &pentry_parent->object.dir.dentries); /* release to pool */ ReleaseToPool(dirent, &pclient->pool_dir_entry); pentry_parent->object.dir.nbactive--; *pstatus = CACHE_INODE_SUCCESS; break; case CACHE_INODE_DIRENT_OP_RENAME: /* change the installed inode only the rename can succeed */ FSAL_namecpy(&dirent_key->name, newname); tmpnode = avltree_lookup(&dirent_key->node_n, &pentry_parent->object.dir.dentries); if (tmpnode) { /* rename would cause a collision */ *pstatus = CACHE_INODE_ENTRY_EXISTS; } else { /* remove, rename, and re-insert the object with new keys */ avltree_remove(&dirent->node_n, &pentry_parent->object.dir.dentries); FSAL_namecpy(&dirent->name, newname); tmpnode = avltree_insert(&dirent->node_n, &pentry_parent->object.dir.dentries); if (tmpnode) { /* collision, tree state unchanged--this won't happen */ *pstatus = CACHE_INODE_ENTRY_EXISTS; /* still, try to revert the change in place */ FSAL_namecpy(&dirent->name, pname); tmpnode = avltree_insert(&dirent->node_n, &pentry_parent->object.dir.dentries); } else { *pstatus = CACHE_INODE_SUCCESS; } } /* !found */ break; default: /* Should never occurs, in any case, it cost nothing to handle * this situation */ *pstatus = CACHE_INODE_INVALID_ARGUMENT; break; } /* switch */ } if (*pstatus == CACHE_INODE_SUCCESS) { /* As noted, if a mutating operation was performed, we must * invalidate cached cookies. */ cache_inode_release_dirents( pentry_parent, pclient, CACHE_INODE_AVL_COOKIES); /* Someone has to repopulate the avl cookie cache. Populating it * lazily is ok, but the logic to do it makes supporting simultaneous * readers more involved. Another approach would be to do it in the * background, scheduled from here. */ } return pentry; } /* cache_inode_operate_cached_dirent */
GAULFUNC boolean avltree_test(void) #endif { int i, j; AVLTree *tree; char chars[62]; char chx='x', chX='X', *ch; printf("Testing my dodgy AVL tree routines.\n"); tree = avltree_new(test_avltree_generate); i = 0; for (j = 0; j < 26; j++, i++) { chars[i] = 'A' + (char) j; avltree_insert(tree, &chars[i]); } for (j = 0; j < 26; j++, i++) { chars[i] = 'a' + (char) j; avltree_insert(tree, &chars[i]); } for (j = 0; j < 10; j++, i++) { chars[i] = '0' + (char) j; avltree_insert(tree, &chars[i]); } printf("height: %d\n", avltree_height(tree)); printf("num nodes: %d\n", avltree_num_nodes(tree)); printf("tree: "); avltree_traverse(tree, test_avltree_traverse, NULL); printf("\n"); printf("tree to 'S' then foo: "); avltree_traverse(tree, test_avltree_traverse, "foo"); printf("\n"); for (i = 0; i < 26; i++) if ( !avltree_remove(tree, &chars[i]) ) printf("%c not found.\n", chars[i]); printf("height: %d\n", avltree_height(tree)); printf("num nodes: %d\n", avltree_num_nodes(tree)); printf("tree: "); avltree_traverse(tree, test_avltree_traverse, NULL); printf("\n"); printf("Lookup for 'x': "); ch = (char *) avltree_lookup(tree, (vpointer) &chx); if (ch) printf("Found '%c'\n", *ch); else printf("Not found.\n"); printf("Lookup for 'X': "); ch = (char *) avltree_lookup(tree, (vpointer) &chX); if (ch) printf("Found '%c'\n", *ch); else printf("Not found.\n"); printf("Tests: %s\n", failed?"FAILED":"PASSED"); avltree_delete(tree); return failed; }