コード例 #1
0
ファイル: uid2grp_cache.c プロジェクト: ckhardin/nfs-ganesha
/**
 * @brief Add a user entry to the cache
 *
 * @note The caller must hold uid2grp_user_lock for write.
 *
 * @param[in] group_data that has supplementary groups allocated
 *
 * @retval true on success.
 * @retval false if our reach exceeds our grasp.
 */
bool uid2grp_add_user(struct group_data *gdata)
{
	struct avltree_node *name_node;
	struct avltree_node *id_node;
	struct avltree_node *name_node2 = NULL;
	struct avltree_node *id_node2 = NULL;
	struct cache_info *info;
	struct cache_info *tmp;

	info = gsh_malloc(sizeof(struct cache_info));
	if (!info) {
		LogEvent(COMPONENT_IDMAPPER, "memory alloc failed");
		return false;
	}
	info->uid = gdata->uid;
	info->uname.addr = gdata->uname.addr;
	info->uname.len = gdata->uname.len;
	info->gdata = gdata;

	/* The refcount on group_data should be 1 when we put it in
	 * AVL trees.
	 */
	uid2grp_hold_group_data(gdata);

	/* We may have lost the race to insert. We remove existing
	 * entry and insert this new entry if so!
	 */
	name_node = avltree_insert(&info->uname_node, &uname_tree);
	if (unlikely(name_node)) {
		tmp = avltree_container_of(name_node,
					   struct cache_info,
					   uname_node);
		uid2grp_remove_user(tmp);
		name_node2 = avltree_insert(&info->uname_node, &uname_tree);
	}

	id_node = avltree_insert(&info->uid_node, &uid_tree);
	if (unlikely(id_node)) {
		/* We should not come here unless someone changed uid of
		 * a user. Remove old entry and re-insert the new
		 * entry.
		 */
		tmp = avltree_container_of(id_node,
					   struct cache_info,
					   uid_node);
		uid2grp_remove_user(tmp);
		id_node2 = avltree_insert(&info->uid_node, &uid_tree);
	}
	uid_grplist_cache[info->uid % id_cache_size] = &info->uid_node;

	if (name_node && id_node)
		LogWarn(COMPONENT_IDMAPPER, "shouldn't happen, internal error");
	if ((name_node && name_node2) || (id_node && id_node2))
		LogWarn(COMPONENT_IDMAPPER, "shouldn't happen, internal error");

	return true;
}
コード例 #2
0
ファイル: test_mh_avl.c プロジェクト: dotbugfix/nfs-ganesha
static int qp_avl_insert(struct avltree *t, avl_unit_val_t *v)
{
	/*
	 * Insert with quadatic, linear probing.  A unique k is assured for
	 * any k whenever size(t) < max(uint64_t).
	 *
	 * First try quadratic probing, with coeff. 2 (since m = 2^n.)
	 * A unique k is not assured, since the codomain is not prime.
	 * If this fails, fall back to linear probing from hk.k+1.
	 *
	 * On return, the stored key is in v->hk.k, the iteration
	 * count in v->hk.p.
	 **/
	struct avltree_node *tmpnode;
	uint32_t j, j2;
	uint32_t hk[4];

	assert(avltree_size(t) < UINT64_MAX);

	MurmurHash3_x64_128(v->name, strlen(v->name), 67, hk);
	memcpy(&v->hk.k, hk, 8);

	for (j = 0; j < UINT64_MAX; j++) {
		v->hk.k = (v->hk.k + (j * 2));
		tmpnode = avltree_insert(&v->node_hk, t);
		if (!tmpnode) {
			/* success, note iterations and return */
			v->hk.p = j;
			return 0;
		}
	}

	/* warn debug */

	memcpy(&v->hk.k, hk, 8);
	for (j2 = 1 /* tried j=0 */; j2 < UINT64_MAX; j2++) {
		v->hk.k = v->hk.k + j2;
		tmpnode = avltree_insert(&v->node_hk, t);
		if (!tmpnode) {
			/* success, note iterations and return */
			v->hk.p = j + j2;
			return 0;
		}
		j2++;
	}

	/* warn crit  */
	return -1;
}
コード例 #3
0
ファイル: osm.c プロジェクト: alexbirkett/GPSBabel
static void 
osm_node(const char *args, const char **attrv)
{
	const char **avp = &attrv[0];

	wpt = waypt_new();

        while (*avp) {
		if (strcmp(avp[0], "id") == 0) {
			xasprintf(&wpt->description, "osm-id %s", avp[1]);
			if (! avltree_insert(waypoints, avp[1], (void *)wpt))
				warning(MYNAME ": Duplicate osm-id %s!\n", avp[1]);
			else
				wpt->wpt_flags.fmt_use = 1;
		}
		else if (strcmp(avp[0], "user") == 0) ;
		else if (strcmp(avp[0], "lat") == 0)
			wpt->latitude = atof(avp[1]);
		else if (strcmp(avp[0], "lon") == 0)
			wpt->longitude = atof(avp[1]);
		else if (strcmp(avp[0], "timestamp") == 0)
			wpt->creation_time = xml_parse_time(avp[1], &wpt->microseconds);

		avp += 2;
	}
}
コード例 #4
0
ファイル: mmo.c プロジェクト: idaohang/gpsbabel-flytec
static int
mmo_write_obj_mark(const char *sobj, const char *name)
{
	char *key;
	gbuint16 nr;
	char buf[16];
	int res;
	
	if (avltree_find(mmobjects, sobj, (void *)&key)) {
		nr = (unsigned)atoi(key);
		gbfputuint16(nr, fout);
	}
	else {
		mmo_object_id++;
		snprintf(buf, sizeof(buf), "%u", mmo_object_id);

		DBG(("write", "object \"%s\" registered (id = 0x%04X)\n", mmo_object_id));

		avltree_insert(mmobjects, sobj, xstrdup(buf));
		
		gbfputuint32(mmo_filemark, fout);
		gbfputuint16(strlen(sobj), fout);
		gbfwrite(sobj, strlen(sobj), 1, fout);
	}

	mmo_object_id++;
	res = mmo_object_id;
	mmo_writestr(name);

	return res;
}
コード例 #5
0
gweakref_t gweakref_insert(gweakref_table_t *wt, void *obj)
{
    gweakref_t ret;
    gweakref_priv_t *ref;
    gweakref_partition_t *wp;
    struct avltree_node *node;

    ref = gsh_calloc(1, sizeof(gweakref_priv_t));
    ref->k.ptr = obj;

    wp = (gweakref_partition_t *) gwt_partition_of_addr_k(wt, ref->k.ptr);

    /* XXX initially wt had a single atomic counter, but for any address,
     * partition is fixed, and we must take the partition lock exclusive
     * in any case */
    pthread_rwlock_wrlock(&wp->lock);

    ref->k.gen = ++(wp->genctr);

    node = avltree_insert(&ref->node_k, &wp->t);
    if (! node) {
        /* success */
        ret = ref->k;
    } else {
        /* matching key existed */
        ret.ptr = NULL;
        ret.gen = 0;
    }
    pthread_rwlock_unlock(&wp->lock);

    return (ret);
}
コード例 #6
0
ファイル: mmo.c プロジェクト: idaohang/gpsbabel-flytec
static void
mmo_register_icon(const int id, const char *name)
{
	char key[16];
	
	snprintf(key, sizeof(key), "%d", id);
	avltree_insert(icons, key, xstrdup(name));
}
コード例 #7
0
ファイル: mmo.c プロジェクト: idaohang/gpsbabel-flytec
static void
mmo_register_category_names(const char *name)
{
	char key[16];

	snprintf(key, sizeof(key), "%d", mmo_object_id);
	avltree_insert(category_names, name, xstrdup(key));
}
コード例 #8
0
ファイル: avltree.cpp プロジェクト: guker/Algrithm-Learning
/*
 * 将结点插入到AVL树中,并返回根节点
 *
 * 递归方法
 *
 * 参数说明:
 *     tree AVL树的根结点
 *     key 插入的结点的键值
 * 返回值:
 *     根节点
 */
