Beispiel #1
0
/* 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);
}
Beispiel #3
0
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;
	}
}
Beispiel #4
0
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);
}
Beispiel #5
0
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 */
Beispiel #7
0
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;
  }