diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-11-07 03:09:03 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-11-07 03:09:03 (GMT) |
commit | eb36a96a79dd1cd6514794a18baac5f13ce633ae (patch) | |
tree | 2940bf00d7f8ee011c0de576bae7f10c5d68d36e | |
parent | db3632444bbbba2fdbe60516c89fb83ee4892c23 (diff) | |
download | hdf5-eb36a96a79dd1cd6514794a18baac5f13ce633ae.zip hdf5-eb36a96a79dd1cd6514794a18baac5f13ce633ae.tar.gz hdf5-eb36a96a79dd1cd6514794a18baac5f13ce633ae.tar.bz2 |
[svn-r12872] Description:
Implement basic framework for H5Lget_info_by_idx and get it working for
creation order indices on compact groups.
Clean up code a bit.
Close resource link in user-defined link traversal.
Tested on:
Linux/32 2.6 (chicago)
-rw-r--r-- | src/H5Glink.c | 96 | ||||
-rw-r--r-- | src/H5Gobj.c | 159 | ||||
-rw-r--r-- | src/H5Gpkg.h | 17 | ||||
-rw-r--r-- | src/H5Gprivate.h | 2 | ||||
-rw-r--r-- | src/H5Gpublic.h | 11 | ||||
-rw-r--r-- | src/H5Gtraverse.c | 28 | ||||
-rw-r--r-- | src/H5L.c | 421 | ||||
-rw-r--r-- | src/H5Lpublic.h | 15 | ||||
-rw-r--r-- | src/H5Plapl.c | 4 | ||||
-rw-r--r-- | src/H5public.h | 4 | ||||
-rw-r--r-- | test/links.c | 95 |
11 files changed, 704 insertions, 148 deletions
diff --git a/src/H5Glink.c b/src/H5Glink.c index 6611ea0..73b974e 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -88,7 +88,8 @@ typedef struct { /* PRIVATE PROTOTYPES */ static herr_t H5G_link_build_table_cb(const void *_mesg, unsigned idx, void *_udata); static herr_t H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, - const H5O_linfo_t *linfo, H5_iter_order_t order, H5G_link_table_t *ltable); + const H5O_linfo_t *linfo, H5L_index_t idx_type, H5_iter_order_t order, + H5G_link_table_t *ltable); /*------------------------------------------------------------------------- @@ -120,7 +121,7 @@ H5G_link_build_table_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) HDassert(udata->curr_lnk < udata->ltable->nlinks); /* Copy link message into table */ - if(H5O_copy(H5O_LINK_ID, lnk, &(udata->ltable->lnks[udata->curr_lnk])) == NULL) + if(NULL == H5O_copy(H5O_LINK_ID, lnk, &(udata->ltable->lnks[udata->curr_lnk]))) HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5O_ITER_ERROR, "can't copy link message") /* Increment current link entry to operate on */ @@ -147,7 +148,7 @@ done: */ static herr_t H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, - H5_iter_order_t order, H5G_link_table_t *ltable) + H5L_index_t idx_type, H5_iter_order_t order, H5G_link_table_t *ltable) { herr_t ret_value = SUCCEED; /* Return value */ @@ -178,13 +179,22 @@ H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") /* Sort link table in correct iteration order */ - /* (XXX: by name, currently) */ - if(order == H5_ITER_INC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_inc); - else if(order == H5_ITER_INC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_dec); - else - HDassert(order == H5_ITER_NATIVE); + if(idx_type == H5L_INDEX_NAME) { + if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_inc); + else if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_dec); + else + HDassert(order == H5_ITER_NATIVE); + } /* end if */ + else { + if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_corder_inc); + else if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_corder_dec); + else + HDassert(order == H5_ITER_NATIVE); + } /* end else */ } /* end if */ else ltable->lnks = NULL; @@ -439,7 +449,7 @@ H5G_link_get_name_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, HDassert(oloc); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, linfo, H5_ITER_INC, <able) < 0) + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5L_INDEX_NAME, H5_ITER_INC, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Check for going out of bounds */ @@ -494,12 +504,12 @@ H5G_link_get_type_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linf HDassert(oloc); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, linfo, H5_ITER_INC, <able) < 0) + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5L_INDEX_NAME, H5_ITER_INC, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "can't create link message table") /* Check for going out of bounds */ if(idx >= ltable.nlinks) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound") + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5G_UNKNOWN, "index out of bound") /* Determine type of object */ if(ltable.lnks[idx].type == H5L_TYPE_SOFT) @@ -664,7 +674,7 @@ H5G_link_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, HDassert(op.lib_op); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, linfo, order, <able) < 0) + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5L_INDEX_NAME, order, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Iterate over link messages */ @@ -731,7 +741,7 @@ H5G_link_lookup_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) if(HDstrcmp(lnk->name, udata->name) == 0) { if(udata->lnk) { /* Copy link information */ - if(H5O_copy(H5O_LINK_ID, lnk, udata->lnk) == NULL) + if(NULL == H5O_copy(H5O_LINK_ID, lnk, udata->lnk)) HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5O_ITER_ERROR, "can't copy link message") } /* end if */ @@ -790,3 +800,59 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_lookup() */ + +/*------------------------------------------------------------------------- + * Function: H5G_link_lookup_by_corder + * + * Purpose: Look up an object in a group using link messages, according + * the link's creation order. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 6 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_lookup_by_corder(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_iter_order_t order, hsize_t n, H5O_link_t *lnk) +{ + H5G_link_table_t ltable = {0, NULL}; /* Link table */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_lookup_by_corder, FAIL) + + /* check arguments */ + HDassert(oloc && oloc->file); + HDassert(linfo); + HDassert(lnk); + + /* Build table of all link messages, sorted according to desired order */ + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5L_INDEX_CORDER, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index out of bound") + + /* Copy link information */ +#ifdef QAK +HDfprintf(stderr, "%s: ltable.lnks[%Hu].corder = %Hd\n", FUNC, n, ltable.lnks[n].corder); +HDfprintf(stderr, "%s: ltable.lnks[%Hu].corder_valid = %t\n", FUNC, n, ltable.lnks[n].corder_valid); +#endif /* QAK */ + if(NULL == H5O_copy(H5O_LINK_ID, <able.lnks[n], lnk)) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5O_ITER_ERROR, "can't copy link message") + +done: + /* Release link table */ + if(ltable.lnks) { + /* Free link table information */ + if(H5G_obj_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_lookup_by_corder() */ + diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 0762b87..633ac5c 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -163,6 +163,76 @@ H5G_obj_cmp_name_dec(const void *lnk1, const void *lnk2) /*------------------------------------------------------------------------- + * Function: H5G_obj_cmp_corder_inc + * + * Purpose: Callback routine for comparing two link creation orders, in + * increasing order + * + * Return: An integer less than, equal to, or greater than zero if the + * first argument is considered to be respectively less than, + * equal to, or greater than the second. If two members compare + * as equal, their order in the sorted array is undefined. + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 6 2006 + * + *------------------------------------------------------------------------- + */ +int +H5G_obj_cmp_corder_inc(const void *lnk1, const void *lnk2) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_obj_cmp_corder_inc) + + if(((const H5O_link_t *)lnk1)->corder < ((const H5O_link_t *)lnk2)->corder) + ret_value = -1; + else if(((const H5O_link_t *)lnk1)->corder > ((const H5O_link_t *)lnk2)->corder) + ret_value = 1; + else + ret_value = 0; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_cmp_corder_inc() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_cmp_corder_dec + * + * Purpose: Callback routine for comparing two link creation orders, in + * decreasing order + * + * Return: An integer less than, equal to, or greater than zero if the + * second argument is considered to be respectively less than, + * equal to, or greater than the first. If two members compare + * as equal, their order in the sorted array is undefined. + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 6 2006 + * + *------------------------------------------------------------------------- + */ +int +H5G_obj_cmp_corder_dec(const void *lnk1, const void *lnk2) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_obj_cmp_corder_dec) + + if(((const H5O_link_t *)lnk1)->corder < ((const H5O_link_t *)lnk2)->corder) + ret_value = 1; + else if(((const H5O_link_t *)lnk1)->corder > ((const H5O_link_t *)lnk2)->corder) + ret_value = -1; + else + ret_value = 0; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_cmp_corder_dec() */ + + +/*------------------------------------------------------------------------- * Function: H5G_obj_release_table * * Purpose: Release table containing a list of links for a group @@ -1022,7 +1092,7 @@ done: /*------------------------------------------------------------------------- * Function: H5G_obj_lookup * - * Purpose: Look up a link in a group. + * Purpose: Look up a link in a group, using the name as the key. * * Return: Non-negative on success/Negative on failure * @@ -1072,3 +1142,90 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_obj_lookup() */ + +/*------------------------------------------------------------------------- + * Function: H5G_obj_lookup_by_idx + * + * Purpose: Look up a link in a group, according to an order within an + * index. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 6 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id) +{ + H5O_linfo_t linfo; /* Link info message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_lookup_by_idx, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + + /* Attempt to get the link info message for this group */ + if(H5O_read(grp_oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) { + /* Check for query on the name */ + if(idx_type == H5L_INDEX_NAME) { + /* Check for dense link storage */ + if(H5F_addr_defined(linfo.link_fheap_addr)) { + /* Get the object's info from the dense link storage */ + if(H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, "", lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end if */ + else { + /* Get the object's info from the link messages */ + if(H5G_link_lookup(grp_oloc, "", lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end else */ + } /* end if */ + else { + H5O_ginfo_t ginfo; /* Group info message */ + + /* Get group info message, to see if creation order is stored for links in this group */ + if(NULL == H5O_read(grp_oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info message for group") + + /* Check if creation order is tracked */ + if(!ginfo.track_corder) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group") + + /* Check for dense link storage */ + if(H5F_addr_defined(linfo.link_fheap_addr)) { +HDfprintf(stderr, "%s: creation order query on dense storage not implemented yet!\n", FUNC); +HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "creation order query on dense storage not implemented yet") + } /* end if */ + else { + /* Get the object's info from the link messages */ + if(H5G_link_lookup_by_corder(grp_oloc, dxpl_id, &linfo, order, n, lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end else */ + } /* end else */ + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5L_INDEX_NAME) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") +if(order == H5_ITER_DEC) { + HDfprintf(stderr, "%s: decreasing order query on symbol table not implemented yet!\n", FUNC); + HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "decreasing order query on symbol table not implemented yet") +} /* end if */ + + /* Get the object's info from the symbol table */ + if(H5G_stab_lookup(grp_oloc, "", lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_lookup_by_idx() */ + diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index db4d8c1..9c1928b 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -429,6 +429,9 @@ H5_DLL herr_t H5G_link_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t int *last_obj, H5G_link_iterate_t op, void *op_data); H5_DLL herr_t H5G_link_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); +H5_DLL herr_t H5G_link_lookup_by_corder(H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5_iter_order_t order, hsize_t n, + H5O_link_t *lnk); /* Functions that understand "dense" link storage */ H5_DLL herr_t H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, @@ -453,26 +456,28 @@ H5_DLL herr_t H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, /* Functions that understand objects */ H5_DLL int H5G_obj_cmp_name_inc(const void *lnk1, const void *lnk2); H5_DLL int H5G_obj_cmp_name_dec(const void *lnk1, const void *lnk2); +H5_DLL int H5G_obj_cmp_corder_inc(const void *lnk1, const void *lnk2); +H5_DLL int H5G_obj_cmp_corder_dec(const void *lnk1, const void *lnk2); H5_DLL herr_t H5G_obj_release_table(H5G_link_table_t *ltable); H5_DLL herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, const H5O_linfo_t *linfo, H5O_loc_t *oloc/*out*/); H5_DLL herr_t H5G_obj_insert(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, - H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *name, H5_iter_order_t order, int skip, int *last_obj, H5G_iterate_t op, void *op_data, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_count(struct H5O_loc_t *oloc, hsize_t *num_objs, + hid_t dxpl_id); H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, size_t size, hid_t dxpl_id); H5_DLL H5G_obj_t H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id); H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, const char *name, H5G_obj_t *obj_type, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_find(H5G_loc_t *loc, const char *name, - unsigned traverse_flags, H5O_link_t *lnk, H5O_loc_t *obj_oloc, - hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *lnk, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id); /* * These functions operate on group hierarchy names. diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 6ca2b68..23cc895 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -193,5 +193,5 @@ H5_DLL herr_t H5G_loc_find(H5G_loc_t *loc, const char *name, H5_DLL herr_t H5G_loc_reset(H5G_loc_t *loc); H5_DLL herr_t H5G_loc_free(H5G_loc_t *loc); -#endif +#endif /* _H5Gprivate_H */ diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 4f0117a..8048aee 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -92,17 +92,6 @@ typedef struct H5G_stat_t { /* Prototype for H5Giterate() operator */ typedef herr_t (*H5G_iterate_t)(hid_t group, const char *name, void *op_data); -/* - * The types of indices on links in groups. Primarily used for "<do> <foo> by - * index" routines and for iterating over links in groups. - */ -typedef enum H5G_index_t { - H5G_INDEX_UNKNOWN = -1, /* Unknown index type */ - H5G_INDEX_NAME, /* Index on names of links */ - H5G_INDEX_CORDER, /* Index on creation order of links */ - H5G_INDEX_N /* Number of indices defined on links in groups */ -} H5G_index_t; - /********************/ /* Public Variables */ /********************/ diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index c1f8440..4c92bc4 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -146,8 +146,9 @@ done: * *------------------------------------------------------------------------- */ -static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, - H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id, +static herr_t +H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, + H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t _lapl_id, hid_t dxpl_id) { const H5L_class_t *link_class; /* User-defined link class */ @@ -158,7 +159,7 @@ static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, H5O_loc_t *new_oloc=NULL; H5F_t *temp_file=NULL; H5G_t *grp; - H5P_genplist_t *lapl_default; + hid_t lapl_id = (-1); /* LAPL local to this routine */ H5P_genplist_t *lapl; /* LAPL with nlinks set */ hid_t cur_grp = (-1); herr_t ret_value = SUCCEED; /* Return value */ @@ -171,6 +172,7 @@ static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, HDassert(lnk->type >= H5L_TYPE_UD_MIN); HDassert(obj_loc); HDassert(nlinks); + HDassert(_lapl_id >= 0); /* Reset the object's path information, because we can't detect any changes * in the "path" the user-defined callback takes */ @@ -196,17 +198,22 @@ static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, /* Record number of soft links left to traverse in the property list. * If no property list exists yet, create one. */ - if(lapl_id == H5P_DEFAULT) { + if(_lapl_id == H5P_DEFAULT || _lapl_id == H5P_LINK_ACCESS_DEFAULT) { HDassert(H5P_LINK_ACCESS_DEFAULT != -1); - if(NULL == (lapl_default = H5I_object(H5P_LINK_ACCESS_DEFAULT))) + if(NULL == (lapl = H5I_object(H5P_LINK_ACCESS_DEFAULT))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get default property list") - if((lapl_id = H5P_copy_plist(lapl_default)) < 0) + if((lapl_id = H5P_copy_plist(lapl)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to copy property list") } /* end if */ + else { + /* Use the property list passed in */ + lapl_id = _lapl_id; + + if(NULL == (lapl = H5I_object(lapl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID") + } /* end else */ - if(NULL == (lapl = H5I_object(lapl_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID") if(H5P_set(lapl, H5L_ACS_NLINKS_NAME, nlinks) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set nlink info") @@ -268,6 +275,11 @@ done: if(H5I_dec_ref(cb_return) < 0) HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") + /* Close the LAPL, if we copied the default one */ + if(lapl_id > 0 && lapl_id != _lapl_id) + if(H5I_dec_ref(lapl_id) < 0) + HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close copied link access property list") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_traverse_ud() */ @@ -48,54 +48,67 @@ /* Local Typedefs */ /******************/ -/* User data for path traversal routine for getting link metadata */ +/* User data for path traversal routine for getting link info by name */ typedef struct { - H5L_info_t *linfo; /* Buffer to return to user */ - hid_t dxpl_id; /* dxpl to use in callback */ + H5L_info_t *linfo; /* Buffer to return to user */ + hid_t dxpl_id; /* dxpl to use in callback */ } H5L_trav_ud1_t; /* User data for path traversal callback to creating a link */ typedef struct { - H5F_t *file; /* Pointer to the file */ - hid_t dxpl_id; /* Dataset transfer property list */ - hid_t lcpl_id; /* Link creation property list */ - H5G_name_t *path; /* Path to object being linked */ - H5O_link_t *lnk; /* Pointer to link information to insert */ + H5F_t *file; /* Pointer to the file */ + hid_t dxpl_id; /* Dataset transfer property list */ + hid_t lcpl_id; /* Link creation property list */ + H5G_name_t *path; /* Path to object being linked */ + H5O_link_t *lnk; /* Pointer to link information to insert */ } H5L_trav_ud2_t; /* User data for path traversal routine for moving and renaming a link */ typedef struct { - const char *dst_name; /* Destination name for moving object */ - H5T_cset_t cset; /* Char set for new name */ - H5G_loc_t *dst_loc; /* Destination location for moving object */ - hbool_t copy; /* TRUE if this is a copy operation */ - hid_t lapl_id; /* lapl to use in callback */ - hid_t dxpl_id; /* dxpl to use in callback */ + const char *dst_name; /* Destination name for moving object */ + H5T_cset_t cset; /* Char set for new name */ + H5G_loc_t *dst_loc; /* Destination location for moving object */ + hbool_t copy; /* TRUE if this is a copy operation */ + hid_t lapl_id; /* lapl to use in callback */ + hid_t dxpl_id; /* dxpl to use in callback */ } H5L_trav_ud3_t; /* User data for path traversal routine for getting soft link value */ typedef struct { - size_t size; /* Size of user buffer */ - void *buf; /* User buffer */ + size_t size; /* Size of user buffer */ + void *buf; /* User buffer */ } H5L_trav_ud4_t; /* User data for path traversal routine for removing link (i.e. unlink) */ typedef struct { - hid_t dxpl_id; /* Dataset transfer property list */ + hid_t dxpl_id; /* Dataset transfer property list */ } H5L_trav_ud5_t; /* User data for path traversal routine for moving and renaming an object */ typedef struct { - H5F_t *file; /* Pointer to the file */ - H5O_link_t *lnk; /* Pointer to link information to insert */ - hbool_t copy; /* TRUE if this is a copy operation */ - hid_t dxpl_id; /* Dataset transfer property list */ + H5F_t *file; /* Pointer to the file */ + H5O_link_t *lnk; /* Pointer to link information to insert */ + hbool_t copy; /* TRUE if this is a copy operation */ + hid_t dxpl_id; /* Dataset transfer property list */ } H5L_trav_ud6_t; +/* User data for path traversal routine for getting link info by index */ +typedef struct { + /* In */ + H5L_index_t idx_type; /* Index to use */ + H5_iter_order_t order; /* Order to iterate in index */ + hsize_t n; /* Offset of link within index */ + hid_t dxpl_id; /* dxpl to use in callback */ + + /* Out */ + H5L_info_t *linfo; /* Buffer to return to user */ +} H5L_trav_ud7_t; + /********************/ /* Local Prototypes */ /********************/ +static int H5L_find_class_idx(H5L_type_t id); static herr_t H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); @@ -117,7 +130,12 @@ static herr_t H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, static herr_t H5L_get_info_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk, H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static int H5L_find_class_idx(H5L_type_t id); +static herr_t H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, + const H5O_link_t *lnk, H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/, + H5G_own_loc_t *own_loc/*out*/); +static herr_t H5L_get_info_by_idx(const H5G_loc_t *loc, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5L_info_t *linkbuf/*out*/, hid_t lapl_id, hid_t dxpl_id); /*********************/ /* Package Variables */ @@ -669,6 +687,11 @@ H5Lget_info(hid_t loc_id, const char *name, H5L_info_t *linkbuf /*out*/, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") /* Get the creation time */ if(H5L_get_info(&loc, name, linkbuf, lapl_id, H5AC_ind_dxpl_id) < 0) @@ -680,6 +703,54 @@ done: /*------------------------------------------------------------------------- + * Function: H5Lget_info_by_idx + * + * Purpose: Gets metadata for a link, according to the order within an + * index. + * + * Return: Success: Non-negative with information in LINKBUF + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lget_info_by_idx(hid_t loc_id, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5L_info_t *linkbuf /*out*/, hid_t lapl_id) +{ + H5G_loc_t loc; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(H5Lget_info_by_idx, FAIL) + + /* Check arguments */ + if(H5G_loc(loc_id, &loc)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!group_name || !*group_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(idx_type <= H5L_INDEX_UNKNOWN || idx_type >= H5L_INDEX_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified") + if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* Get the creation time */ + if(H5L_get_info_by_idx(&loc, group_name, idx_type, order, n, linkbuf, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_info_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5Lregister * * Purpose: Registers a class of user-defined links, or changes the @@ -716,9 +787,9 @@ H5Lregister(const H5L_class_t *cls) if(cls->version != H5L_LINK_CLASS_T_VERS) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5L_class_t version number") - if (cls->id < H5L_TYPE_UD_MIN || cls->id > H5L_TYPE_MAX) + if(cls->id < H5L_TYPE_UD_MIN || cls->id > H5L_TYPE_MAX) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link identification number") - if (cls->trav_func == NULL) + if(cls->trav_func == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no traversal function specified") /* Do it */ @@ -748,7 +819,7 @@ done: herr_t H5Lunregister(H5L_type_t id) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Lunregister, FAIL) H5TRACE1("e","Ll",id); @@ -785,18 +856,18 @@ htri_t H5Lis_registered(H5L_type_t id) { size_t i; /* Local index variable */ - htri_t ret_value=FALSE; /* Return value */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_API(H5Lis_registered, FAIL) /* Check args */ - if(id<0 || id>H5L_TYPE_MAX) + if(id < 0 || id > H5L_TYPE_MAX) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link type id number") /* Is the link class already registered? */ - for(i=0; i<H5L_table_used_g; i++) - if(H5L_table_g[i].id==id) { - ret_value=TRUE; + for(i = 0; i < H5L_table_used_g; i++) + if(H5L_table_g[i].id == id) { + ret_value = TRUE; break; } /* end if */ @@ -832,12 +903,12 @@ static int H5L_find_class_idx(H5L_type_t id) { size_t i; /* Local index variable */ - int ret_value=FAIL; /* Return value */ + int ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_find_class_idx) - for (i=0; i<H5L_table_used_g; i++) - if (H5L_table_g[i].id == id) + for(i = 0; i < H5L_table_used_g; i++) + if(H5L_table_g[i].id == id) HGOTO_DONE((int)i) done: @@ -863,16 +934,16 @@ const H5L_class_t * H5L_find_class(H5L_type_t id) { int idx; /* Filter index in global table */ - H5L_class_t *ret_value=NULL; /* Return value */ + H5L_class_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(H5L_find_class, NULL) /* Get the index in the global table */ - if((idx=H5L_find_class_idx(id))<0) + if((idx = H5L_find_class_idx(id)) < 0) HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, NULL, "unable to find link class") /* Set return value */ - ret_value=H5L_table_g+idx; + ret_value = H5L_table_g+idx; done: FUNC_LEAVE_NOAPI(ret_value) @@ -951,25 +1022,25 @@ done: herr_t H5L_unregister(H5L_type_t id) { - size_t i; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5L_unregister,FAIL) + FUNC_ENTER_NOAPI(H5L_unregister, FAIL) - assert (id>=0 && id<=H5L_TYPE_MAX); + HDassert(id >= 0 && id <= H5L_TYPE_MAX); /* Is the filter already registered? */ - for (i=0; i<H5L_table_used_g; i++) - if (H5L_table_g[i].id==id) + for(i = 0; i < H5L_table_used_g; i++) + if(H5L_table_g[i].id == id) break; /* Fail if filter not found */ - if (i>=H5L_table_used_g) + if(i >= H5L_table_used_g) HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "link class is not registered") /* Remove filter from table */ /* Don't worry about shrinking table size (for now) */ - HDmemmove(&H5L_table_g[i],&H5L_table_g[i+1],sizeof(H5L_class_t)*((H5L_table_used_g-1)-i)); + HDmemmove(&H5L_table_g[i], &H5L_table_g[i + 1], sizeof(H5L_class_t) * ((H5L_table_used_g - 1) - i)); H5L_table_used_g--; done: @@ -1014,7 +1085,7 @@ H5L_link(H5G_loc_t *new_loc, const char *new_name, H5G_loc_t *obj_loc, lnk.u.hard.addr = obj_loc->oloc->addr; /* Create the link */ - if( H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, lcpl_id, lapl_id, dxpl_id) <0) + if(H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, lcpl_id, lapl_id, dxpl_id) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object") done: @@ -1113,12 +1184,12 @@ done: /* Close the location given to the user callback if it was created */ if(grp_id >= 0) { - if(H5I_dec_ref(grp_id) <0) + if(H5I_dec_ref(grp_id) < 0) HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") } else if(grp != NULL) { - if(H5G_close(grp) <0) + if(H5G_close(grp) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close group given to UD callback") } else if(temp_loc_init) @@ -1288,16 +1359,14 @@ H5L_create_hard(H5G_loc_t *cur_loc, const char *cur_name, /* Create actual link to the object. Pass in NULL for the path, since this * function shouldn't change an object's user path. */ - if(H5L_create_real(link_loc, link_name, NULL, link_file, &lnk, lcpl_id, - lapl_id, dxpl_id) < 0) + if(H5L_create_real(link_loc, link_name, NULL, link_file, &lnk, lcpl_id, lapl_id, dxpl_id) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object") done: /* Free the object header location */ - if(loc_valid) { + if(loc_valid) if(H5G_loc_free(&obj_loc) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free location") - } /* Free the normalized path name */ if(norm_cur_name) @@ -1343,8 +1412,7 @@ H5L_create_soft(const char *target_path, H5G_loc_t *link_loc, lnk.u.soft.name = norm_target; /* Create actual link to the object */ - if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, lcpl_id, - lapl_id, dxpl_id) < 0) + if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, lcpl_id, lapl_id, dxpl_id) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object") done: @@ -1405,8 +1473,7 @@ H5L_create_ud(H5G_loc_t *link_loc, const char *link_name, const void * ud_data, lnk.type = type; /* Create actual link to the object */ - if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, lcpl_id, - lapl_id, dxpl_id) < 0) + if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, lcpl_id, lapl_id, dxpl_id) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to register new name for object") done: @@ -1736,25 +1803,25 @@ H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name, { if((link_class->copy_func)(udata->lnk->name, grp_id, udata->lnk->u.ud.udata, udata->lnk->u.ud.size) < 0) HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "UD copy callback returned error") - } + } /* end if */ else { if((link_class->move_func)(udata->lnk->name, grp_id, udata->lnk->u.ud.udata, udata->lnk->u.ud.size) < 0) HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "UD move callback returned error") - } - } - } + } /* end else */ + } /* end if */ + } /* end if */ done: /* Close the location given to the user callback if it was created */ if(grp_id >= 0) { - if(H5I_dec_ref(grp_id) <0) + if(H5I_dec_ref(grp_id) < 0) HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") } else if(grp != NULL) { - if(H5G_close(grp) <0) + if(H5G_close(grp) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close group given to UD callback") } else if(temp_loc_init) @@ -1809,7 +1876,7 @@ H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, /* Get object type */ switch(lnk->type) { case H5L_TYPE_HARD: - if(H5G_UNKNOWN == (type = H5O_obj_type(obj_loc->oloc, udata->dxpl_id))) + if(H5G_UNKNOWN == (type = H5O_obj_type(obj_loc->oloc, udata->dxpl_id))) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object type to move") break; @@ -1826,6 +1893,7 @@ H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, /* Set up user data for move_dest_cb */ if((udata_out.lnk = H5O_copy(H5O_LINK_ID, lnk, NULL)) == NULL) HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy link to be moved") + /* In this special case, the link's name is going to be replaced at its * destination, so we should free it here. */ @@ -1857,10 +1925,10 @@ H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk, if(H5G_obj_remove(grp_loc->oloc, orig_name, &type, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to remove old name") H5RS_decr(dst_name_r); - } + } /* end if */ done: - /* Cleanup */ + /* Cleanup */ if(orig_name) H5MM_xfree(orig_name); @@ -1875,7 +1943,7 @@ done: else if(udata_out.lnk->type >= H5L_TYPE_UD_MIN && udata_out.lnk->u.ud.size > 0) udata_out.lnk->u.ud.udata = H5MM_xfree(udata_out.lnk->u.ud.udata); H5MM_xfree(udata_out.lnk); - } + } /* end if */ /* Indicate that this callback didn't take ownership of the group * * location for the object */ @@ -1988,14 +2056,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5L_get_info_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk, - H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/) +H5L_get_info_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, + const H5O_link_t *lnk, H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/, + H5G_own_loc_t *own_loc/*out*/) { H5L_trav_ud1_t *udata = (H5L_trav_ud1_t *)_udata; /* User data passed in */ H5L_info_t *linfo = udata->linfo; - const H5L_class_t *link_class; /* User-defined link class */ - ssize_t cb_ret; /* Return value from UD callback */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5L_get_info_cb) @@ -2013,34 +2080,39 @@ H5L_get_info_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const switch(lnk->type) { - case H5L_TYPE_HARD: - linfo->u.address = lnk->u.hard.addr; - break; - - case H5L_TYPE_SOFT: - linfo->u.link_size = HDstrlen(lnk->u.soft.name) + 1; /*count the null terminator*/ - break; - - default: - if(lnk->type < H5L_TYPE_UD_MIN || lnk->type > H5L_TYPE_MAX) - HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "unknown link class") - - /* User-defined link; call its query function to get the link udata size. */ - /* Get the link class for this type of link. It's okay if the class - * isn't registered, though--we just can't give any more information - * about it - */ - link_class = H5L_find_class(lnk->type); - - if(link_class != NULL && link_class->query_func != NULL) { - if((cb_ret = (link_class->query_func)(lnk->name, lnk->u.ud.udata, lnk->u.ud.size, NULL, (size_t)0)) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "query buffer size callback returned failure") - - linfo->u.link_size = cb_ret; - } - else { - linfo->u.link_size = 0; - } + case H5L_TYPE_HARD: + linfo->u.address = lnk->u.hard.addr; + break; + + case H5L_TYPE_SOFT: + linfo->u.link_size = HDstrlen(lnk->u.soft.name) + 1; /*count the null terminator*/ + break; + + default: + { + const H5L_class_t *link_class; /* User-defined link class */ + + if(lnk->type < H5L_TYPE_UD_MIN || lnk->type > H5L_TYPE_MAX) + HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "unknown link class") + + /* User-defined link; call its query function to get the link udata size. */ + /* Get the link class for this type of link. It's okay if the class + * isn't registered, though--we just can't give any more information + * about it + */ + link_class = H5L_find_class(lnk->type); + + if(link_class != NULL && link_class->query_func != NULL) { + ssize_t cb_ret; /* Return value from UD callback */ + + if((cb_ret = (link_class->query_func)(lnk->name, lnk->u.ud.udata, lnk->u.ud.size, NULL, (size_t)0)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "query buffer size callback returned failure") + + linfo->u.link_size = cb_ret; + } /* end if */ + else + linfo->u.link_size = 0; + } /* end case */ } /* end switch */ } /* end if */ @@ -2066,12 +2138,13 @@ done: *------------------------------------------------------------------------- */ herr_t -H5L_get_info(const H5G_loc_t *loc, const char *name, H5L_info_t *linkbuf/*out*/, hid_t lapl_id, hid_t dxpl_id) +H5L_get_info(const H5G_loc_t *loc, const char *name, + H5L_info_t *linkbuf/*out*/, hid_t lapl_id, hid_t dxpl_id) { - H5L_trav_ud1_t udata; - herr_t ret_value = SUCCEED; /* Return value */ + H5L_trav_ud1_t udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5L_get_info) + FUNC_ENTER_NOAPI(H5L_get_info, FAIL) udata.linfo = linkbuf; udata.dxpl_id = dxpl_id; @@ -2086,6 +2159,148 @@ done: /*------------------------------------------------------------------------- + * Function: H5L_get_info_by_idx_cb + * + * Purpose: Callback for retrieving a link's metadata according to an + * index's order. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 6 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, + const H5O_link_t UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, + H5G_own_loc_t *own_loc/*out*/) +{ + H5L_trav_ud7_t *udata = (H5L_trav_ud7_t *)_udata; /* User data passed in */ + H5O_link_t grp_lnk; /* Link within group */ + H5L_info_t *linfo = udata->linfo; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5L_get_info_by_idx_cb) + +#ifdef QAK +HDfprintf(stderr, "%s: grp_loc = %p\n", FUNC, grp_loc); +HDfprintf(stderr, "%s: name = %p\n", FUNC, name); +if(name) + HDfprintf(stderr, "%s: name = '%s'\n", FUNC, name); +HDfprintf(stderr, "%s: lnk = %p\n", FUNC, lnk); +if(lnk && lnk->name) + HDfprintf(stderr, "%s: lnk->name = '%s'\n", FUNC, lnk->name); +HDfprintf(stderr, "%s: obj_loc = %p\n", FUNC, obj_loc); +if(obj_loc) { + HDfprintf(stderr, "%s: obj_loc->oloc = %p\n", FUNC, obj_loc->oloc); + if(obj_loc->oloc) + HDfprintf(stderr, "%s: obj_loc->oloc->addr = %a\n", FUNC, obj_loc->oloc->addr); +} /* end if */ +#endif /* QAK */ + + /* Check if the name of the group resolved to a valid object */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist") + + /* Query link */ + if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order, + udata->n, &grp_lnk, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") + + /* Get information from the link */ + if(linfo) { + linfo->cset = grp_lnk.cset; + linfo->corder = grp_lnk.corder; + linfo->corder_valid = grp_lnk.corder_valid; + linfo->type = grp_lnk.type; + + switch(grp_lnk.type) { + case H5L_TYPE_HARD: + linfo->u.address = grp_lnk.u.hard.addr; + break; + + case H5L_TYPE_SOFT: + linfo->u.link_size = HDstrlen(grp_lnk.u.soft.name) + 1; /*count the null terminator*/ + break; + + default: + { + const H5L_class_t *link_class; /* User-defined link class */ + + if(grp_lnk.type < H5L_TYPE_UD_MIN || grp_lnk.type > H5L_TYPE_MAX) + HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "unknown link class") + + /* User-defined link; call its query function to get the link udata size. */ + /* Get the link class for this type of link. It's okay if the class + * isn't registered, though--we just can't give any more information + * about it + */ + link_class = H5L_find_class(grp_lnk.type); + + if(link_class != NULL && link_class->query_func != NULL) { + ssize_t cb_ret; /* Return value from UD callback */ + + if((cb_ret = (link_class->query_func)(grp_lnk.name, grp_lnk.u.ud.udata, grp_lnk.u.ud.size, NULL, (size_t)0)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "query buffer size callback returned failure") + + linfo->u.link_size = cb_ret; + } /* end if */ + else + linfo->u.link_size = 0; + } /* end case */ + } /* end switch */ + } /* end if */ + +done: + /* Indicate that this callback didn't take ownership of the group * + * location for the object */ + *own_loc = H5G_OWN_NONE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5L_get_info_by_idx_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5L_get_info_by_idx + * + * Purpose: Returns metadata about a link, according to an order within + * an index. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 6 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5L_get_info_by_idx(const H5G_loc_t *loc, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5L_info_t *linkbuf/*out*/, hid_t lapl_id, hid_t dxpl_id) +{ + H5L_trav_ud7_t udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5L_get_info_by_idx) + + /* Set up user data for callback */ + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.dxpl_id = dxpl_id; + udata.linfo = linkbuf; + + /* Traverse the group hierarchy to locate the object to get info about */ + if(H5G_traverse(loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_info_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5L_get_info_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5L_get_default_lcpl * * Purpose: Accessor for the default Link Creation Property List @@ -2102,7 +2317,7 @@ done: hid_t H5L_get_default_lcpl(void) { - hid_t ret_value = FAIL; /* Return value */ + hid_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5L_get_default_lcpl, FAIL) diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index e944965..eb24375 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -120,6 +120,18 @@ typedef struct { H5L_query_func_t query_func; /* Callback for queries */ } H5L_class_t; +/* + * The types of indices on links in groups. Primarily used for "<do> <foo> by + * index" routines and for iterating over links in groups. + */ +typedef enum H5L_index_t { + H5L_INDEX_UNKNOWN = -1, /* Unknown index type */ + H5L_INDEX_NAME, /* Index on names of links */ + H5L_INDEX_CORDER, /* Index on creation order of links */ + H5L_INDEX_N /* Number of indices defined on links in groups */ +} H5L_index_t; + + /********************/ /* Public Variables */ /********************/ @@ -144,6 +156,9 @@ H5_DLL herr_t H5Lget_val(hid_t loc_id, const char *name, size_t size, void *buf/*out*/, hid_t lapl_id); H5_DLL herr_t H5Lget_info(hid_t loc_id, const char *name, H5L_info_t *linkbuf /*out*/, hid_t lapl_id); +H5_DLL herr_t H5Lget_info_by_idx(hid_t loc_id, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5L_info_t *linkbuf /*out*/, hid_t lapl_id); /* UD link functions */ H5_DLL herr_t H5Lcreate_ud(hid_t link_loc_id, const char *link_name, diff --git a/src/H5Plapl.c b/src/H5Plapl.c index eb3fb1c..e05e4b0 100644 --- a/src/H5Plapl.c +++ b/src/H5Plapl.c @@ -119,14 +119,14 @@ const H5P_libclass_t H5P_CLS_LACC[1] = {{ * October 31, 2006 *------------------------------------------------------------------------- */ -herr_t +static herr_t H5P_lacc_reg_prop(H5P_genclass_t *pclass) { size_t nlinks = H5L_ACS_NLINKS_DEF; /* Default number of soft links to traverse */ char *elink_prefix = H5L_ACS_ELINK_PREFIX_DEF; /* Default external link prefix string */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5P_lacc_reg_prop, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5P_lacc_reg_prop) /* Register property for number of links traversed */ if(H5P_register(pclass, H5L_ACS_NLINKS_NAME, H5L_ACS_NLINKS_SIZE, diff --git a/src/H5public.h b/src/H5public.h index e7f4d32..114944a 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -229,9 +229,11 @@ typedef ssize_t hssize_t; /* Common iteration orders */ typedef enum { + H5_ITER_UNKNOWN, /* Unknown order */ H5_ITER_INC, /* Increasing order */ H5_ITER_DEC, /* Decreasing order */ - H5_ITER_NATIVE /* No particular order, whatever is fastest */ + H5_ITER_NATIVE, /* No particular order, whatever is fastest */ + H5_ITER_N /* Number of iteration orders */ } H5_iter_order_t; /* Functions in H5.c */ diff --git a/test/links.c b/test/links.c index 4785ac01..64ef6c0 100644 --- a/test/links.c +++ b/test/links.c @@ -5902,6 +5902,99 @@ error: /*------------------------------------------------------------------------- + * Function: corder_info_by_idx + * + * Purpose: Create a group with creation order indices and test querying + * info by index. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static int +corder_info_by_idx(hid_t fapl) +{ + hid_t file_id = (-1); /* File ID */ + hid_t group_id = (-1), group_id2 = (-1); /* Group IDs */ + hid_t gcpl_id = (-1); /* Group creation property list ID */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + H5L_info_t linfo; /* Link info struct */ + char objname[NAME_BUF_SIZE]; /* Object name */ + char filename[NAME_BUF_SIZE];/* File name */ + unsigned u; /* Local index variable */ + + TESTING("querying info by index") + + /* Create file */ + /* (with creation order tracking for the root group) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create group creation property list */ + if((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0) TEST_ERROR + + /* Set creation order tracking & indexing on group */ + if(H5Pset_creation_order_index(gcpl_id, TRUE) < 0) TEST_ERROR + if(H5Pset_creation_order_tracking(gcpl_id, TRUE) < 0) TEST_ERROR + + /* Create group with creation order indexing & tracking on */ + if((group_id = H5Gcreate_expand(file_id, gcpl_id, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Llink(file_id, CORDER_GROUP_NAME, group_id, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Query the group creation properties */ + if(H5Pget_link_phase_change(gcpl_id, &max_compact, &min_dense) < 0) TEST_ERROR + + /* Create several links, up to limit of compact form */ + for(u = 0; u < max_compact; u++) { + sprintf(objname, "filler %u", u); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + + /* Get the link information for new object */ + if(H5Lget_info_by_idx(group_id, ".", H5L_INDEX_CORDER, H5_ITER_INC, (hsize_t)u, &linfo, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify the link information for new object */ +#ifdef QAK +HDfprintf(stderr, "linfo.corder_valid = %t\n", linfo.corder_valid); +HDfprintf(stderr, "linfo.corder = %Hd\n", linfo.corder); +HDfprintf(stderr, "u = %u\n", u); +#endif /* QAK */ + if(linfo.corder != u) TEST_ERROR + } /* end for */ + + /* Create another link, to push group into dense form */ + sprintf(objname, "filler %u", max_compact); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) TEST_ERROR + + /* Close the group creation property list */ + if(H5Pclose(gcpl_id) < 0) TEST_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(gcpl_id); + H5Gclose(group_id); + H5Fclose(file_id); + } H5E_END_TRY; + return -1; +} /* end corder_create_dense() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test links @@ -6004,6 +6097,7 @@ main(void) nerrors += corder_create_dense(fapl2) < 0 ? 1 : 0; nerrors += corder_transition(fapl2) < 0 ? 1 : 0; nerrors += corder_delete(fapl2) < 0 ? 1 : 0; + nerrors += corder_info_by_idx(fapl2) < 0 ? 1 : 0; } /* end if */ } /* end for */ #else /* QAK */ @@ -6016,6 +6110,7 @@ main(void) nerrors += corder_create_dense(fapl2) < 0 ? 1 : 0; nerrors += corder_transition(fapl2) < 0 ? 1 : 0; nerrors += corder_delete(fapl2) < 0 ? 1 : 0; + nerrors += corder_info_by_idx(fapl2) < 0 ? 1 : 0; #endif /* QAK */ /* Close 2nd FAPL */ |