Node* avltree_insert(AVLTree tree, Type key)
{
    if (tree == NULL)
    {
        // 新建节点
        tree = avltree_create_node(key, NULL, NULL);
        if (tree==NULL)
        {
            printf("ERROR: create avltree node failed!\n");
            return NULL;
        }
    }
    else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况
    {
        tree->left = avltree_insert(tree->left, key);
        // 插入节点后,若AVL树失去平衡,则进行相应的调节。
        if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
        {
            if (key < tree->left->key)
                tree = left_left_rotation(tree);
            else
                tree = left_right_rotation(tree);
        }
    }
    else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况
    {
        tree->right = avltree_insert(tree->right, key);
        // 插入节点后,若AVL树失去平衡,则进行相应的调节。
        if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
        {
            if (key > tree->right->key)
                tree = right_right_rotation(tree);
            else
                tree = right_left_rotation(tree);
        }
    }
    else //key == tree->key)
    {
        printf("添加失败:不允许添加相同的节点!\n");
    }

    tree->height = MAX( HEIGHT(tree->left), HEIGHT(tree->right)) + 1;

    return tree;
}
コード例 #9
0
ファイル: osm.c プロジェクト: alexbirkett/GPSBabel
static void
osm_features_init(void)
{
	int i;
	
	keys = avltree_init(AVLTREE_STATIC_KEYS, MYNAME);
	values = avltree_init(0, MYNAME);
	
	/* the first of osm_features is a place holder */
	for (i = 1; osm_features[i]; i++)
		avltree_insert(keys, osm_features[i], gb_int2ptr(i));
	
	for (i = 0; osm_icon_mappings[i].value; i++) {
		char buff[128];

		buff[0] = osm_icon_mappings[i].key;
		strncpy(&buff[1], osm_icon_mappings[i].value, sizeof(buff) - 1);
		avltree_insert(values, buff, (const void *)&osm_icon_mappings[i]);
	}
}
コード例 #10
0
ファイル: osm.c プロジェクト: alexbirkett/GPSBabel
static void
osm_init_icons(void)
{
	int i;

	if (icons) return;

	icons = avltree_init(AVLTREE_STATIC_KEYS, MYNAME);

	for (i = 0; osm_icon_mappings[i].value; i++)
		avltree_insert(icons, osm_icon_mappings[i].icon, (const void *)&osm_icon_mappings[i]);
}
コード例 #11
0
ファイル: test_avl.c プロジェクト: JevonQ/nfs-ganesha
void insert_long_val(struct avltree *t, unsigned long l)
{
	avl_unit_val_t *v;

	/* new k, v */
	v = avl_unit_new_val(l);

	/* if actual key cannot be marshalled as a pointer */
	v->key = l;

	/* insert mapping */
	avltree_insert(&v->node_k, t);
}
コード例 #12
0
ファイル: boztree_insert.c プロジェクト: debosvi/bozCore
int boztree_insert(boztree_t *t, boztree_id_t const *e) {
    unsigned int n=0;
    void *p;
    if(!t) return (errno=EFAULT, -1);
    if(!e) return (errno=EINVAL, -1);
    if(avltree_search(&t->a, &e->i, &n)) return (errno=EEXIST, -1);

    if(!gensetdyn_new(&t->s, &n)) return (errno=ENOMEM, -1);
    p = gensetdyn_p(&t->s, n);
    memcpy(p, e, t->s.esize);

    avltree_insert(&t->a, n);
    
    return 0;
}
コード例 #13
0
ファイル: test_avl.c プロジェクト: JevonQ/nfs-ganesha
void insert_long_val_safe(struct avltree *t, unsigned long l)
{
	struct avltree_node *node;
	avl_unit_val_t *v;

	/* new k, v */
	v = avl_unit_new_val(l);
	v->key = l;

	node = avltree_lookup(&v->node_k, t);
	if (node == NULL)
		avltree_insert(&v->node_k, t);
	else
		avl_unit_free_val(v);
}
コード例 #14
0
/**
 *
 * revalidate_cookie_cache:  sync cookie avl offsets with the dentry name avl.
 *
 * If no cookies are cached, add those of any dirents in the name avl.  The
 * entry is assumed to be write locked.
 *
 * @param pentry [IN] entry for the parent directory to be read.
 *
 * @return void
 *
 */
