From f6deaca1d4cca061273cd6daef0357200d4c6ea4 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 20 Nov 2006 20:18:55 -0500 Subject: [svn-r12954] Description: Initial refactoring to prepare for H5Oopen_by_idx() API support. Tested on: Linux/32 2.4 (chicago) Linux/64 2.4 (chicago2) --- src/H5Glink.c | 48 +++++++++++++++ src/H5Gloc.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++----- src/H5Gpkg.h | 4 +- src/H5Gprivate.h | 3 + src/H5Gtraverse.c | 171 +++++++++++++++++++++++++++++++----------------------- src/H5L.c | 16 ++--- src/H5O.c | 87 +++++++++++++++++++++++++-- src/H5Opublic.h | 27 ++++++++- 8 files changed, 418 insertions(+), 104 deletions(-) diff --git a/src/H5Glink.c b/src/H5Glink.c index b0966d7..e984a91 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -415,6 +415,54 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_link_to_loc + * + * Purpose: Build group location from group and link object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 20 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, + H5G_loc_t *obj_loc) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_to_loc, FAIL) + + /* Sanity check */ + HDassert(grp_loc); + HDassert(lnk); + HDassert(obj_loc); + + /* + * Build location from the link + */ + + /* Check for unknown library-internal link */ + if(lnk->type > H5L_TYPE_BUILTIN_MAX && lnk->type < H5L_TYPE_UD_MIN) + HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "unknown link type") + + /* Build object's group hier. location */ + if(H5G_name_set(grp_loc->path, obj_loc->path, lnk->name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name") + + /* Set the object location, if it's a hard link set the address also */ + obj_loc->oloc->file = grp_loc->oloc->file; + obj_loc->oloc->holding_file = FALSE; + if(lnk->type == H5L_TYPE_HARD) + obj_loc->oloc->addr = lnk->u.hard.addr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_to_loc() */ + + +/*------------------------------------------------------------------------- * Function: H5G_link_copy_file * * Purpose: Copy a link and the object it points to from one file to diff --git a/src/H5Gloc.c b/src/H5Gloc.c index 3a94a79..ca488cf 100644 --- a/src/H5Gloc.c +++ b/src/H5Gloc.c @@ -22,10 +22,17 @@ * *------------------------------------------------------------------------- */ + +/****************/ +/* Module Setup */ +/****************/ + #define H5G_PACKAGE /*suppress error about including H5Gpkg */ -/* Packages needed by this file... */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5Aprivate.h" /* Attributes */ #include "H5Dprivate.h" /* Datasets */ @@ -33,21 +40,61 @@ #include "H5Gpkg.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ -/* Private typedefs */ +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ /* User data for looking up an object in a group */ typedef struct { + /* upward */ H5G_loc_t *loc; /* Group location to set */ -} H5G_loc_ud1_t; +} H5G_loc_fnd_t; -/* Private macros */ +/* User data for looking up an object in a group by index */ +typedef struct { + /* downward */ + hid_t dxpl_id; /* DXPL to use for operation */ + H5L_index_t idx_type; /* Index to use */ + H5_iter_order_t order; /* Iteration order within index */ + hsize_t n; /* Offset within index */ + + /* upward */ + H5G_loc_t *loc; /* Group location to set */ +} H5G_loc_fbi_t; -/* Local variables */ -/* PRIVATE PROTOTYPES */ +/********************/ +/* Local Prototypes */ +/********************/ + +/* Group traversal callbacks */ static herr_t H5G_loc_find_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc/*out*/); +static herr_t H5G_loc_find_by_idx_cb(H5G_loc_t *grp_loc, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata, + H5G_own_loc_t *own_loc/*out*/); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + /*------------------------------------------------------------------------- @@ -184,7 +231,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5_copy_depth_t depth) +H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth) { herr_t ret_value = SUCCEED; /* Return value */ @@ -261,10 +308,6 @@ H5G_loc_free(H5G_loc_t *loc) HDassert(loc); /* Reset components of the location */ -#ifdef NOT_YET - if(H5G_ent_free(loc->ent) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to free entry") -#endif /* NOT_YET */ if(H5G_name_free(loc->path) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free path") if(H5O_loc_free(loc->oloc) < 0) @@ -291,8 +334,8 @@ static herr_t H5G_loc_find_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*/) { - H5G_loc_ud1_t *udata = (H5G_loc_ud1_t *)_udata; /* User data passed in */ - herr_t ret_value = SUCCEED; /* Return value */ + H5G_loc_fnd_t *udata = (H5G_loc_fnd_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_loc_find_cb) @@ -328,8 +371,8 @@ herr_t H5G_loc_find(H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, hid_t dxpl_id) { - H5G_loc_ud1_t udata; /* User data for traversal callback */ - herr_t ret_value = SUCCEED; /* Return value */ + H5G_loc_fnd_t udata; /* User data for traversal callback */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_loc_find, FAIL) @@ -351,6 +394,99 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_loc_find_by_idx_cb + * + * Purpose: Callback for retrieving object location for an object in a group + * according to the order within an index + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 20, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_loc_find_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*/) +{ + H5G_loc_fbi_t *udata = (H5G_loc_fbi_t *)_udata; /* User data passed in */ + H5O_link_t fnd_lnk; /* Link within group */ + hbool_t lnk_copied = FALSE; /* Whether the link was copied */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_loc_find_by_idx_cb) + + /* Check if the name in this group resolved to a valid link */ + 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, &fnd_lnk, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") + lnk_copied = TRUE; + + /* Build the object location for the link */ + +done: + /* Reset the link information, if we have a copy */ + if(lnk_copied) + H5O_reset(H5O_LINK_ID, &fnd_lnk); + + /* 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 H5G_loc_find_by_idx_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_find_by_idx + * + * Purpose: Find a symbol from a location, according to the order in an index + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, November 20, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_find_by_idx(H5G_loc_t *loc, const char *group_name, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n, H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, + hid_t dxpl_id) +{ + H5G_loc_fbi_t udata; /* User data for traversal callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_find_by_idx, FAIL) + + /* Check args. */ + HDassert(loc); + HDassert(group_name && *group_name); + HDassert(obj_loc); + + /* Set up user data for locating object */ + udata.dxpl_id = dxpl_id; + udata.idx_type = idx_type; + udata.order = order; + udata.n = n; + udata.loc = obj_loc; + + /* Traverse group hierarchy to locate object */ + if(H5G_traverse(loc, group_name, H5G_TARGET_NORMAL, H5G_loc_find_by_idx_cb, &udata, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_find_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5G_loc_insert * * Purpose: Insert an object at a location diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index b240fb0..411a8e7 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -434,6 +434,8 @@ H5_DLL herr_t H5G_ent_to_link(H5F_t *f, hid_t dxpl_id, H5O_link_t *lnk, H5_DLL herr_t H5G_ent_to_info(H5F_t *f, hid_t dxpl_id, H5L_info_t *info, haddr_t lheap_addr, const H5G_entry_t *ent); H5_DLL herr_t H5G_link_to_info(const H5O_link_t *lnk, H5L_info_t *linfo); +H5_DLL herr_t H5G_link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, + H5G_loc_t *obj_loc); H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk, const H5O_loc_t *src_oloc, H5O_link_t *dst_lnk, H5O_copy_t *cpy_info); @@ -529,7 +531,7 @@ H5_DLL H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char /* * These functions operate on group "locations" */ -H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5_copy_depth_t depth); +H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth); H5_DLL herr_t H5G_loc_insert(H5G_loc_t *grp_loc, const char *name, H5G_loc_t *obj_loc, hid_t dxpl_id); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 69a448a..786b6a6 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -193,6 +193,9 @@ H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t dxpl_id, H5_DLL herr_t H5G_loc(hid_t loc_id, H5G_loc_t *loc); H5_DLL herr_t H5G_loc_find(H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, hid_t dxpl_id); +H5_DLL herr_t H5G_loc_find_by_idx(H5G_loc_t *loc, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, + H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, hid_t dxpl_id); H5_DLL herr_t H5G_loc_reset(H5G_loc_t *loc); H5_DLL herr_t H5G_loc_free(H5G_loc_t *loc); diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 4c92bc4..3cb66cc 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -52,13 +52,13 @@ static char *H5G_comp_g = NULL; /*component buffer */ static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */ /* PRIVATE PROTOTYPES */ -static herr_t H5G_traverse_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, +static herr_t H5G_traverse_link_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, +static herr_t H5G_traverse_ud(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id, hid_t dxpl_id); -static herr_t H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, +static herr_t H5G_traverse_slink(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id, hid_t dxpl_id); static herr_t H5G_traverse_mount(H5G_loc_t *loc/*in,out*/); @@ -147,7 +147,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, +H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk, H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t _lapl_id, hid_t dxpl_id) { @@ -291,9 +291,7 @@ done: * whose entry is GRP_LOC and the link tail entry is OBJ_LOC. * * Return: Success: Non-negative, OBJ_LOC will contain information - * about the object to which the link points and - * GRP_LOC will contain the information about - * the group in which the link tail appears. + * about the object to which the link points * * Failure: Negative * @@ -303,7 +301,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, +H5G_traverse_slink(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id, hid_t dxpl_id) { @@ -435,6 +433,90 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_traverse_special + * + * Purpose: Handle traversing special link situations + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 20 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_traverse_special(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, + unsigned target, size_t *nlinks, hbool_t last_comp, + H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_special) + + /* Sanity check */ + HDassert(grp_loc); + HDassert(lnk); + HDassert(obj_loc); + HDassert(nlinks); + + /* + * If we found a symbolic link then we should follow it. But if this + * is the last component of the name and the H5G_TARGET_SLINK bit of + * TARGET is set then we don't follow it. + */ + if(H5L_TYPE_SOFT == lnk->type && + (0 == (target & H5G_TARGET_SLINK) || !last_comp)) { + if((*nlinks)-- <= 0) + HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links") + if(H5G_traverse_slink(grp_loc, lnk, obj_loc, nlinks, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "symbolic link traversal failed") + } /* end if */ + + /* + * If we found a user-defined link then we should follow it. But if this + * is the last component of the name and the H5G_TARGET_UDLINK bit of + * TARGET is set then we don't follow it. + */ + if(lnk->type >= H5L_TYPE_UD_MIN && + (0 == (target & H5G_TARGET_UDLINK) || !last_comp) ) { + if((*nlinks)-- <= 0) + HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links") + if(H5G_traverse_ud(grp_loc, lnk, obj_loc, nlinks, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "user-defined link traversal failed") + } /* end if */ + + /* + * Resolve mount points to the mounted group. Do not do this step if + * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last + * component of the name. + * + * (If this link is a hard link, try to perform mount point traversal) + * + * (Note that the soft and external link traversal above can change + * the status of the object (into a hard link), so don't use an 'else' + * statement here. -QAK) + */ + if(H5F_addr_defined(obj_loc->oloc->addr) && + (0 == (target & H5G_TARGET_MOUNT) || !last_comp)) { + if(H5G_traverse_mount(obj_loc/*in,out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "mount point traversal failed") + } /* end if */ + + /* If the grp_loc is the only thing holding an external file open + * and obj_loc is in the same file, obj_loc should also hold the + * file open so that closing the grp_loc doesn't close the file. + */ + if(grp_loc->oloc->holding_file && grp_loc->oloc->file == obj_loc->oloc->file) + if(H5O_loc_hold_file(obj_loc->oloc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse_special() */ + + +/*------------------------------------------------------------------------- * Function: H5G_traverse_real * * Purpose: Internal version of path traversal routine @@ -564,75 +646,22 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, /* (Defer issuing error for bad lookup until later) */ lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id); - /* If the lookup was OK, try traversing soft links and mount points, if allowed */ + /* If the lookup was OK, build object location and traverse special links, etc. */ if(lookup_status >= 0) { - /* Indicate that the link info is valid */ + /* Sanity check link and indicate it's valid */ HDassert(lnk.type >= H5L_TYPE_HARD); - if(lnk.type >H5L_TYPE_BUILTIN_MAX && lnk.type < H5L_TYPE_UD_MIN) - HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "unknown link type") + HDassert(!HDstrcmp(H5G_comp_g, lnk.name)); link_valid = TRUE; - /* Build object's group hier. location */ - if(H5G_name_set(grp_loc.path, obj_loc.path, H5G_comp_g) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name") - - /* Set the object location, if it's a hard link set the address also */ - obj_loc.oloc->file = grp_loc.oloc->file; - obj_loc.oloc->holding_file = FALSE; - if(lnk.type == H5L_TYPE_HARD) - obj_loc.oloc->addr = lnk.u.hard.addr; + /* Build object location from the link */ + if(H5G_link_to_loc(&grp_loc, &lnk, &obj_loc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot initialize object location") obj_loc_valid = TRUE; - /* - * If we found a symbolic link then we should follow it. But if this - * is the last component of the name and the H5G_TARGET_SLINK bit of - * TARGET is set then we don't follow it. - */ - if(H5L_TYPE_SOFT == lnk.type && - (0 == (target & H5G_TARGET_SLINK) || !last_comp)) { - if((*nlinks)-- <= 0) - HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links") - if(H5G_traverse_slink(&grp_loc/*in,out*/, &lnk/*in*/, &obj_loc, nlinks, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "symbolic link traversal failed") - } /* end if */ - - /* - * If we found a user-defined link then we should follow it. But if this - * is the last component of the name and the H5G_TARGET_UDLINK bit of - * TARGET is set then we don't follow it. - */ - if(lnk.type >= H5L_TYPE_UD_MIN && - (0 == (target & H5G_TARGET_UDLINK) || !last_comp) ) { - if((*nlinks)-- <= 0) - HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links") - if(H5G_traverse_ud(&grp_loc/*in,out*/, &lnk/*in*/, &obj_loc, nlinks, lapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "user-defined link traversal failed") - } /* end if */ - - /* - * Resolve mount points to the mounted group. Do not do this step if - * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last - * component of the name. - * - * (If this link is a hard link, try to perform mount point traversal) - * - * (Note that the soft and external link traversal above can change - * the status of the object (into a hard link), so don't use an 'else' - * statement here. -QAK) - */ - if(H5F_addr_defined(obj_loc.oloc->addr) && - (0 == (target & H5G_TARGET_MOUNT) || !last_comp)) { - if(H5G_traverse_mount(&obj_loc/*in,out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "mount point traversal failed") - } /* end if */ - - /* If the grp_loc is the only thing holding an external file open - * and obj_loc is in the same file, obj_loc should also hold the - * file open so that closing the grp_loc doesn't close the file. - */ - if(grp_loc.oloc->holding_file && grp_loc.oloc->file == obj_loc.oloc->file) - if(H5O_loc_hold_file(obj_loc.oloc) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open") + /* Perform any special traversals that the link needs */ + /* (soft links, user-defined links, file mounting, etc.) */ + if(H5G_traverse_special(&grp_loc, &lnk, target, nlinks, last_comp, &obj_loc, lapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "special link traversal failed") } /* end if */ /* Check for last component in name provided */ diff --git a/src/H5L.c b/src/H5L.c index d6a9fa7..6ef6338 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -1935,7 +1935,7 @@ H5L_get_val_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, H5G_own_loc_t *own_loc/*out*/) { H5L_trav_gvbi_t *udata = (H5L_trav_gvbi_t *)_udata; /* User data passed in */ - H5O_link_t grp_lnk; /* Link within group */ + H5O_link_t fnd_lnk; /* Link within group */ hbool_t lnk_copied = FALSE; /* Whether the link was copied */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1947,18 +1947,18 @@ H5L_get_val_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, /* Query link */ if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order, - udata->n, &grp_lnk, udata->dxpl_id) < 0) + udata->n, &fnd_lnk, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") lnk_copied = TRUE; /* Retrieve the value for the link */ - if(H5L_get_val_real(&grp_lnk, udata->buf, udata->size) < 0) + if(H5L_get_val_real(&fnd_lnk, udata->buf, udata->size) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't retrieve link value") done: /* Reset the link information, if we have a copy */ if(lnk_copied) - H5O_reset(H5O_LINK_ID, &grp_lnk); + H5O_reset(H5O_LINK_ID, &fnd_lnk); /* Indicate that this callback didn't take ownership of the group * * location for the object */ @@ -2610,7 +2610,7 @@ H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, H5G_own_loc_t *own_loc/*out*/) { H5L_trav_gibi_t *udata = (H5L_trav_gibi_t *)_udata; /* User data passed in */ - H5O_link_t grp_lnk; /* Link within group */ + H5O_link_t fnd_lnk; /* Link within group */ hbool_t lnk_copied = FALSE; /* Whether the link was copied */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2622,18 +2622,18 @@ H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, /* Query link */ if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order, - udata->n, &grp_lnk, udata->dxpl_id) < 0) + udata->n, &fnd_lnk, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") lnk_copied = TRUE; /* Get information from the link */ - if(H5G_link_to_info(&grp_lnk, udata->linfo) < 0) + if(H5G_link_to_info(&fnd_lnk, udata->linfo) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link info") done: /* Reset the link information, if we have a copy */ if(lnk_copied) - H5O_reset(H5O_LINK_ID, &grp_lnk); + H5O_reset(H5O_LINK_ID, &fnd_lnk); /* Indicate that this callback didn't take ownership of the group * * location for the object */ diff --git a/src/H5O.c b/src/H5O.c index b1b373a..ff18111 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -268,6 +268,7 @@ H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") loc_found = TRUE; + /* Open the object */ if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object") @@ -282,6 +283,81 @@ done: /*------------------------------------------------------------------------- + * Function: H5Oopen_by_idx + * + * Purpose: Opens an object within an HDF5 file, according to the offset + * within an index. + * + * This function opens an object in the same way that H5Gopen, + * H5Topen, and H5Dopen do. However, H5Oopen doesn't require + * the type of object to be known beforehand. This can be + * useful in user-defined links, for instance, when only a + * path is known. + * + * The opened object should be closed again with H5Oclose + * or H5Gclose, H5Tclose, or H5Dclose. + * + * Return: Success: An open object identifier + * Failure: Negative + * + * Programmer: Quincey Koziol + * November 20 2006 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n, hid_t lapl_id) +{ + H5G_loc_t loc; + H5G_loc_t obj_loc; /* Location used to open group */ + H5G_name_t obj_path; /* Opened object group hier. path */ + H5O_loc_t obj_oloc; /* Opened object object location */ + hbool_t loc_found = FALSE; /* Entry at 'name' found */ + hid_t ret_value = FAIL; + + FUNC_ENTER_API(H5Oopen_by_idx, FAIL) + + /* Check args */ + if(H5G_loc(loc_id, &loc) < 0) + 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") + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object's location, according to the order in the index */ + if(H5G_loc_find_by_idx(&loc, group_name, idx_type, order, n, &obj_loc/*out*/, lapl_id, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") + loc_found = TRUE; + + /* Open the object */ + if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object") + +done: + if(ret_value < 0) + if(loc_found) + if(H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location") + + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5Oopen_by_addr * * Purpose: Warning! This function is EXTREMELY DANGEROUS! @@ -332,7 +408,7 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr) /* Check args */ if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if(addr == 0) + if(!H5F_addr_defined(addr)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no address supplied") /* Set up opened group location to fill in */ @@ -341,18 +417,17 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr) H5G_loc_reset(&obj_loc); obj_loc.oloc->addr = addr; obj_loc.oloc->file = loc.oloc->file; - H5G_name_reset(obj_loc.path); + H5G_name_reset(obj_loc.path); /* objects opened through this routine don't have a path name */ + /* Open the object */ if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object") done: - if(ret_value < 0) { - if(loc_found) { + if(ret_value < 0) + if(loc_found) if(H5G_loc_free(&obj_loc) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location") - } - } /* end if */ FUNC_LEAVE_API(ret_value) } /* end H5Oopen_by_addr() */ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index 9576ff1..258f701 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -29,8 +29,13 @@ #define _H5Opublic_H /* Public headers needed by this file */ -#include "H5public.h" -#include "H5Ipublic.h" +#include "H5public.h" /* Generic Functions */ +#include "H5Ipublic.h" /* IDs */ +#include "H5Lpublic.h" /* Links */ + +/*****************/ +/* Public Macros */ +/*****************/ /* Flags for object copy (H5Ocopy) */ #define H5O_COPY_SHALLOW_HIERARCHY_FLAG (0x0001u) /* Copy only immediate members */ @@ -57,6 +62,10 @@ #define H5O_MESG_ALL_FLAG (H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG | H5O_MESG_ATTR_FLAG) +/*******************/ +/* Public Typedefs */ +/*******************/ + typedef struct H5O_stat_t { hsize_t size; /* Total size of object header in file */ hsize_t free; /* Free space within object header */ @@ -64,12 +73,23 @@ typedef struct H5O_stat_t { unsigned nchunks; /* Number of object header chunks */ } H5O_stat_t; + +/********************/ +/* Public Variables */ +/********************/ + + #ifdef __cplusplus extern "C" { #endif +/*********************/ +/* Public Prototypes */ +/*********************/ H5_DLL hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id); H5_DLL hid_t H5Oopen_by_addr(hid_t loc_id, haddr_t addr); +H5_DLL hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id); H5_DLL herr_t H5Oincr_refcount(hid_t object_id); H5_DLL herr_t H5Odecr_refcount(hid_t object_id); H5_DLL herr_t H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, @@ -79,4 +99,5 @@ H5_DLL herr_t H5Oclose(hid_t object_id); #ifdef __cplusplus } #endif -#endif +#endif /* _H5Opublic_H */ + -- cgit v0.12