From 0b7306beed3616d5e259ce3efa1dd0105f436fdb Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 28 Jul 2010 07:27:56 -0500 Subject: [svn-r19133] Description: Correct traversal of user-defined links (including external links) to retain path information of object, allowing H5Iget_name() queries to work quickly (without searching entire destination file). This required some refactoring and addition of a mechanism to detect if a "fast" query was performed (for the tests). Minor code cleanups, etc. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, w/threadsafe, in production mode Linux/PPC 2.6 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode Mac OS X/32 10.6.4 (amazon) in debug mode Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode --- MANIFEST | 1 + src/H5Dtest.c | 2 +- src/H5Gname.c | 72 ++++++++++++++++++++---------------- src/H5Gprivate.h | 4 +- src/H5Gtraverse.c | 95 ++++++++++++++--------------------------------- src/H5I.c | 50 +++++++++++++++---------- src/H5Ipkg.h | 6 +++ src/H5Itest.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Lexternal.c | 52 +++++++++++++------------- src/Makefile.am | 2 +- src/Makefile.in | 5 ++- test/getname.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 12 files changed, 339 insertions(+), 157 deletions(-) create mode 100644 src/H5Itest.c diff --git a/MANIFEST b/MANIFEST index 6f67124..e4efb7a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -638,6 +638,7 @@ ./src/H5Ipkg.h ./src/H5Iprivate.h ./src/H5Ipublic.h +./src/H5Itest.c ./src/H5L.c ./src/H5Lexternal.c ./src/H5Lpkg.h diff --git a/src/H5Dtest.c b/src/H5Dtest.c index a933c88..0a69ff7 100644 --- a/src/H5Dtest.c +++ b/src/H5Dtest.c @@ -14,7 +14,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Programmer: Quincey Koziol - * Thusdayr, May 27, 2004 + * Thursday, May 27, 2004 * * Purpose: Dataset testing functions. */ diff --git a/src/H5Gname.c b/src/H5Gname.c index b298ccf..96b2e3a 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -426,49 +426,57 @@ H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_depth_t depth) *------------------------------------------------------------------------- */ ssize_t -H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id, - hid_t dxpl_id) +H5G_get_name(const H5G_loc_t *loc, char *name/*out*/, size_t size, + hbool_t *cached, hid_t lapl_id, hid_t dxpl_id) { - H5G_loc_t loc; /* Object location */ - ssize_t ret_value = FAIL; + ssize_t len = 0; /* Length of object's name */ + ssize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_get_name, FAIL) - /* get object location */ - if(H5G_loc(id, &loc) >= 0) { - ssize_t len = 0; + /* Sanity check */ + HDassert(loc); - /* If the user path is available and it's not "hidden", use it */ - if(loc.path->user_path_r != NULL && loc.path->obj_hidden == 0) { - len = H5RS_len(loc.path->user_path_r); + /* If the user path is available and it's not "hidden", use it */ + if(loc->path->user_path_r != NULL && loc->path->obj_hidden == 0) { + len = H5RS_len(loc->path->user_path_r); - if(name) { - HDstrncpy(name, H5RS_get_str(loc.path->user_path_r), MIN((size_t)(len + 1), size)); - if((size_t)len >= size) - name[size - 1] = '\0'; - } /* end if */ + if(name) { + HDstrncpy(name, H5RS_get_str(loc->path->user_path_r), MIN((size_t)(len + 1), size)); + if((size_t)len >= size) + name[size - 1] = '\0'; } /* end if */ - else if(!loc.path->obj_hidden) { - hid_t file; - /* Retrieve file ID for name search */ - if((file = H5I_get_file_id(id, FALSE)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID") + /* Indicate that the name is cached, if requested */ + /* (Currently only used for testing - QAK, 2010/07/26) */ + if(cached) + *cached = TRUE; + } /* end if */ + else if(!loc->path->obj_hidden) { + hid_t file; - /* Search for name of object */ - if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) { - H5I_dec_ref(file, FALSE); - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name") - } /* end if */ + /* Retrieve file ID for name search */ + if((file = H5F_get_id(loc->oloc->file, FALSE)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get file ID") - /* Close file ID used for search */ - if(H5I_dec_ref(file, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTCLOSEFILE, FAIL, "can't determine name") - } /* end else */ + /* Search for name of object */ + if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc->oloc, name, size)) < 0) { + H5I_dec_ref(file, FALSE); + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name") + } /* end if */ - /* Set return value */ - ret_value = len; - } /* end if */ + /* Close file ID used for search */ + if(H5I_dec_ref(file, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCLOSEFILE, FAIL, "can't determine name") + + /* Indicate that the name is _not_ cached, if requested */ + /* (Currently only used for testing - QAK, 2010/07/26) */ + if(cached) + *cached = FALSE; + } /* end else */ + + /* Set return value */ + ret_value = len; done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 3e66777..7b09423 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -196,8 +196,8 @@ H5_DLL herr_t H5G_name_replace(const struct H5O_link_t *lnk, H5G_names_op_t op, H5_DLL herr_t H5G_name_reset(H5G_name_t *name); H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_depth_t depth); H5_DLL herr_t H5G_name_free(H5G_name_t *name); -H5_DLL ssize_t H5G_get_name(hid_t id, char *name/*out*/, size_t size, - hid_t lapl_id, hid_t dxpl_id); +H5_DLL ssize_t H5G_get_name(const H5G_loc_t *loc, char *name/*out*/, size_t size, + hbool_t *cached, hid_t lapl_id, hid_t dxpl_id); H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, hid_t lapl_id, hid_t dxpl_id, const struct H5O_loc_t *loc, char* name, size_t size); diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 5b1f71c..61c08fa 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -171,8 +171,7 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk, H5G_loc_t grp_loc_copy; H5G_name_t grp_path_copy; H5O_loc_t grp_oloc_copy; - H5O_loc_t *new_oloc = NULL; - H5F_t *temp_file = NULL; + H5G_loc_t new_loc; /* Group location for newly opened external object */ H5G_t *grp; hid_t lapl_id = (-1); /* LAPL local to this routine */ H5P_genplist_t *lapl; /* LAPL with nlinks set */ @@ -189,13 +188,9 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk, 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 */ - H5G_name_free(obj_loc->path); - /* Get the link class for this type of link. */ if(NULL == (link_class = H5L_find_class(lnk->type))) - HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to get UD link class") + HGOTO_ERROR(H5E_SYM, H5E_NOTREGISTERED, FAIL, "unable to get UD link class") /* Set up location for user-defined callback. Use a copy of our current * grp_loc. */ @@ -203,37 +198,37 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk, grp_loc_copy.oloc = &grp_oloc_copy; H5G_loc_reset(&grp_loc_copy); if(H5G_loc_copy(&grp_loc_copy, grp_loc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location") + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "unable to copy object location") - /* Create a group to pass to the user-defined callback */ - if((grp = H5G_open(&grp_loc_copy, dxpl_id)) == NULL) + /* Create a group ID to pass to the user-defined callback */ + if(NULL == (grp = H5G_open(&grp_loc_copy, dxpl_id))) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") if((cur_grp = H5I_register(H5I_GROUP, grp, FALSE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") + HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, FAIL, "unable to register group") /* Check for generic default property list and use link access default if so */ if(_lapl_id == H5P_DEFAULT) { HDassert(H5P_LINK_ACCESS_DEFAULT != -1); if(NULL == (lapl = (H5P_genplist_t *)H5I_object(H5P_LINK_ACCESS_DEFAULT))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get default property list") + HGOTO_ERROR(H5E_SYM, H5E_BADATOM, FAIL, "unable to get default property list") } /* end if */ else { /* Get the underlying property list passed in */ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(_lapl_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID") + HGOTO_ERROR(H5E_SYM, H5E_BADATOM, FAIL, "unable to get property list from ID") } /* end else */ /* Copy the property list passed in */ if((lapl_id = H5P_copy_plist(lapl, FALSE)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to copy property list") + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "unable to copy property list") /* Get the underlying property list copy */ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(lapl_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID") + HGOTO_ERROR(H5E_SYM, H5E_BADATOM, FAIL, "unable to get property list from ID") /* Record number of soft links left to traverse in the property list. */ if(H5P_set(lapl, H5L_ACS_NLINKS_NAME, nlinks) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set nlink info") + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set nlink info") /* User-defined callback function */ cb_return = (link_class->trav_func)(lnk->name, cur_grp, lnk->u.ud.udata, lnk->u.ud.size, lapl_id); @@ -253,79 +248,45 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk, } /* end if */ /* else, we really needed to open the object */ else - HGOTO_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "traversal callback returned invalid ID") + HGOTO_ERROR(H5E_SYM, H5E_BADATOM, FAIL, "traversal callback returned invalid ID") } /* end if */ - /* Get the oloc from the ID the user callback returned */ - switch(H5I_get_type(cb_return)) { - case H5I_GROUP: - if((new_oloc = H5G_oloc((H5G_t *)H5I_object(cb_return))) == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from group ID") - break; - - case H5I_DATASET: - if((new_oloc = H5D_oloc((H5D_t *)H5I_object(cb_return))) ==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from dataset ID") - break; - - case H5I_DATATYPE: - if((new_oloc = H5T_oloc((H5T_t *)H5I_object(cb_return))) ==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from datatype ID") - break; - - case H5I_FILE: - if((temp_file = (H5F_t *)H5I_object(cb_return)) == NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "couldn't get file from ID") - if((new_oloc = H5G_oloc(temp_file->shared->root_grp)) ==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get root group location from file ID") - break; - - case H5I_UNINIT: - case H5I_BADID: - case H5I_DATASPACE: - case H5I_ATTR: - case H5I_REFERENCE: - case H5I_VFL: - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - case H5I_NTYPES: - default: - HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, FAIL, "not a valid location or object ID") - } /* end switch */ - - /* Copy the location the user returned to us */ - if(H5O_loc_copy(obj_loc->oloc, new_oloc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location") + /* Get the object location information from the ID the user callback returned */ + if(H5G_loc(cb_return, &new_loc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to get object location from ID") + + /* Release any previous location information for the object */ + H5G_loc_free(obj_loc); + + /* Copy new object's location information */ + H5G_loc_copy(obj_loc, &new_loc, H5_COPY_DEEP); /* Hold the file open until we free this object header (otherwise the * object location will be invalidated when the file closes). */ if(H5O_loc_hold_file(obj_loc->oloc) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open") + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to hold file open") /* We have a copy of the location and we're holding the file open. * Close the open ID the user passed back. */ if(H5I_dec_ref(cb_return, FALSE) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") cb_return = (-1); done: /* Close location given to callback. */ if(cur_grp > 0) if(H5I_dec_ref(cur_grp, FALSE) < 0) - HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for current location") + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close atom for current location") if(ret_value < 0 && cb_return > 0) if(H5I_dec_ref(cb_return, FALSE) < 0) - HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback") /* Close the LAPL, if we copied one */ if(lapl_id > 0 && H5I_dec_ref(lapl_id, FALSE) < 0) - HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close copied link access property list") + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close copied link access property list") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_traverse_ud() */ @@ -573,7 +534,7 @@ H5G_traverse_special(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, */ 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") + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to hold file open") done: FUNC_LEAVE_NOAPI(ret_value) @@ -845,7 +806,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, */ if(grp_loc.oloc->holding_file) if(H5O_loc_hold_file(obj_loc.oloc) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open") + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to hold file open") } /* end if */ else HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found") diff --git a/src/H5I.c b/src/H5I.c index d6655e0..be3c9d6 100644 --- a/src/H5I.c +++ b/src/H5I.c @@ -896,7 +896,7 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref) /* new ID to check for */ next_id = H5I_MAKE(type, type_ptr->nextid); - hash_loc = H5I_LOC(type_ptr->nextid, type_ptr->hash_size); + hash_loc = (unsigned)H5I_LOC(type_ptr->nextid, type_ptr->hash_size); curr_id = type_ptr->id_list[hash_loc]; if(curr_id == NULL) break; /* Ha! this is not likely... */ @@ -1421,15 +1421,16 @@ H5I_dec_ref(hid_t id, hbool_t app_ref) if(!type_ptr->free_func || (type_ptr->free_func)((void *)id_ptr->obj_ptr) >= 0) { H5I_remove(id); ret_value = 0; - } else { + } /* end if */ + else ret_value = FAIL; - } - } else { + } /* end if */ + else { --(id_ptr->count); - if (app_ref) + if(app_ref) --(id_ptr->app_count); HDassert(id_ptr->count >= id_ptr->app_count); - ret_value = app_ref ? id_ptr->app_count : id_ptr->count; + ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count); } done: @@ -1525,7 +1526,7 @@ H5I_inc_ref(hid_t id, hbool_t app_ref) ++(id_ptr->app_count); /* Set return value */ - ret_value = app_ref ? id_ptr->app_count : id_ptr->count; + ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1615,7 +1616,7 @@ H5I_get_ref(hid_t id, hbool_t app_ref) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID") /* Set return value */ - ret_value = app_ref ? id_ptr->app_count : id_ptr->count; + ret_value = (int)(app_ref ? id_ptr->app_count : id_ptr->count); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1696,7 +1697,7 @@ H5I_inc_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* Set return value */ - ret_value = ++(type_ptr->count); + ret_value = (int)(++(type_ptr->count)); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1797,7 +1798,7 @@ H5I_dec_type_ref(H5I_type_t type) } /* end if */ else { --(type_ptr->count); - ret_value = type_ptr->count; + ret_value = (herr_t)type_ptr->count; } /* end else */ done: @@ -1879,7 +1880,7 @@ H5I_get_type_ref(H5I_type_t type) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type") /* Set return value */ - ret_value = type_ptr->count; + ret_value = (int)type_ptr->count; done: FUNC_LEAVE_NOAPI(ret_value) @@ -2133,13 +2134,18 @@ done: ssize_t H5Iget_name(hid_t id, char *name/*out*/, size_t size) { + H5G_loc_t loc; /* Object location */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Iget_name, FAIL) H5TRACE3("Zs", "ixz", id, name, size); + /* Get object location */ + if(H5G_loc(id, &loc) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object location") + /* Call internal group routine to retrieve object's name */ - if((ret_value = H5G_get_name(id, name, size, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + if((ret_value = H5G_get_name(&loc, name, size, NULL, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object name") done: @@ -2187,7 +2193,6 @@ done: * ID given an object ID. * * Return: Success: file ID - * * Failure: a negative value * * Programmer: Raymond Lu @@ -2198,7 +2203,6 @@ done: hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref) { - H5G_loc_t loc; /* Location of object */ H5I_type_t type; /* ID type */ hid_t ret_value; /* Return value */ @@ -2207,18 +2211,24 @@ H5I_get_file_id(hid_t obj_id, hbool_t app_ref) /* Get object type */ type = H5I_TYPE(obj_id); if(type == H5I_FILE) { - ret_value = obj_id; - - /* Increment reference count on atom. */ - if(H5I_inc_ref(ret_value, app_ref) < 0) + /* Increment reference count on file ID */ + if(H5I_inc_ref(obj_id, app_ref) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") - } + + /* Set return value */ + ret_value = obj_id; + } /* end if */ else if(type == H5I_DATATYPE || type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) { + H5G_loc_t loc; /* Location of object */ + + /* Get the object location information */ if(H5G_loc(obj_id, &loc) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get object location") + + /* Get the file ID for the object */ if((ret_value = H5F_get_id(loc.oloc->file, app_ref)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get file ID") - } + } /* end if */ else HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID") diff --git a/src/H5Ipkg.h b/src/H5Ipkg.h index e86f134..f17a4b0 100644 --- a/src/H5Ipkg.h +++ b/src/H5Ipkg.h @@ -67,4 +67,10 @@ /* Package Private Prototypes */ /******************************/ +/* Testing functions */ +#ifdef H5I_TESTING +H5_DLL ssize_t H5I_get_name_test(hid_t id, char *name/*out*/, size_t size, + hbool_t *cached); +#endif /* H5I_TESTING */ + #endif /*_H5Ipkg_H*/ diff --git a/src/H5Itest.c b/src/H5Itest.c new file mode 100644 index 0000000..1c6892d --- /dev/null +++ b/src/H5Itest.c @@ -0,0 +1,98 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol + * Tuesday, July 27, 2010 + * + * Purpose: ID testing functions. + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5I_PACKAGE /*suppress error about including H5Ipkg */ +#define H5I_TESTING /*suppress warning about H5I testing funcs*/ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gprivate.h" /* Groups */ +#include "H5Ipkg.h" /* IDs */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5I_get_name_test + * + * Purpose: Testing version of H5Iget_name() + * + * Return: Success: The length of name. + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, July 27, 2010 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5I_get_name_test(hid_t id, char *name/*out*/, size_t size, hbool_t *cached) +{ + H5G_loc_t loc; /* Object location */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_get_name_test, FAIL) + + /* Get object location */ + if(H5G_loc(id, &loc) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object location") + + /* Call internal group routine to retrieve object's name */ + if((ret_value = H5G_get_name(&loc, name, size, cached, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object name") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_get_name_test() */ + diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c index c5ae92f..d98a843 100644 --- a/src/H5Lexternal.c +++ b/src/H5Lexternal.c @@ -53,6 +53,9 @@ const H5L_class_t H5L_EXTERN_LINK_CLASS[1] = {{ /* Valid flags for external links */ #define H5L_EXT_FLAGS_ALL 0 +/* Size of local link name buffer for traversing external links */ +#define H5L_EXT_TRAVERSE_BUF_SIZE 256 + /*-------------------------------------------------------------------------- NAME @@ -205,7 +208,8 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, H5L_elink_cb_t cb_info; /* Callback info struct */ hid_t fapl_id = -1; /* File access property list for external link's file */ hid_t ext_obj = -1; /* ID for external link's object */ - char *temp_group_name = NULL;/* Temporary pointer to group name */ + char *parent_group_name = NULL;/* Temporary pointer to group name */ + char local_group_name[H5L_EXT_TRAVERSE_BUF_SIZE]; /* Local buffer to hold group name */ char *temp_file_name = NULL; /* Temporary pointer to file name */ char *actual_file_name = NULL; /* Parent file's actual name */ H5P_genplist_t *fa_plist; /* File access property list pointer */ @@ -264,41 +268,34 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group, /* Make callback if it exists */ if(cb_info.func) { const char *parent_file_name; /* Parent file name */ - const char *parent_group_name; /* Parent group name */ + ssize_t group_name_len; /* Length of parent group name */ /* Get parent file name */ parent_file_name = H5F_OPEN_NAME(loc.oloc->file); + /* Query length of parent group name */ + if((group_name_len = H5G_get_name(&loc, NULL, (size_t) 0, NULL, lapl_id, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve length of group name") + + /* Account for null terminator */ + group_name_len++; + + /* Check if we need to allocate larger buffer */ + if((size_t)group_name_len > sizeof(local_group_name)) { + if(NULL == (parent_group_name = (char *)H5MM_malloc((size_t)group_name_len))) + HGOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, "can't allocate buffer to hold group name, group_name_len = %Zu", group_name_len) + } /* end if */ + else + parent_group_name = local_group_name; + /* Get parent group name */ - if(loc.path->user_path_r != NULL && loc.path->obj_hidden == 0) - /* Use user_path_r if possible */ - parent_group_name = H5RS_get_str(loc.path->user_path_r); - else { - /* Otherwise use H5G_get_name */ - ssize_t group_name_len; /* Length of parent group name */ - - /* Get length of parent group name */ - if((group_name_len = H5G_get_name(cur_group, NULL, (size_t) 0, lapl_id, H5AC_ind_dxpl_id)) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve length of group name") - - /* account for null terminator */ - group_name_len++; - - /* Copy parent group name */ - if(NULL == (temp_group_name = (char *)H5MM_malloc((size_t)group_name_len))) - HGOTO_ERROR(H5E_LINK, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5G_get_name(cur_group, temp_group_name, (size_t) group_name_len, lapl_id, H5AC_ind_dxpl_id) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve group name") - parent_group_name = temp_group_name; - } /* end else */ + if(H5G_get_name(&loc, parent_group_name, (size_t) group_name_len, NULL, lapl_id, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve group name") /* Make callback */ if((cb_info.func)(parent_file_name, parent_group_name, file_name, obj_name, &intent, fapl_id, cb_info.user_data) < 0) HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "traversal operator failed") - /* Free temp_group_name */ - temp_group_name = (char *)H5MM_xfree(temp_group_name); - /* Check access flags */ if((intent & H5F_ACC_TRUNC) || (intent & H5F_ACC_EXCL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") @@ -460,8 +457,9 @@ done: HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list") if(ext_file && H5F_try_close(ext_file) < 0) HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file") + if(parent_group_name && parent_group_name != local_group_name) + parent_group_name = (char *)H5MM_xfree(parent_group_name); full_name = (char *)H5MM_xfree(full_name); - temp_group_name = (char *)H5MM_xfree(temp_group_name); temp_file_name = (char *)H5MM_xfree(temp_file_name); actual_file_name = (char *)H5MM_xfree(actual_file_name); diff --git a/src/Makefile.am b/src/Makefile.am index 65e2bac..dc0edb3 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,7 +72,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ H5HG.c H5HGcache.c H5HGdbg.c \ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c \ - H5HP.c H5I.c H5L.c H5Lexternal.c H5lib_settings.c \ + H5HP.c H5I.c H5Itest.c H5L.c H5Lexternal.c H5lib_settings.c \ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 88d8793..c7fb1b4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -122,7 +122,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \ H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \ H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HL.lo \ - H5HLcache.lo H5HLdbg.lo H5HLint.lo H5HP.lo H5I.lo H5L.lo \ + H5HLcache.lo H5HLdbg.lo H5HLint.lo H5HP.lo H5I.lo H5Itest.lo H5L.lo \ H5Lexternal.lo H5lib_settings.lo H5MF.lo H5MFaggr.lo \ H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \ @@ -492,7 +492,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ H5HG.c H5HGcache.c H5HGdbg.c \ H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c \ - H5HP.c H5I.c H5L.c H5Lexternal.c H5lib_settings.c \ + H5HP.c H5I.c H5Itest.c H5L.c H5Lexternal.c H5lib_settings.c \ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ @@ -803,6 +803,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Itest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Lexternal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@ diff --git a/test/getname.c b/test/getname.c index 0dc623e..eba0f6b 100644 --- a/test/getname.c +++ b/test/getname.c @@ -21,12 +21,15 @@ */ #define H5G_PACKAGE /*suppress error about including H5Gpkg */ +#define H5I_PACKAGE /*suppress error about including H5Ipkg */ -/* Define this macro to indicate that the testing APIs should be available */ +/* Define these macros to indicate that the testing APIs should be available */ #define H5G_TESTING +#define H5I_TESTING #include "h5test.h" #include "H5Gpkg.h" /* Groups */ +#include "H5Ipkg.h" /* IDs */ /* Compound datatype */ @@ -1145,7 +1148,7 @@ test_main(hid_t file_id, hid_t fapl) /* Get name */ *name2 = '\0'; - name_len=H5Iget_name(group_id, name2, SMALL_NAME_BUF_SIZE); + name_len=(size_t)H5Iget_name(group_id, name2, SMALL_NAME_BUF_SIZE); /* Check that name is longer */ if(name_len <= SMALL_NAME_BUF_SIZE) TEST_ERROR @@ -1172,14 +1175,14 @@ test_main(hid_t file_id, hid_t fapl) if((group_id = H5Gopen2(file_id, "/g17", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR /* Get name */ - name_len = H5Iget_name(group_id, NULL, NAME_BUF_SIZE); + name_len = (size_t)H5Iget_name(group_id, NULL, NAME_BUF_SIZE); { /* dynamic buffer to hold name */ char *name3; /* Include the extra null character */ - name3 = HDmalloc(name_len + 1); + name3 = (char *)HDmalloc(name_len + 1); if(!name3) TEST_ERROR /* Get name with dynamic buffer */ @@ -2679,7 +2682,7 @@ test_reg_ref(hid_t fapl) hsize_t count[2]; hsize_t coord[2][3] = {{0, 0, 1}, {6, 0, 8}}; unsigned num_points = 3; - size_t name_size1, name_size2; + ssize_t name_size1, name_size2; char buf1[NAME_BUF_SIZE], buf2[NAME_BUF_SIZE]; /* Initialize the file name */ @@ -2808,6 +2811,101 @@ error: return 1; } + +/*------------------------------------------------------------------------- + * Function: test_elinks + * + * Purpose: Verify that querying names of objects reached via external + * links uses cached path/name information for object and doesn't + * search the file. + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, July 27, 2010 + * + *------------------------------------------------------------------------- + */ +static int +test_elinks(hid_t fapl) +{ + char filename1[1024], filename2[1024]; /* Filenames */ + hid_t fid1, fid2; /* HDF5 File IDs */ + hid_t group, group2; /* Group IDs */ + char name[NAME_BUF_SIZE]; /* Buffer for storing object's name */ + ssize_t namelen; /* Length of object's name */ + hbool_t name_cached; /* Indicate if name is cached */ + unsigned u; /* Counting variables */ + + /* Initialize the file names */ + h5_fixname(FILENAME[1], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[2], fapl, filename2, sizeof filename2); + + /* Create files */ + if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Create a group in the second file */ + if((group2 = H5Gcreate2(fid2, "Group2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Close Group */ + if(H5Gclose(group2) < 0) + FAIL_STACK_ERROR + + /* Create an external link in first file to the group in the second file */ + if(H5Lcreate_external(filename2, "Group2", fid1, "Link_to_Group2", H5P_DEFAULT, H5P_DEFAULT) < 0) + FAIL_STACK_ERROR + + /* Create an external link in second file to the external link in the first file */ + if(H5Lcreate_external(filename1, "Link_to_Group2", fid2, "Link_to_Link_to_Group2", H5P_DEFAULT, H5P_DEFAULT) < 0) + FAIL_STACK_ERROR + + /* Open the group in thesecond file through the external link */ + if((group = H5Gopen2(fid1, "Link_to_Group2", H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Query the external link object's name */ + *name = '\0'; + name_cached = FALSE; + namelen = H5I_get_name_test(group, (char*)name, sizeof(name), &name_cached); + if(!((HDstrcmp(name, "/Group2") == 0) && (namelen == 7) && name_cached)) + TEST_ERROR + + /* Close Group */ + if(H5Gclose(group) < 0) + FAIL_STACK_ERROR + + /* Open the group in the second file through the external link to the external link */ + if((group = H5Gopen2(fid2, "Link_to_Link_to_Group2", H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Query the external link to external link object's name */ + *name = '\0'; + name_cached = FALSE; + namelen = H5I_get_name_test(group, (char*)name, sizeof(name), &name_cached); + if(!((HDstrcmp(name, "/Group2") == 0) && (namelen == 7) && name_cached)) + TEST_ERROR + + /* Close Group */ + if(H5Gclose(group) < 0) + FAIL_STACK_ERROR + + /* Close files */ + if(H5Fclose(fid1) < 0) + FAIL_STACK_ERROR + if(H5Fclose(fid2) < 0) + FAIL_STACK_ERROR + + return 0; + +error: + return 1; +} + int main(void) { @@ -2830,6 +2928,7 @@ main(void) nerrors += test_main(file_id, fapl); nerrors += test_obj_ref(fapl); nerrors += test_reg_ref(fapl); + nerrors += test_elinks(fapl); /* Close file */ H5Fclose(file_id); -- cgit v0.12