static void revalidate_cookie_cache(cache_entry_t *dir_pentry,
                                    cache_inode_client_t *pclient)
{
  struct avltree_node *dirent_node;
  cache_inode_dir_entry_t *dirent;
  int size_n, size_c, ix;

  /* we'll try to add entries to any directory whose cookie
   * avl cache is currently empty (mutating dirent operations
   * clear it) */
#if 0
  if (avltree_size(&dir_pentry->object.dir.cookies) > 0)
      return;
#else
  size_c = avltree_size(&dir_pentry->object.dir.cookies);
  size_n = avltree_size(&dir_pentry->object.dir.dentries);
  if (size_c == size_n)
      return;
  /* the following is safe to call arbitrarily many times, with
   * CACHE_INODE_AVL_COOKIES -only-. */
      cache_inode_release_dirents(dir_pentry,
                                  pclient,
                                  CACHE_INODE_AVL_COOKIES);      
#endif

  dirent_node = avltree_first(&dir_pentry->object.dir.dentries);
  dirent = avltree_container_of(dirent_node,
				cache_inode_dir_entry_t, 
				node_n);

  ix = 3; /* first non-reserved cookie value */
  dirent_node = &dirent->node_n;
  while (dirent_node) {
      dirent = avltree_container_of(dirent_node,
				    cache_inode_dir_entry_t, 
				    node_n);
      dirent->cookie = ix;
      /* XXX we could optimize this somewhat (saving an internal
       * lookup in avltree_insert), by adding an avl append
       * operation */
      (void) avltree_insert(&dirent->node_c,
			    &dir_pentry->object.dir.cookies);
      dirent_node = avltree_next(dirent_node);
      ++ix;
  }

  return;
}
コード例 #15
0
ファイル: test_avl.c プロジェクト: JevonQ/nfs-ganesha
void inserts_tree_10000(void)
{
	avl_unit_val_t *v;
	int ix;

	for (ix = 1; ix < 10001; ++ix) {

		/* new k, v */
		v = avl_unit_new_val(ix);

		/* if actual key cannot be marshalled as a pointer */
		v->key = ix;

		/* insert mapping */
		avltree_insert(&v->node_k, &avl_tree_10000);
	}
}
コード例 #16
0
ファイル: humminbird.c プロジェクト: alexbirkett/GPSBabel
static void
humminbird_read_wpt(gbfile* fin) {

	humminbird_waypt_t w;
	double guder;
	int num_icons;
	waypoint *wpt;
	char buff[10];

	if (! gbfread(&w, 1, sizeof(w), fin))
		fatal(MYNAME ": Unexpected end of file!\n");

	/* Fix endianness - these are now BE */
	w.num = be_read16(&w.num);
	w.zero = be_read16(&w.zero);
	w.depth = be_read16(&w.depth);
	w.time = be_read32(&w.time);
	w.north = be_read32(&w.north);
	w.east = be_read32(&w.east);

	/* All right! Copy the data to the gpsbabel struct... */

	wpt = waypt_new();

	wpt->shortname = xstrndup(w.name, sizeof(w.name));
	wpt->creation_time = w.time;

	guder = gudermannian_i1924(w.north);
	wpt->latitude = geocentric_to_geodetic_hwr(guder);
	wpt->longitude = (double)w.east / EAST_SCALE * 180.0;

	wpt->altitude  = 0.0; /* It's from a fishfinder... */

	if (w.depth != 0)
		WAYPT_SET(wpt,depth,(double)w.depth / 100.0);

	num_icons = sizeof(humminbird_icons) / sizeof(humminbird_icons[0]);
	if (w.icon < num_icons)
		wpt->icon_descr = humminbird_icons[w.icon];

	waypt_add(wpt);
	
	/* register the point over his internal Humminbird "Number" */
	snprintf(buff, sizeof(buff), "%d", w.num);
	avltree_insert(waypoints, buff, wpt);
}
コード例 #17
0
ファイル: mmo.c プロジェクト: idaohang/gpsbabel-flytec
static mmo_data_t *
mmo_register_object(const int objid, const void *ptr, const gpsdata_type type)
{
	char key[16];
	mmo_data_t *data;
	
	data = xcalloc(1, sizeof(*data));
	data->data = (void *)ptr;
	data->visible = 1;
	data->locked = 0;
	data->type = type;
	data->objid = objid;
	
	snprintf(key, sizeof(key), "%d", objid);
	avltree_insert(objects, key, data);
	
	return data;
}
コード例 #18
0
ファイル: error.c プロジェクト: lubberscorrado/tass64
struct file_list_s *enterfile(struct file_s *file, linepos_t epoint) {
    struct avltree_node *b;
    if (!lastfl) {
        lastfl = (struct file_list_s *)malloc(sizeof(struct file_list_s));
        if (!lastfl) err_msg_out_of_memory();
    }
    lastfl->file = file;
    lastfl->epoint = *epoint;

