summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2010-03-05 17:51:45 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2010-03-05 17:51:45 (GMT)
commit187292532027ed6abdbd8be127381491881d5a59 (patch)
tree44f62304f23b9af8ac0f0b5f86d9acc5c00e8a32 /src
parent179b54da83f293948a531afd6b59e676df7a60e7 (diff)
downloadhdf5-187292532027ed6abdbd8be127381491881d5a59.zip
hdf5-187292532027ed6abdbd8be127381491881d5a59.tar.gz
hdf5-187292532027ed6abdbd8be127381491881d5a59.tar.bz2
[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
Diffstat (limited to 'src')
-rw-r--r--src/H5Gdeprec.c2
-rw-r--r--src/H5Glink.c96
-rw-r--r--src/H5Ocopy.c23
-rw-r--r--src/H5Opkg.h2
4 files changed, 79 insertions, 44 deletions
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 */