From 187292532027ed6abdbd8be127381491881d5a59 Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Fri, 5 Mar 2010 12:51:45 -0500 Subject: [svn-r18376] Purpose: Fix bug 1733 Description: Support for expanding external links was not implemented in H5Ocopy, even though a flag existed for H5Pset_copy_object to enable this. This patch implements this feature. Tested: jam, amani, linew (h5committest); Fedora --- release_docs/RELEASE.txt | 3 + src/H5Gdeprec.c | 2 +- src/H5Glink.c | 96 +++++++++++------- src/H5Ocopy.c | 23 +++-- src/H5Opkg.h | 2 +- test/objcopy.c | 250 ++++++++++++++++++++++++++++++++++++++++------- 6 files changed, 294 insertions(+), 82 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 1e845e3..84c7cf7 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -208,6 +208,9 @@ Bug Fixes since HDF5-1.8.0 release Library ------- + - Added support for H5O_COPY_EXPAND_EXT_LINK_FLAG to H5Ocopy. External + links will now be expanded if this flag is set. + (NAF - 2010/03/05 - 1733) - Fixed a bug where the library, when traversing an external link, would reopen the source file if nothing else worked. (NAF - 2010/03/05) - Fixed an intermittent bug in the b-tree code which could be triggered diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index a18339b..0eb4764 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -250,7 +250,7 @@ H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint) done: if(tmp_gcpl > 0 && tmp_gcpl != H5P_GROUP_CREATE_DEFAULT) - if(H5I_dec_ref(tmp_gcpl, TRUE) < 0) + if(H5I_dec_ref(tmp_gcpl, FALSE) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release property list") if(ret_value < 0) diff --git a/src/H5Glink.c b/src/H5Glink.c index f5ad7d9..05df268 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -403,6 +403,10 @@ H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk, H5O_link_t tmp_src_lnk; /* Temporary copy of src link, when needed */ const H5O_link_t *src_lnk = _src_lnk; /* Source link */ hbool_t dst_lnk_init = FALSE; /* Whether the destination link is initialized */ + hbool_t expanded_link_open = FALSE; /* Whether the target location has been opened */ + H5G_loc_t tmp_src_loc; /* Group location holding target object */ + H5G_name_t tmp_src_path; /* Path for target object */ + H5O_loc_t tmp_src_oloc; /* Object location for target object */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_link_copy_file, FAIL) @@ -413,61 +417,79 @@ H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk, HDassert(dst_lnk); HDassert(cpy_info); - /* Expand soft link */ - if(H5L_TYPE_SOFT == src_lnk->type && cpy_info->expand_soft_link) { - H5O_info_t oinfo; /* Information about object pointed to by soft link */ - H5G_loc_t grp_loc; /* Group location holding soft link */ - H5G_name_t grp_path; /* Path for group holding soft link */ - - /* Make a temporary copy, so that it will not change the info in the cache */ - if(NULL == H5O_msg_copy(H5O_LINK_ID, src_lnk, &tmp_src_lnk)) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy message") - - /* Set up group location for soft link to start in */ - H5G_name_reset(&grp_path); - grp_loc.path = &grp_path; - grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Casting away const OK -QAK */ - - /* Check if the object pointed by the soft link exists in the source file */ - if(H5G_loc_info(&grp_loc, tmp_src_lnk.u.soft.name, FALSE, &oinfo, H5P_DEFAULT, dxpl_id) >= 0) { - /* Convert soft link to hard link */ - tmp_src_lnk.u.soft.name = (char *)H5MM_xfree(tmp_src_lnk.u.soft.name); + /* Expand soft or external link, if requested */ + if((H5L_TYPE_SOFT == src_lnk->type && cpy_info->expand_soft_link) + || (H5L_TYPE_EXTERNAL == src_lnk->type + && cpy_info->expand_ext_link)) { + H5G_loc_t lnk_grp_loc; /* Group location holding link */ + H5G_name_t lnk_grp_path; /* Path for link */ + htri_t tar_exists; /* Whether the target object exists */ + + /* Set up group location for link */ + H5G_name_reset(&lnk_grp_path); + lnk_grp_loc.path = &lnk_grp_path; + lnk_grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Casting away const OK -QAK */ + + /* Check if the target object exists */ + if((tar_exists = H5G_loc_exists(&lnk_grp_loc, src_lnk->name, H5P_DEFAULT, + dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to check if target object exists") + + if(tar_exists) { + /* Make a temporary copy of the link, so that it will not change the + * info in the cache when we change it to a hard link */ + if(NULL == H5O_msg_copy(H5O_LINK_ID, src_lnk, &tmp_src_lnk)) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy message") + + /* Set up group location for target object. Let H5G_traverse expand + * the link. */ + tmp_src_loc.path = &tmp_src_path; + tmp_src_loc.oloc = &tmp_src_oloc; + if(H5G_loc_reset(&tmp_src_loc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to reset location") + + /* Find the target object */ + if(H5G_loc_find(&lnk_grp_loc, src_lnk->name, &tmp_src_loc, + H5P_DEFAULT, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to find target object") + expanded_link_open = TRUE; + + /* Convert symbolic link to hard link */ + if(tmp_src_lnk.type == H5L_TYPE_SOFT) + tmp_src_lnk.u.soft.name = + (char *)H5MM_xfree(tmp_src_lnk.u.soft.name); + else if(tmp_src_lnk.u.ud.size > 0) + tmp_src_lnk.u.ud.udata = H5MM_xfree(tmp_src_lnk.u.ud.udata); tmp_src_lnk.type = H5L_TYPE_HARD; - tmp_src_lnk.u.hard.addr = oinfo.addr; + tmp_src_lnk.u.hard.addr = tmp_src_oloc.addr; src_lnk = &tmp_src_lnk; } /* end if */ - else { - /* Discard any errors from a dangling soft link */ - H5E_clear_stack(NULL); - - /* Release any information copied for temporary src link */ - H5O_msg_reset(H5O_LINK_ID, &tmp_src_lnk); - } /* end else */ } /* end if */ /* Copy src link information to dst link information */ if(NULL == H5O_msg_copy(H5O_LINK_ID, src_lnk, dst_lnk)) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy message") dst_lnk_init = TRUE; /* Check if object in source group is a hard link & copy it */ if(H5L_TYPE_HARD == src_lnk->type) { H5O_loc_t new_dst_oloc; /* Copied object location in destination */ - H5O_loc_t tmp_src_oloc; /* Temporary object location for source object */ /* Set up copied object location to fill in */ H5O_loc_reset(&new_dst_oloc); new_dst_oloc.file = dst_file; - /* Build temporary object location for source */ - H5O_loc_reset(&tmp_src_oloc); - tmp_src_oloc.file = src_oloc->file; - HDassert(H5F_addr_defined(src_lnk->u.hard.addr)); - tmp_src_oloc.addr = src_lnk->u.hard.addr; + if(!expanded_link_open) { + /* Build temporary object location for source */ + H5O_loc_reset(&tmp_src_oloc); + tmp_src_oloc.file = src_oloc->file; + tmp_src_oloc.addr = src_lnk->u.hard.addr; + } /* end if */ + HDassert(H5F_addr_defined(tmp_src_oloc.addr)); /* Copy the shared object from source to destination */ if(H5O_copy_header_map(&tmp_src_oloc, &new_dst_oloc, dxpl_id, cpy_info, TRUE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy object") + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") /* Copy new destination object's information for eventual insertion */ dst_lnk->u.hard.addr = new_dst_oloc.addr; @@ -482,6 +504,10 @@ done: if(ret_value < 0) if(dst_lnk_init) H5O_msg_reset(H5O_LINK_ID, dst_lnk); + /* Check if we need to free the temp source oloc */ + if(expanded_link_open) + if(H5G_loc_free(&tmp_src_loc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_copy_file() */ diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index 1712706..da91782 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -661,12 +661,14 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Insert the address mapping for the new object into the copied list */ /* (Do this here, because "post copy" possibly checks it) */ - addr_map->src_addr = oloc_src->addr; + H5F_GET_FILENO(oloc_src->file, addr_map->src_obj_pos.fileno); + addr_map->src_obj_pos.addr = oloc_src->addr; addr_map->dst_addr = oloc_dst->addr; addr_map->is_locked = TRUE; /* We've locked the object currently */ addr_map->inc_ref_count = 0; /* Start with no additional ref counts to add */ - if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_addr)) < 0) + /* Insert into skip list */ + if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") /* "post copy" loop over messages, to fix up any messages which require a complete @@ -765,20 +767,27 @@ herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, H5O_copy_t *cpy_info, hbool_t inc_depth) { - H5O_addr_map_t *addr_map; /* Address mapping of object copied */ + H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ + H5_obj_t src_obj_pos; /* Position of source object */ hbool_t inc_link; /* Whether to increment the link count for the object */ - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5O_copy_header_map, FAIL) /* Sanity check */ HDassert(oloc_src); + HDassert(oloc_src->file); HDassert(oloc_dst); HDassert(oloc_dst->file); HDassert(cpy_info); - /* Look up the address of the object to copy in the skip list */ - addr_map = (H5O_addr_map_t *)H5SL_search(cpy_info->map_list, &(oloc_src->addr)); + /* Create object "position" struct */ + H5F_GET_FILENO(oloc_src->file, src_obj_pos.fileno); + src_obj_pos.addr = oloc_src->addr; + + /* Search for the object in the skip list of copied objects */ + addr_map = (H5O_addr_map_t *)H5SL_search(cpy_info->map_list, + &src_obj_pos); /* Check if address is already in list of objects copied */ if(addr_map == NULL) { @@ -910,7 +919,7 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, cpy_info.preserve_null = TRUE; /* Create a skip list to keep track of which objects are copied */ - if((cpy_info.map_list = H5SL_create(H5SL_TYPE_HADDR)) == NULL) + if((cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ)) == NULL) HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list") /* copy the object from the source file to the destination file */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 7e1811d..ee18dc9 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -326,7 +326,7 @@ typedef struct H5O_obj_class_t { /* Node in skip list to map addresses from one file to another during object header copy */ typedef struct H5O_addr_map_t { - haddr_t src_addr; /* Address of object in source file */ + H5_obj_t src_obj_pos; /* Location of source object */ haddr_t dst_addr; /* Address of object in destination file */ hbool_t is_locked; /* Indicate that the destination object is locked currently */ hsize_t inc_ref_count; /* Number of deferred increments to reference count */ diff --git a/test/objcopy.c b/test/objcopy.c index 05da5dd..854006e 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -103,8 +103,11 @@ const char *FILENAME[] = { #define NAME_LINK_SOFT "/g_links/soft_link_to_dataset_simple" #define NAME_LINK_SOFT2 "/g_links2/soft_link_to_dataset_simple" #define NAME_LINK_EXTERN "/g_links/external_link_to_dataset_simple" +#define NAME_LINK_EXTERN2 "/g_links2/external_link_to_dataset_simple" #define NAME_LINK_SOFT_DANGLE "/g_links/soft_link_to_nowhere" #define NAME_LINK_SOFT_DANGLE2 "/g_links2/soft_link_to_nowhere" +#define NAME_LINK_EXTERN_DANGLE "/g_links/external_link_to_nowhere" +#define NAME_LINK_EXTERN_DANGLE2 "/g_links2/external_link_to_nowhere" #define NAME_OLD_FORMAT "/dset1" #define NAME_BUF_SIZE 1024 @@ -5229,21 +5232,32 @@ error: * Friday, September 30, 2005 * * Modifications: + * Neil Fortner + * Tuesday, February 16, 2010 + * Modified test to test flags for expanding soft and external + * links. * *------------------------------------------------------------------------- */ static int test_copy_group_links(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) { - hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */ hid_t sid = -1; /* Dataspace ID */ - hid_t did = -1; /* Dataset ID */ + hid_t did = -1, did2 = -1; /* Dataset ID */ hid_t gid = -1, gid2 = -1; /* Group IDs */ + hid_t plid = -1; /* Object copy plist ID */ hsize_t dim2d[2]; + hsize_t dim1d[1]; + H5L_info_t linfo; int buf[DIM_SIZE_1][DIM_SIZE_2]; int i, j; + unsigned expand_soft; + unsigned expand_ext; + unsigned copy_options; char src_filename[NAME_BUF_SIZE]; char dst_filename[NAME_BUF_SIZE]; + char ext_filename[NAME_BUF_SIZE]; TESTING("H5Ocopy(): group with links"); @@ -5255,6 +5269,7 @@ test_copy_group_links(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) /* Initialize the filenames */ h5_fixname(FILENAME[0], fapl, src_filename, sizeof src_filename); h5_fixname(FILENAME[1], fapl, dst_filename, sizeof dst_filename); + h5_fixname(FILENAME[2], fapl, ext_filename, sizeof ext_filename); /* Reset file address checking info */ addr_reset(); @@ -5262,11 +5277,16 @@ test_copy_group_links(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) /* create source file */ if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, fapl)) < 0) TEST_ERROR - /* create group at the SRC file */ + /* create file to hold external dataset */ + if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, fapl)) < 0) TEST_ERROR + + /* create groups at the SRC file. Group 2 will hold dangling links. */ if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if((gid2 = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* attach attributes to the group */ + /* attach attributes to the groups */ if(test_copy_attach_attributes(gid, H5T_NATIVE_INT) < 0) TEST_ERROR + if(test_copy_attach_attributes(gid2, H5T_NATIVE_INT) < 0) TEST_ERROR /* Set dataspace dimensions */ dim2d[0]=DIM_SIZE_1; @@ -5285,57 +5305,162 @@ test_copy_group_links(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) /* close the dataset */ if(H5Dclose(did) < 0) TEST_ERROR + /* Now create a 1-D dataset in an external file */ + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_2; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* add a dataset to the external file */ + if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + /* make a hard link to the dataset */ if(H5Lcreate_hard(fid_src, NAME_LINK_DATASET, H5L_SAME_LOC, NAME_LINK_HARD, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR /* make a soft link to the dataset */ if(H5Lcreate_soft(NAME_LINK_DATASET, fid_src, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - /* make a soft link to nowhere */ - if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + /* make an external link to the external dataset */ + if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* make a dangling soft link */ + if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR /* make a dangling external link */ - if(H5Lcreate_external("filename", "obj_name", fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR - /* close the group */ + /* close the groups */ if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR - /* close the SRC file */ + /* close the SRC and EXT files */ if(H5Fclose(fid_src) < 0) TEST_ERROR + if(H5Fclose(fid_ext) < 0) TEST_ERROR - /* open the source file with read-only */ - if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + /* Create the object copy plist */ + if((plid = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR - /* create destination file */ - if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, fapl)) < 0) TEST_ERROR + /* Loop over all configurations (expand soft/external links) */ + for(expand_soft=0; expand_soft<=1; expand_soft++) { + for(expand_ext=0; expand_ext<=1; expand_ext++) { + /* Set the correct copy options on the obj copy plist */ + copy_options = 0; + if(expand_soft) + copy_options |= H5O_COPY_EXPAND_SOFT_LINK_FLAG; + if(expand_ext) + copy_options |= H5O_COPY_EXPAND_EXT_LINK_FLAG; + if(H5Pset_copy_object(plid, copy_options) < 0) TEST_ERROR - /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ - if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR - /* copy the group from SRC to DST */ - if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, fapl)) < 0) TEST_ERROR - /* open the group for copy */ - if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - /* open the destination group */ - if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + /* copy the group from SRC to DST */ + if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, plid, H5P_DEFAULT) < 0) TEST_ERROR - /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR + /* open the group for copy */ + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - /* close the destination group */ - if(H5Gclose(gid2) < 0) TEST_ERROR + /* open the destination group */ + if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - /* close the source group */ - if(H5Gclose(gid) < 0) TEST_ERROR + /* If expand_soft is set to true, verify that the soft link is now a + * hard link, and compare the expanded dataset, then delete it and + * re-add it as a soft link so compare_groups() works */ + if(expand_soft) { + /* Check link type */ + if(H5Lget_info(fid_dst, NAME_LINK_SOFT, &linfo, H5P_DEFAULT) < 0) TEST_ERROR + if(linfo.type != H5L_TYPE_HARD) + FAIL_PUTS_ERROR("Soft link was not expanded to a hard link") - /* close the SRC file */ - if(H5Fclose(fid_src) < 0) TEST_ERROR + /* Compare datasets */ + if((did = H5Dopen2(fid_src, NAME_LINK_DATASET, H5P_DEFAULT)) < 0) TEST_ERROR + if((did2 = H5Dopen2(fid_dst, NAME_LINK_SOFT, H5P_DEFAULT)) < 0) TEST_ERROR + if(compare_datasets(did, did2, H5P_DEFAULT, NULL) != TRUE) TEST_ERROR - /* close the DST file */ - if(H5Fclose(fid_dst) < 0) TEST_ERROR + /* Delete expanded dataset, add soft link */ + if(H5Ldelete(fid_dst, NAME_LINK_SOFT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lcreate_soft(NAME_LINK_DATASET, fid_dst, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close datasets */ + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Dclose(did2) < 0) TEST_ERROR + } /* end if */ + + /* If expand_ext is set to true, verify that the external link is + * now a hard link, and compare the expanded dataset, then delete it + * and re-add it as an external link so compare_groups() works */ + if(expand_ext) { + /* Check link type */ + if(H5Lget_info(fid_dst, NAME_LINK_EXTERN, &linfo, H5P_DEFAULT) < 0) TEST_ERROR + if(linfo.type != H5L_TYPE_HARD) + FAIL_PUTS_ERROR("External link was not expanded to a hard link") + + /* Compare datasets */ + if((fid_ext = H5Fopen(ext_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + if((did = H5Dopen2(fid_ext, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((did2 = H5Dopen2(fid_dst, NAME_LINK_EXTERN, H5P_DEFAULT)) < 0) TEST_ERROR + if(compare_datasets(did, did2, H5P_DEFAULT, NULL) != TRUE) TEST_ERROR + + /* Delete expanded dataset, add external link */ + if(H5Ldelete(fid_dst, NAME_LINK_EXTERN, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_dst, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close datasets and external file */ + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Dclose(did2) < 0) TEST_ERROR + if(H5Fclose(fid_ext) < 0) TEST_ERROR + } /* end if */ + + /* Check if the groups are equal */ + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR + + /* close the destination group */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* close the source group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Now try to copy the group containing the dangling link. They + * should always be copied as the same type of link, never expanded + * to hard links. */ + if(H5Ocopy(fid_src, NAME_GROUP_LINK2, fid_dst, NAME_GROUP_LINK2, plid, H5P_DEFAULT) < 0) TEST_ERROR + + /* Open the original and copied groups */ + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR + if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Compare the groups */ + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR + + /* Close groups */ + if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + } /* end for */ + } /* end for */ + + /* Close the object copy plist */ + if(H5Pclose(plid) < 0) TEST_ERROR PASSED(); return 0; @@ -5343,11 +5468,14 @@ test_copy_group_links(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) error: H5E_BEGIN_TRY { H5Sclose(sid); + H5Dclose(did2); H5Dclose(did); H5Gclose(gid2); H5Gclose(gid); + H5Fclose(fid_ext); H5Fclose(fid_dst); H5Fclose(fid_src); + H5Pclose(plid); } H5E_END_TRY; return 1; } /* end test_copy_group_links */ @@ -5516,7 +5644,7 @@ test_copy_ext_link(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) /* Initialize the filenames */ h5_fixname(FILENAME[0], fapl, src_filename, sizeof src_filename); h5_fixname(FILENAME[1], fapl, dst_filename, sizeof dst_filename); - h5_fixname(FILENAME[2], fapl, ext_filename, sizeof dst_filename); + h5_fixname(FILENAME[2], fapl, ext_filename, sizeof ext_filename); /* Reset file address checking info */ addr_reset(); @@ -7679,7 +7807,7 @@ error: static int test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl, unsigned flag, hbool_t crt_intermediate_grp, const char* test_desciption) { - hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */ hid_t sid = -1; /* Dataspace ID */ hid_t did = -1; /* Dataset ID */ hid_t gid=-1, gid2=-1, gid_ref=-1; /* Group IDs */ @@ -7770,6 +7898,45 @@ test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl, unsigned flag, hboo if(H5Gclose(gid) < 0) FAIL_STACK_ERROR } /* end if */ + if((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0) { + char ext_filename[NAME_BUF_SIZE]; + + h5_fixname(FILENAME[2], fapl, ext_filename, sizeof ext_filename); + + /* Create the external file and dataset */ + if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, fapl)) < 0) TEST_ERROR + if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR + if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Fclose(fid_ext) < 0) TEST_ERROR + + /* Create group to copy */ + if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + } /* end if */ + else + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Create group to compare with */ + if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) { + if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + } /* end if */ + else + if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR + if((did = H5Dcreate2(fid_src, NAME_LINK_EXTERN2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + } /* end if */ + if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) { if((gid_ref = H5Gcreate2(fid_src, NAME_GROUP_REF, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR @@ -7830,12 +7997,14 @@ test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl, unsigned flag, hboo /* open the destination group */ if((gid2 = H5Gopen2(fid_dst, "/new_g0/new_g00", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - } else if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) { + } else if(((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) + || ((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)) { if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, pid, H5P_DEFAULT) < 0) TEST_ERROR - /* Unlink dataset to copy from original location */ - /* (So group comparison works properly) */ - if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) + /* Unlink dataset to copy from original location */ + /* (So group comparison works properly) */ + if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR /* open the group for copy */ if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR @@ -7904,6 +8073,7 @@ error: H5Gclose(gid); H5Fclose(fid_dst); H5Fclose(fid_src); + H5Fclose(fid_ext); } H5E_END_TRY; return 1; } /* end test_copy_option */ @@ -8043,6 +8213,11 @@ main(void) "H5Ocopy(): with missing groups"); nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_EXPAND_SOFT_LINK_FLAG, FALSE, "H5Ocopy(): expand soft link"); + nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_EXPAND_EXT_LINK_FLAG, + FALSE, "H5Ocopy: expand external link"); + nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, + H5O_COPY_EXPAND_SOFT_LINK_FLAG | H5O_COPY_EXPAND_EXT_LINK_FLAG, + FALSE, "H5Ocopy: expand soft and external links"); nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_SHALLOW_HIERARCHY_FLAG, FALSE, "H5Ocopy(): shallow group copy"); nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_EXPAND_REFERENCE_FLAG, @@ -8086,7 +8261,6 @@ main(void) } /* TODO: not implemented - nerrors += test_copy_option(my_fapl, H5O_COPY_EXPAND_EXT_LINK_FLAG, FALSE, "H5Ocopy: expand external link"); nerrors += test_copy_mount(my_fapl); */ } /* end for */ -- cgit v0.12