    b = avltree_insert(&lastfl->node, &current_file_list->members, file_list_compare);
    if (!b) {
        lastfl->parent = current_file_list;
        avltree_init(&lastfl->members);
        current_file_list = lastfl;
        lastfl = NULL;
        return current_file_list;
    }
    current_file_list = avltree_container_of(b, struct file_list_s, node);
    return current_file_list;
}
コード例 #19
0
ファイル: dict.c プロジェクト: lulujiang/segc
void
dict_load_words(const char* filename)
{
    FILE* fp = fopen(filename, "r");
    if(fp)
    {
        word_t w;
        while(1)
        {
            if(fscanf(fp, "%s", w) < 0)
                break;
#ifdef AVLTREE
            root = avltree_insert(root, w, make_word_info(w, 0));
#else
            hash_table_insert(root, w, make_word_info(w, 0));
#endif
        }
        fclose(fp);
    }
}
コード例 #20
0
ファイル: humminbird.c プロジェクト: alexbirkett/GPSBabel
static void
humminbird_write_waypoint_wrapper(const waypoint *wpt)
{
	char *key;
	waypoint *tmpwpt;

	xasprintf(&key, "%s\01%.9f\01%.9f", wpt->shortname, wpt->latitude, wpt->longitude);

	if (! avltree_find(waypoints, key, (void *)&tmpwpt)) {
		tmpwpt = (waypoint *)wpt;

		avltree_insert(waypoints, key, wpt);

		tmpwpt->extra_data = gb_int2ptr(waypoint_num + 1);	/* NOT NULL */
		humminbird_write_waypoint(wpt);
	}
	else {
		void *p = tmpwpt->extra_data;
		tmpwpt = (waypoint *)wpt;
		tmpwpt->extra_data = p;
	}

	xfree(key);
}
コード例 #21
0
ファイル: error.c プロジェクト: lubberscorrado/tass64
static inline void err_msg_not_defined2(const str_t *name, const struct label_s *l, int down, linepos_t epoint) {
    struct notdefines_s *tmp2;
    struct avltree_node *b;

    if (constcreated && pass < max_pass) return;

    if (!lastnd) {
        lastnd = (struct notdefines_s *)malloc(sizeof(struct notdefines_s));
        if (!lastnd) err_msg_out_of_memory();
    }

    if (name->data) {
        str_cfcpy(&lastnd->cfname, name);
        lastnd->parent = l;
        lastnd->pass = pass;
        b=avltree_insert(&lastnd->node, &notdefines, notdefines_compare);
        if (b) {
            tmp2 = avltree_container_of(b, struct notdefines_s, node);
            if (tmp2->pass == pass) {
                return;
            }
            tmp2->pass = pass;
        } else {
            if (lastnd->cfname.data == name->data) str_cpy(&lastnd->cfname, name);
コード例 #22
0
ファイル: avltree.c プロジェクト: versionzero/gaul
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;
  }
コード例 #23
0
/**
 *
 * cache_inode_readdir_populate: fully reads a directory in FSAL and caches
 * the related entries.
 *
 * fully reads a directory in FSAL and caches the related entries. No MT
 * safety managed here !!
 *
 * @param pentry [IN]  entry for the parent directory to be read. This must be
 * a DIRECTORY
 * @param ht [IN] hash table used for the cache, unused in this call.
 * @param pclient [INOUT] ressource allocated by the client for the nfs
 * management.
 * @param pcontext [IN] FSAL credentials
 * @param pstatus [OUT] returned status.
 *
 */
cache_inode_status_t cache_inode_readdir_populate(
    cache_entry_t * pentry_dir,
    cache_inode_policy_t policy,
    hash_table_t * ht,
    cache_inode_client_t * pclient,
    fsal_op_context_t * pcontext,
    cache_inode_status_t * pstatus)
{
  fsal_dir_t fsal_dirhandle;
  fsal_status_t fsal_status;
  fsal_attrib_list_t dir_attributes;

  fsal_cookie_t begin_cookie;
  fsal_cookie_t end_cookie;
  fsal_count_t nbfound;
  fsal_count_t iter;
  fsal_boolean_t fsal_eod;

  cache_entry_t *pentry = NULL;
  cache_entry_t *pentry_parent = pentry_dir;
  fsal_attrib_list_t object_attributes;

  cache_inode_create_arg_t create_arg;
  cache_inode_file_type_t type;
  cache_inode_status_t cache_status;
  fsal_dirent_t array_dirent[FSAL_READDIR_SIZE + 20];
  cache_inode_fsal_data_t new_entry_fsdata;
  cache_inode_dir_entry_t *new_dir_entry = NULL;
  uint64_t i = 0;

  /* Set the return default to CACHE_INODE_SUCCESS */
  *pstatus = CACHE_INODE_SUCCESS;

  /* Only DIRECTORY entries are concerned */
  if(pentry_dir->internal_md.type != DIRECTORY)
    {
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }
#ifdef _USE_MFSL_ASYNC
  /* If entry is asynchronous (via MFSL), it should not be repopulated until
     it is synced */
  if(MFSL_ASYNC_is_synced(&pentry_dir->mobject) == FALSE)
    {
      /* Directory is asynchronous, do not repopulate it and let it
       * in the state 'has_been_readdir == FALSE' */
      *pstatus = CACHE_INODE_SUCCESS;
      return *pstatus;
    }
#endif

  /* If directory is already populated , there is no job to do */
  if(pentry_dir->object.dir.has_been_readdir == CACHE_INODE_YES)
    {
      *pstatus = CACHE_INODE_SUCCESS;
      return *pstatus;
    }

  /* Invalidate all the dirents */
  if(cache_inode_invalidate_all_cached_dirent(pentry_dir,
                                              ht,
                                              pclient,
					      pstatus) != CACHE_INODE_SUCCESS)
    return *pstatus;

  /* Open the directory */
  dir_attributes.asked_attributes = pclient->attrmask;
#ifdef _USE_MFSL
  fsal_status = MFSL_opendir(&pentry_dir->mobject,
                             pcontext,
                             &pclient->mfsl_context, &fsal_dirhandle, &dir_attributes, NULL);
#else
  fsal_status = FSAL_opendir(&pentry_dir->object.dir.handle,
                             pcontext, &fsal_dirhandle, &dir_attributes);
#endif
  if(FSAL_IS_ERROR(fsal_status))
    {
      *pstatus = cache_inode_error_convert(fsal_status);

      if(fsal_status.major == ERR_FSAL_STALE)
        {
          cache_inode_status_t kill_status;

          LogEvent(COMPONENT_CACHE_INODE,
                   "cache_inode_readdir: Stale FSAL File Handle detected for pentry = %p, fsal_status=(%u,%u)",
                   pentry_dir, fsal_status.major, fsal_status.minor);

          if(cache_inode_kill_entry(pentry_dir, WT_LOCK, ht, pclient, &kill_status) !=
             CACHE_INODE_SUCCESS)
            LogCrit(COMPONENT_CACHE_INODE,
                    "cache_inode_readdir: Could not kill entry %p, status = %u",
                    pentry_dir, kill_status);

          *pstatus = CACHE_INODE_FSAL_ESTALE;
        }
      return *pstatus;
    }

  /* Loop for readding the directory */
  FSAL_SET_COOKIE_BEGINNING(begin_cookie);
  FSAL_SET_COOKIE_BEGINNING(end_cookie);
  fsal_eod = FALSE;

  do
    {
#ifdef _USE_MFSL
      fsal_status = MFSL_readdir(&fsal_dirhandle,
                                 begin_cookie,
                                 pclient->attrmask,
                                 FSAL_READDIR_SIZE * sizeof(fsal_dirent_t),
                                 array_dirent,
                                 &end_cookie,
                                 &nbfound, &fsal_eod, &pclient->mfsl_context, NULL);
#else
      fsal_status = FSAL_readdir(&fsal_dirhandle,
                                 begin_cookie,
                                 pclient->attrmask,
                                 FSAL_READDIR_SIZE * sizeof(fsal_dirent_t),
                                 array_dirent, &end_cookie, &nbfound, &fsal_eod);
#endif

      if(FSAL_IS_ERROR(fsal_status))
        {
          *pstatus = cache_inode_error_convert(fsal_status);
          return *pstatus;
        }

      for(iter = 0; iter < nbfound; iter++)
        {
          LogFullDebug(COMPONENT_NFS_READDIR,
                       "cache readdir populate found entry %s",
                       array_dirent[iter].name.name);

          /* It is not needed to cache '.' and '..' */
          if(!FSAL_namecmp(&(array_dirent[iter].name), (fsal_name_t *) & FSAL_DOT) ||
             !FSAL_namecmp(&(array_dirent[iter].name), (fsal_name_t *) & FSAL_DOT_DOT))
            {
              LogFullDebug(COMPONENT_NFS_READDIR,
                           "cache readdir populate : do not cache . and ..");
              continue;
            }

          /* If dir entry is a symbolic link, its content has to be read */
          if((type =
              cache_inode_fsal_type_convert(array_dirent[iter].attributes.type)) ==
             SYMBOLIC_LINK)
            {
#ifdef _USE_MFSL
              mfsl_object_t tmp_mfsl;
#endif
              /* Let's read the link for caching its value */
              object_attributes.asked_attributes = pclient->attrmask;
              if( CACHE_INODE_KEEP_CONTENT( pentry_dir->policy ) )
                {
#ifdef _USE_MFSL
                  tmp_mfsl.handle = array_dirent[iter].handle;
                  fsal_status = MFSL_readlink(&tmp_mfsl,
                                              pcontext,
                                              &pclient->mfsl_context,
                                              &create_arg.link_content, &object_attributes, NULL);
#else
                  fsal_status = FSAL_readlink(&array_dirent[iter].handle,
                                              pcontext,
                                              &create_arg.link_content, &object_attributes);
#endif
                }
              else
                {
                   fsal_status.major = ERR_FSAL_NO_ERROR ;
                   fsal_status.minor = 0 ;
                }

              if(FSAL_IS_ERROR(fsal_status))
                {
                  *pstatus = cache_inode_error_convert(fsal_status);

                  if(fsal_status.major == ERR_FSAL_STALE)
                    {
                      cache_inode_status_t kill_status;

                      LogEvent(COMPONENT_CACHE_INODE,
                               "cache_inode_readdir: Stale FSAL File Handle detected for pentry = %p, fsal_status=(%u,%u)",
                               pentry_dir, fsal_status.major, fsal_status.minor );

                      if(cache_inode_kill_entry(pentry_dir, WT_LOCK, ht, pclient, &kill_status) !=
                         CACHE_INODE_SUCCESS)
                        LogCrit(COMPONENT_CACHE_INODE,
                                "cache_inode_readdir: Could not kill entry %p, status = %u",
                                pentry_dir, kill_status);

                      *pstatus = CACHE_INODE_FSAL_ESTALE;
                    }

                  return *pstatus;
                }
            }

          /* Try adding the entry, if it exists then this existing entry is
             returned */
          new_entry_fsdata.handle = array_dirent[iter].handle;
	  new_entry_fsdata.cookie = 0; /* XXX needed? */

          if((pentry = cache_inode_new_entry( &new_entry_fsdata,
		                              &array_dirent[iter].attributes,
		                              type, 
                                              policy,
		                              &create_arg,
		                              NULL, 
		                              ht, 
		                              pclient, 
		                              pcontext, 
		                              FALSE,  /* This is population and no creation */
		                              pstatus)) == NULL)
            return *pstatus;

          cache_status = cache_inode_add_cached_dirent(
	      pentry_parent,
	      &(array_dirent[iter].name),
	      pentry,
	      ht,
	      &new_dir_entry,
	      pclient,
	      pcontext,
	      pstatus);

          if(cache_status != CACHE_INODE_SUCCESS
             && cache_status != CACHE_INODE_ENTRY_EXISTS)
            return *pstatus;

          /*
           * Remember the FSAL readdir cookie associated with this dirent.  This
           * is needed for partial directory reads.
           * 
           * to_uint64 should be a lightweight operation--it is in the current
           * default implementation.  We think the right thing -should- happen
           * therefore with if _USE_MFSL. 
           *
           * I'm ignoring the status because the default operation is a memcmp--
           * we lready -have- the cookie. */

          if (cache_status != CACHE_INODE_ENTRY_EXISTS) {

              (void) FSAL_cookie_to_uint64(&array_dirent[iter].handle,
                                           pcontext, &array_dirent[iter].cookie,
                                           &new_dir_entry->fsal_cookie);

              /* we are filling in all entries, and the cookie avl was
               * cleared before adding dirents */
              new_dir_entry->cookie = i; /* still an offset */
              (void) avltree_insert(&new_dir_entry->node_c,
                                    &pentry_parent->object.dir.cookies);
          } /* !exist */

        } /* iter */
      
      /* Get prepared for next step */
      begin_cookie = end_cookie;

      /* next offset */
      i++;
    }
  while(fsal_eod != TRUE);

  /* Close the directory */
#ifdef _USE_MFSL
  fsal_status = MFSL_closedir(&fsal_dirhandle, &pclient->mfsl_context, NULL);
#else
  fsal_status = FSAL_closedir(&fsal_dirhandle);
#endif
  if(FSAL_IS_ERROR(fsal_status))
    {
      *pstatus = cache_inode_error_convert(fsal_status);
      return *pstatus;
    }

  /* End of work */
  pentry_dir->object.dir.has_been_readdir = CACHE_INODE_YES;
  *pstatus = CACHE_INODE_SUCCESS;
  return *pstatus;
}                               /* cache_inode_readdir_populate */
コード例 #24
0
/**
 *
 * cache_inode_add_cached_dirent: Adds a directory entry to a cached directory.
 *
 * Adds a directory entry to a cached directory. This is use when creating a
 * new entry through nfs and keep it to the cache. It also allocates and caches
 * the entry.  This function can be call iteratively, within a loop (like what
 * is done in cache_inode_readdir_populate).  In this case, pentry_parent should
 * be set to the value returned in *pentry_next.  This function should never be
 * used for managing a junction.
 *
 * @param pentry_parent [INOUT] cache entry representing the directory to be
 *                              managed.
 * @param name          [IN]    name of the entry to add.
 * @param pentry_added  [IN]    the pentry added to the dirent array
 * @param pentry_next   [OUT]   the next pentry to use for next call.
 * @param ht            [IN]    hash table used for the cache, unused in this
 *                              call.
 * @param pclient       [INOUT] resource allocated by the client for the nfs
 *                              management.
 * @param pstatus       [OUT]   returned status.
 *
 * @return the DIRECTORY that contain this entry in its array_dirent\n
 * @return NULL if failed, see *pstatus for error's meaning.
 *
 */
cache_inode_status_t cache_inode_add_cached_dirent(
    cache_entry_t * pentry_parent,
    fsal_name_t * pname,
    cache_entry_t * pentry_added,
    hash_table_t * ht,
    cache_inode_dir_entry_t **pnew_dir_entry,
    cache_inode_client_t * pclient,
    fsal_op_context_t * pcontext,
    cache_inode_status_t * pstatus)
{
  fsal_status_t fsal_status;
  cache_inode_parent_entry_t *next_parent_entry = NULL;
  cache_inode_dir_entry_t *new_dir_entry = NULL;
  struct avltree_node *tmpnode;

  *pstatus = CACHE_INODE_SUCCESS;

  /* Sanity check */
  if(pentry_parent->internal_md.type != DIRECTORY)
    {
 
      *pstatus = CACHE_INODE_BAD_TYPE;
      return *pstatus;
    }
    
  /* in cache inode avl, we always insert on pentry_parent */
  GetFromPool(new_dir_entry, &pclient->pool_dir_entry, cache_inode_dir_entry_t);

  if(new_dir_entry == NULL)
    {
      *pstatus = CACHE_INODE_MALLOC_ERROR;
      return *pstatus;
    }

  fsal_status = FSAL_namecpy(&new_dir_entry->name, pname);
  if(FSAL_IS_ERROR(fsal_status))
  {
    *pstatus = CACHE_INODE_FSAL_ERROR;
    return *pstatus;
  }

  /* still need the parent list */
  GetFromPool(next_parent_entry, &pclient->pool_parent,
              cache_inode_parent_entry_t);
  if(next_parent_entry == NULL)
    {
      *pstatus = CACHE_INODE_MALLOC_ERROR;
      return *pstatus;
    }

  /* Init the next_parent_entry variable */
  next_parent_entry->parent = NULL;
  next_parent_entry->next_parent = NULL;

  /* add to avl */
  tmpnode = avltree_insert(&new_dir_entry->node_n,
			   &pentry_parent->object.dir.dentries);
  if (tmpnode) {
  	/* collision, tree not updated--release both pool objects and return
         * err */
	ReleaseToPool(next_parent_entry, &pclient->pool_parent);
	ReleaseToPool(new_dir_entry, &pclient->pool_dir_entry);
	*pstatus = CACHE_INODE_ENTRY_EXISTS;
	return *pstatus;
  }

  *pnew_dir_entry = new_dir_entry;

  /* we're going to succeed */
  pentry_parent->object.dir.nbactive++;  
  new_dir_entry->pentry = pentry_added;

  /* link with the parent entry (insert as first entry) */
  next_parent_entry->parent = pentry_parent;
  next_parent_entry->next_parent = pentry_added->parent_list;
  pentry_added->parent_list = next_parent_entry;

  return *pstatus;
}                               /* cache_inode_add_cached_dirent */
コード例 #25
0
/**
 *
 * 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 */
コード例 #26
0
ファイル: osm.c プロジェクト: alexbirkett/GPSBabel
static void
osm_waypt_disp(const waypoint *wpt)
{
	char *buff;
	
	xasprintf(&buff, "%s\01%f\01%f", (wpt->shortname) ? wpt->shortname : "",
		wpt->latitude, wpt->longitude);

	if (avltree_insert(waypoints, buff, (const void *) wpt)) {
		int *id;
		
		id = xmalloc(sizeof(*id));
		*id = --node_id;
		((waypoint *)(wpt))->extra_data = id;
	
		gbfprintf(fout, "  <node id='%d' visible='true' lat='%0.7f' lon='%0.7f'", *id, wpt->latitude, wpt->longitude);
		if (wpt->creation_time) {
			char time_string[64];
			xml_fill_in_time(time_string, wpt->creation_time, wpt->microseconds, XML_LONG_TIME);
			gbfprintf(fout, " timestamp='%s'", time_string);
		}
		gbfprintf(fout, ">\n");

		if (wpt->hdop) {
			gbfprintf(fout, "    <tag k='gps:hdop' v='%f' />\n", wpt->hdop);
		}
		if (wpt->vdop) {
			gbfprintf(fout, "    <tag k='gps:vdop' v='%f' />\n", wpt->vdop);
		}
		if (wpt->pdop) {
			gbfprintf(fout, "    <tag k='gps:pdop' v='%f' />\n", wpt->pdop);
		}
		if (wpt->sat > 0) {
			gbfprintf(fout, "    <tag k='gps:sat' v='%d' />\n", wpt->sat);
		}

		switch (wpt->fix) {
			case fix_2d:
				gbfprintf(fout, "    <tag k='gps:fix' v='2d' />\n");
				break;
			case fix_3d:
				gbfprintf(fout, "    <tag k='gps:fix' v='3d' />\n");
				break;
			case fix_dgps:
				gbfprintf(fout, "    <tag k='gps:fix' v='dgps' />\n");
				break;
			case fix_pps:
				gbfprintf(fout, "    <tag k='gps:fix' v='pps' />\n");
				break;
			case fix_none:
				gbfprintf(fout, "    <tag k='gps:fix' v='none' />\n");
				break;
			case fix_unknown:
			default:
				break;
		}
		
		if (strlen(created_by) !=0) {
			gbfprintf(fout, "    <tag k='created_by' v='%s",created_by);
			if (gpsbabel_time != 0)
				if (strcmp("GPSBabel",created_by)==0)
					gbfprintf(fout, "-%s", gpsbabel_version);
			gbfprintf(fout, "'/>\n");
		}
		
		osm_write_tag("name", wpt->shortname);
		osm_write_tag("note", (wpt->notes) ? wpt->notes : wpt->description);
		if (wpt->icon_descr)
			osm_disp_feature(wpt);

		osm_write_opt_tag(opt_tagnd);

		gbfprintf(fout, "  </node>\n");
	}

	xfree(buff);
}