/** * @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; }
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; }
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; } }
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; }
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); }
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)); }
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)); }
/* * 将结点插入到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; }
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]); } }
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]); }
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); }
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; }
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); }
/** * * 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; }
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); } }
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); }
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; }
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, ¤t_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; }
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); } }
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); }
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, ¬defines, 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);
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; }
/** * * 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 */
/** * * 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 */
/** * * 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 */
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); }