summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt1
-rw-r--r--src/H5Aint.c536
-rw-r--r--src/H5Apkg.h9
-rw-r--r--src/H5Oainfo.c66
-rw-r--r--src/H5Oattr.c283
-rwxr-xr-xtest/objcopy.c189
6 files changed, 769 insertions, 315 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index b225ae5..7ca6ecf 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -51,6 +51,7 @@ New Features
Library:
--------
+ - Added support for dense attributes to H5Ocopy. (XCao/NAF - 2009/01/29)
- Added H5Pset_elink_cb and H5Pget_elink_cb functions to support a
user-defined callback function for external link traversal.
(NAF - 2009/01/08)
diff --git a/src/H5Aint.c b/src/H5Aint.c
index aadf79c..a93d807 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -66,6 +66,17 @@ typedef struct {
size_t curr_attr; /* Current attribute to operate on */
} H5A_dense_bt_ud_t;
+/* Data exchange structure to use when copying an attribute from _SRC to _DST */
+typedef struct {
+ H5O_ainfo_t *ainfo; /* dense information */
+ H5F_t *file; /* file */
+ hbool_t *recompute_size; /* Flag to indicate if size changed */
+ H5O_copy_t *cpy_info; /* Information on copying options */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5O_loc_t *oloc_src;
+ H5O_loc_t *oloc_dst;
+} H5A_dense_file_cp_ud_t;
+
/********************/
/* Package Typedefs */
@@ -765,3 +776,528 @@ H5A_set_version(const H5F_t *f, H5A_t *attr)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5A_set_version() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_copy_file
+ *
+ * Purpose: Copies a message from _MESG to _DEST in file
+ *
+ * Return: Success: Ptr to _DEST
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * November 1, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_attr_copy_file(H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_size,
+ H5O_copy_t *cpy_info, hid_t dxpl_id)
+{
+ H5A_t *attr_dst = NULL;
+
+ /* for dataype conversion */
+ hid_t tid_src = -1; /* Datatype ID for source datatype */
+ hid_t tid_dst = -1; /* Datatype ID for destination datatype */
+ hid_t tid_mem = -1; /* Datatype ID for memory datatype */
+ void *buf = NULL; /* Buffer for copying data */
+ void *reclaim_buf = NULL; /* Buffer for reclaiming data */
+ hid_t buf_sid = -1; /* ID for buffer dataspace */
+
+ H5A_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_attr_copy_file)
+
+ /* check args */
+ HDassert(attr_src);
+ HDassert(file_dst);
+ HDassert(cpy_info);
+ HDassert(!cpy_info->copy_without_attr);
+
+ /* Allocate space for the destination message */
+ if(NULL == (attr_dst = H5FL_CALLOC(H5A_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Copy the top level of the attribute */
+ *attr_dst = *attr_src;
+
+ if(NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
+
+ /* Don't have an opened group location for copy */
+ H5O_loc_reset(&(attr_dst->shared->oloc));
+ H5G_name_reset(&(attr_dst->path));
+ attr_dst->obj_opened = FALSE;
+
+ /* Reference count for the header message in the cache */
+ attr_dst->shared->nrefs = 1;
+
+ /* Copy attribute's name */
+ attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
+ HDassert(attr_dst->shared->name);
+
+ /* Copy attribute's datatype */
+ /* (Start destination datatype as transient, even if source is named) */
+ if(NULL == (attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "cannot copy datatype")
+
+ /* Set the location of the destination datatype */
+ if(H5T_set_loc(attr_dst->shared->dt, file_dst, H5T_LOC_DISK) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk")
+
+ /* Check for named datatype being copied */
+ if(H5T_committed(attr_src->shared->dt)) {
+ H5O_loc_t *src_oloc; /* Pointer to source datatype's object location */
+ H5O_loc_t *dst_oloc; /* Pointer to dest. datatype's object location */
+
+ /* Get group entries for source & destination */
+ src_oloc = H5T_oloc(attr_src->shared->dt);
+ HDassert(src_oloc);
+ dst_oloc = H5T_oloc(attr_dst->shared->dt);
+ HDassert(dst_oloc);
+
+ /* Reset object location for new object */
+ H5O_loc_reset(dst_oloc);
+ dst_oloc->file = file_dst;
+
+ /* Copy the shared object from source to destination */
+ if(H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
+
+ /* Update shared message info from named datatype info */
+ H5T_update_shared(attr_dst->shared->dt);
+ } /* end if */
+ else {
+ /* If the datatype is not named, it may have been shared in the
+ * source file's heap. Un-share it for now. We'll try to shared
+ * it in the destination file below.
+ */
+ if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing")
+ } /* end else */
+
+ /* Copy the dataspace for the attribute */
+ attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, FALSE, FALSE);
+ HDassert(attr_dst->shared->ds);
+
+ /* Reset the dataspace's sharing in the source file before trying to share
+ * it in the destination.
+ */
+ if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing")
+
+
+ /* Try to share both the datatype and dataset. This does nothing if the
+ * datatype is committed or sharing is disabled.
+ */
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype")
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace")
+
+ /* Compute the sizes of the datatype and dataspace. This is their raw
+ * size unless they're shared.
+ */
+ attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->shared->dt);
+ HDassert(attr_dst->shared->dt_size > 0);
+ attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->shared->ds);
+ HDassert(attr_dst->shared->ds_size > 0);
+
+ /* Check whether to recompute the size of the attribute */
+ /* (happens when the datatype or dataspace changes sharing status) */
+ if(attr_dst->shared->dt_size != attr_src->shared->dt_size || attr_dst->shared->ds_size != attr_src->shared->ds_size)
+ *recompute_size = TRUE;
+
+ /* Compute the size of the data */
+ H5_ASSIGN_OVERFLOW(attr_dst->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds) * H5T_get_size(attr_dst->shared->dt), hsize_t, size_t);
+
+ /* Copy (& convert) the data, if necessary */
+ if(attr_src->shared->data) {
+ if(NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Check if we need to convert data */
+ if(H5T_detect_class(attr_src->shared->dt, H5T_VLEN) > 0) {
+ H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */
+ H5T_t *dt_mem; /* Memory datatype */
+ size_t src_dt_size; /* Source datatype size */
+ size_t tmp_dt_size; /* Temp. datatype size */
+ size_t max_dt_size; /* Max atatype size */
+ H5S_t *buf_space; /* Dataspace describing buffer */
+ hsize_t buf_dim; /* Dimension for buffer */
+ size_t nelmts; /* Number of elements in buffer */
+ size_t buf_size; /* Size of copy buffer */
+
+ /* Create datatype ID for src datatype */
+ if((tid_src = H5I_register(H5I_DATATYPE, attr_src->shared->dt, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source file datatype")
+
+ /* create a memory copy of the variable-length datatype */
+ if(NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register memory datatype")
+
+ /* create variable-length datatype at the destinaton file */
+ if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->shared->dt, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination file datatype")
+
+ /* Set up the conversion functions */
+ if(NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and mem datatypes")
+ if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between mem and dst datatypes")
+
+ /* Determine largest datatype size */
+ if(0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
+ if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
+ max_dt_size = MAX(src_dt_size, tmp_dt_size);
+ if(0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
+ max_dt_size = MAX(max_dt_size, tmp_dt_size);
+
+ /* Set number of whole elements that fit in buffer */
+ if(0 == (nelmts = attr_src->shared->data_size / src_dt_size))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large")
+
+ /* Set up number of bytes to copy, and initial buffer size */
+ buf_size = nelmts * max_dt_size;
+
+ /* Create dataspace for number of elements in buffer */
+ buf_dim = nelmts;
+
+ /* Create the space and set the initial extent */
+ if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
+
+ /* Atomize */
+ if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
+ H5S_close(buf_space);
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, NULL, "unable to register dataspace ID")
+ } /* end if */
+
+ /* Allocate memory for recclaim buf */
+ if(NULL == (reclaim_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
+
+ /* Allocate memory for copying the chunk */
+ if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
+
+ HDmemcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
+
+ /* Convert from source file to memory */
+ if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
+
+ HDmemcpy(reclaim_buf, buf, buf_size);
+
+ /* Convert from memory to destination file */
+ if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
+
+ HDmemcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
+
+ if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
+ } /* end if */
+ else {
+ HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
+ HDmemcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
+ } /* end else */
+ } /* end if(attr_src->shared->data) */
+
+ /* Recompute the version to encode the destination attribute */
+ if(H5A_set_version(file_dst, attr_dst) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
+
+ /* Indicate that the fill values aren't to be written out */
+ attr_dst->shared->initialized = TRUE;
+
+ /* Set return value */
+ ret_value = attr_dst;
+
+done:
+ if(buf_sid > 0)
+ if(H5I_dec_ref(buf_sid, FALSE) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary dataspace ID")
+ if(tid_src > 0)
+ /* Don't decrement ID, we want to keep underlying datatype */
+ if(H5I_remove(tid_src) == NULL)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
+ if(tid_dst > 0)
+ /* Don't decrement ID, we want to keep underlying datatype */
+ if(H5I_remove(tid_dst) == NULL)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
+ if(tid_mem > 0)
+ /* Decrement the memory datatype ID, it's transient */
+ if(H5I_dec_ref(tid_mem, FALSE) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
+ if(buf)
+ buf = H5FL_BLK_FREE(attr_buf, buf);
+ if(reclaim_buf)
+ reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
+
+ /* Release destination attribute information on failure */
+ if(!ret_value && attr_dst && H5A_close(attr_dst) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_attr_copy_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_post_copy_file
+ *
+ * Purpose: Finish copying a message from between files.
+ * We have to copy the values of a reference attribute in the
+ * post copy because H5O_post_copy_file() fails at the case that
+ * an object may have a reference attribute that points to the
+ * object itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Peter Cao
+ * March 6, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t UNUSED *attr_src,
+ H5O_loc_t *dst_oloc, H5A_t *attr_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+{
+ H5F_t *file_src = src_oloc->file;
+ H5F_t *file_dst = dst_oloc->file;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_attr_post_copy_file)
+
+ /* check args */
+ HDassert(attr_dst);
+ HDassert(file_dst);
+
+
+ /* Only need to fix reference attribute with real data being copied to
+ * another file.
+ */
+ if((NULL != attr_dst->shared->data) && (H5T_get_class(attr_dst->shared->dt, FALSE) == H5T_REFERENCE) ) {
+
+ /* copy object pointed by reference. The current implementation does not
+ * deal with nested reference such as reference in a compound structure
+ */
+
+ /* Check for expanding references */
+ if(cpy_info->expand_ref) {
+ size_t ref_count;
+
+ /* Determine # of reference elements to copy */
+ ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
+
+ /* Copy objects referenced in source buffer to destination file and set destination elements */
+ if(H5O_copy_expand_ref(file_src, attr_dst->shared->data, dxpl_id,
+ file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_dst->shared->dt), cpy_info) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
+ } /* end if */
+ else
+ /* Reset value to zero */
+ HDmemset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_attr_post_copy_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_copy_file_cb
+ *
+ * Purpose: Callback routine for copying a dense attribute from SRC to DST.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Peter Cao
+ * xcao@hdfgroup.org
+ * July 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_copy_file_cb(const H5A_t *attr_src, void *_udata)
+{
+ H5A_dense_file_cp_ud_t *udata = (H5A_dense_file_cp_ud_t *)_udata;
+ H5A_t *attr_dst = NULL;
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_copy_file_cb)
+
+ /* check arguments */
+ HDassert(attr_src);
+ HDassert(udata);
+ HDassert(udata->ainfo);
+ HDassert(udata->file);
+ HDassert(udata->cpy_info);
+
+ if ( NULL == (attr_dst=H5A_attr_copy_file(attr_src, udata->file,
+ udata->recompute_size, udata->cpy_info, udata->dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+
+ /* Reset shared location information */
+ if(H5O_msg_reset_share(H5O_ATTR_ID, attr_dst) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to reset attribute sharing")
+
+ /* Insert attribute into dense storage */
+ if(H5A_dense_insert(udata->file, udata->dxpl_id, udata->ainfo, attr_dst) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
+
+done:
+ if (attr_dst) {
+ (void)H5A_free(attr_dst);
+ H5FL_FREE(H5A_t, attr_dst);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_copy_file_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_copy_file_all
+ *
+ * Purpose: Copy all dense attributes from SRC to DST.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Peter Cao
+ * xcao@hdfgroup.org
+ * July 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_copy_file_all(H5F_t *file_src, H5O_ainfo_t *ainfo_src, H5F_t *file_dst,
+ H5O_ainfo_t *ainfo_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, hid_t dxpl_id)
+{
+ H5A_dense_file_cp_ud_t udata; /* User data for iteration callback */
+ H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_copy_file_all)
+
+ /* check arguments */
+ HDassert(ainfo_src);
+ HDassert(ainfo_dst);
+
+ udata.ainfo = ainfo_dst; /* Destination dense information */
+ udata.file = file_dst; /* Destination file */
+ udata.recompute_size = recompute_size; /* Flag to indicate if size changed */
+ udata.cpy_info = cpy_info; /* Information on copying options */
+ udata.dxpl_id = dxpl_id; /* DXPL for operation */
+
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ attr_op.u.lib_op = H5A_dense_copy_file_cb;
+
+ if(H5A_dense_iterate(file_src, dxpl_id, (hid_t)0, ainfo_src, H5_INDEX_NAME,
+ H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_post_copy_file_cb
+ *
+ * Purpose: Callback routine to perfom post copy for a dense attribute.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Peter Cao
+ * xcao@hdfgroup.org
+ * July 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_post_copy_file_cb(const H5A_t *attr_dst, void *_udata)
+{
+ H5A_dense_file_cp_ud_t *udata = (H5A_dense_file_cp_ud_t *)_udata;
+ H5A_t *attr_src = NULL;
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_post_copy_file_cb)
+
+ /* check arguments */
+ HDassert(attr_dst);
+ HDassert(udata);
+ HDassert(udata->ainfo);
+ HDassert(udata->file);
+ HDassert(udata->cpy_info);
+
+ if ( H5A_attr_post_copy_file(udata->oloc_src, NULL,
+ udata->oloc_dst, attr_dst, udata->dxpl_id, udata->cpy_info) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_post_copy_file_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_post_copy_file_all
+ *
+ * Purpose: Do post copy for all dense attributes.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Peter Cao
+ * xcao@hdfgroup.org
+ * July 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo_src,
+ H5O_loc_t *dst_oloc, H5O_ainfo_t *ainfo_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+{
+ H5A_dense_file_cp_ud_t udata; /* User data for iteration callback */
+ H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_post_copy_file_all)
+
+ /* check arguments */
+ HDassert(ainfo_src);
+ HDassert(ainfo_dst);
+ HDassert(src_oloc);
+ HDassert(dst_oloc);
+ HDassert(src_oloc->file);
+ HDassert(dst_oloc->file);
+
+ udata.ainfo = ainfo_src;
+ udata.file = src_oloc->file;
+ udata.cpy_info = cpy_info; /* Information on copying options */
+ udata.dxpl_id = dxpl_id; /* DXPL for operation */
+ udata.oloc_src = src_oloc;
+ udata.oloc_dst = dst_oloc;
+
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ attr_op.u.lib_op = H5A_dense_post_copy_file_cb;
+
+ if(H5A_dense_iterate(dst_oloc->file, dxpl_id, (hid_t)0, ainfo_dst, H5_INDEX_NAME,
+ H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index a1b5e62..f66fa77 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -279,6 +279,15 @@ H5_DLL htri_t H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL int H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+H5_DLL H5A_t *H5A_attr_copy_file(H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_size,
+ H5O_copy_t *cpy_info, hid_t dxpl_id);
+H5_DLL herr_t H5A_attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *mesg_src,
+ H5O_loc_t *dst_oloc, H5A_t *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+H5_DLL herr_t H5A_dense_copy_file_all(H5F_t *file_src, H5O_ainfo_t *ainfo_src, H5F_t *file_dst,
+ H5O_ainfo_t *ainfo_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, hid_t dxpl_id);
+H5_DLL herr_t H5A_dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t * ainfo_src,
+ H5O_loc_t *dst_oloc, H5O_ainfo_t *ainfo_dst, hid_t dxpl_id, H5O_copy_t *cpy_info);
+
/* Testing functions */
#ifdef H5A_TESTING
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index 2a9d403..7f6a55d 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -48,6 +48,9 @@ static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src,
static void *H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src,
H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata,
hid_t dxpl_id);
+static herr_t H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc,
+ const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id,
+ H5O_copy_t *cpy_info);
static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
FILE * stream, int indent, int fwidth);
@@ -69,7 +72,7 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{
NULL, /*can share method */
H5O_ainfo_pre_copy_file, /* pre copy native value to file */
H5O_ainfo_copy_file, /* copy native value to file */
- NULL, /* post copy native value to file */
+ H5O_ainfo_post_copy_file, /* post copy native value to file */
NULL, /* get creation index */
NULL, /* set creation index */
H5O_ainfo_debug /*debug the message */
@@ -393,15 +396,14 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src,
* Return: Success: Ptr to _DEST
* Failure: NULL
*
- * Programmer: Quincey Koziol
- * March 9, 2007
+ * Programmer: Peter Cao
+ * July 18, 2007
*
*-------------------------------------------------------------------------
*/
static void *
-H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src,
- H5F_t UNUSED *file_dst, hbool_t UNUSED *recompute_size,
- H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id)
+H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
+ hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
{
H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
H5O_ainfo_t *ainfo_dst = NULL;
@@ -416,10 +418,6 @@ H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src,
HDassert(cpy_info);
HDassert(!cpy_info->copy_without_attr);
-/* XXX: Bail out for now, if the source object has densely stored attributes */
- if(H5F_addr_defined(ainfo_src->fheap_addr))
- HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, NULL, "densely stored attributes not supported yet")
-
/* Allocate space for the destination message */
if(NULL == (ainfo_dst = H5FL_MALLOC(H5O_ainfo_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
@@ -427,6 +425,16 @@ H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src,
/* Copy the top level of the information */
*ainfo_dst = *ainfo_src;
+ if(H5F_addr_defined(ainfo_src->fheap_addr)) {
+ /* copy dense attribute */
+
+ if(H5A_dense_create(file_dst, dxpl_id, ainfo_dst) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")
+
+ if ( (H5A_dense_copy_file_all(file_src, ainfo_src, file_dst, ainfo_dst, recompute_size, cpy_info, dxpl_id)) <0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")
+ }
+
/* Set return value */
ret_value = ainfo_dst;
@@ -440,6 +448,44 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_ainfo_post_copy_file
+ *
+ * Purpose: Finish copying a message from between files.
+ * We have to copy the values of a reference attribute in the
+ * post copy because H5O_post_copy_file() fails at the case that
+ * an object may have a reference attribute that points to the
+ * object itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Peter Cao
+ * July 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
+ H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
+{
+ H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_ainfo_post_copy_file)
+
+ HDassert(ainfo_src);
+
+ if(H5F_addr_defined(ainfo_src->fheap_addr)) {
+ if ( H5A_dense_post_copy_file_all(src_oloc, ainfo_src, dst_oloc,
+ (H5O_ainfo_t *)mesg_dst, dxpl_id, cpy_info) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_ainfo_post_copy_file() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_ainfo_debug
*
* Purpose: Prints debugging info for a message.
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index 85b1ef3..db216ad 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -641,257 +641,20 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id)
{
- H5A_t *attr_src = (H5A_t *)native_src;
- H5A_t *attr_dst = NULL;
-
- /* for dataype conversion */
- hid_t tid_src = -1; /* Datatype ID for source datatype */
- hid_t tid_dst = -1; /* Datatype ID for destination datatype */
- hid_t tid_mem = -1; /* Datatype ID for memory datatype */
- void *buf = NULL; /* Buffer for copying data */
- void *reclaim_buf = NULL; /* Buffer for reclaiming data */
- hid_t buf_sid = -1; /* ID for buffer dataspace */
-
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_copy_file)
/* check args */
- HDassert(attr_src);
+ HDassert(native_src);
HDassert(file_dst);
HDassert(cpy_info);
HDassert(!cpy_info->copy_without_attr);
- /* Allocate space for the destination message */
- if(NULL == (attr_dst = H5FL_CALLOC(H5A_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Copy the top level of the attribute */
- *attr_dst = *attr_src;
-
- if(NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
-
- /* Don't have an opened group location for copy */
- H5O_loc_reset(&(attr_dst->shared->oloc));
- H5G_name_reset(&(attr_dst->path));
- attr_dst->obj_opened = FALSE;
-
- /* Reference count for the header message in the cache */
- attr_dst->shared->nrefs = 1;
-
- /* Copy attribute's name */
- attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
- HDassert(attr_dst->shared->name);
-
- /* Copy attribute's datatype */
- /* (Start destination datatype as transient, even if source is named) */
- if(NULL == (attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "cannot copy datatype")
-
- /* Set the location of the destination datatype */
- if(H5T_set_loc(attr_dst->shared->dt, file_dst, H5T_LOC_DISK) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk")
-
- /* Check for named datatype being copied */
- if(H5T_committed(attr_src->shared->dt)) {
- H5O_loc_t *src_oloc; /* Pointer to source datatype's object location */
- H5O_loc_t *dst_oloc; /* Pointer to dest. datatype's object location */
-
- /* Get group entries for source & destination */
- src_oloc = H5T_oloc(attr_src->shared->dt);
- HDassert(src_oloc);
- dst_oloc = H5T_oloc(attr_dst->shared->dt);
- HDassert(dst_oloc);
-
- /* Reset object location for new object */
- H5O_loc_reset(dst_oloc);
- dst_oloc->file = file_dst;
-
- /* Copy the shared object from source to destination */
- if(H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info, FALSE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
-
- /* Update shared message info from named datatype info */
- H5T_update_shared(attr_dst->shared->dt);
- } /* end if */
- else {
- /* If the datatype is not named, it may have been shared in the
- * source file's heap. Un-share it for now. We'll try to shared
- * it in the destination file below.
- */
- if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing")
- } /* end else */
-
- /* Copy the dataspace for the attribute */
- attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, FALSE, FALSE);
- HDassert(attr_dst->shared->ds);
-
- /* Reset the dataspace's sharing in the source file before trying to share
- * it in the destination.
- */
- if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing")
-
-
- /* Try to share both the datatype and dataset. This does nothing if the
- * datatype is committed or sharing is disabled.
- */
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype")
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace")
-
- /* Compute the sizes of the datatype and dataspace. This is their raw
- * size unless they're shared.
- */
- attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->shared->dt);
- HDassert(attr_dst->shared->dt_size > 0);
- attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->shared->ds);
- HDassert(attr_dst->shared->ds_size > 0);
-
- /* Check whether to recompute the size of the attribute */
- /* (happens when the datatype or dataspace changes sharing status) */
- if(attr_dst->shared->dt_size != attr_src->shared->dt_size || attr_dst->shared->ds_size != attr_src->shared->ds_size)
- *recompute_size = TRUE;
-
- /* Compute the size of the data */
- H5_ASSIGN_OVERFLOW(attr_dst->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds) * H5T_get_size(attr_dst->shared->dt), hsize_t, size_t);
-
- /* Copy (& convert) the data, if necessary */
- if(attr_src->shared->data) {
- if(NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Check if we need to convert data */
- if(H5T_detect_class(attr_src->shared->dt, H5T_VLEN) > 0) {
- H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */
- H5T_t *dt_mem; /* Memory datatype */
- size_t src_dt_size; /* Source datatype size */
- size_t tmp_dt_size; /* Temp. datatype size */
- size_t max_dt_size; /* Max atatype size */
- H5S_t *buf_space; /* Dataspace describing buffer */
- hsize_t buf_dim; /* Dimension for buffer */
- size_t nelmts; /* Number of elements in buffer */
- size_t buf_size; /* Size of copy buffer */
-
- /* Create datatype ID for src datatype */
- if((tid_src = H5I_register(H5I_DATATYPE, attr_src->shared->dt, FALSE)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source file datatype")
-
- /* create a memory copy of the variable-length datatype */
- if(NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
- if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register memory datatype")
-
- /* create variable-length datatype at the destinaton file */
- if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->shared->dt, FALSE)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination file datatype")
-
- /* Set up the conversion functions */
- if(NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and mem datatypes")
- if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between mem and dst datatypes")
-
- /* Determine largest datatype size */
- if(0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
- if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
- max_dt_size = MAX(src_dt_size, tmp_dt_size);
- if(0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
- max_dt_size = MAX(max_dt_size, tmp_dt_size);
-
- /* Set number of whole elements that fit in buffer */
- if(0 == (nelmts = attr_src->shared->data_size / src_dt_size))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large")
-
- /* Set up number of bytes to copy, and initial buffer size */
- buf_size = nelmts * max_dt_size;
-
- /* Create dataspace for number of elements in buffer */
- buf_dim = nelmts;
-
- /* Create the space and set the initial extent */
- if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
-
- /* Atomize */
- if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
- H5S_close(buf_space);
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, NULL, "unable to register dataspace ID")
- } /* end if */
-
- /* Allocate memory for recclaim buf */
- if(NULL == (reclaim_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
-
- /* Allocate memory for copying the chunk */
- if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
-
- HDmemcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
-
- /* Convert from source file to memory */
- if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
-
- HDmemcpy(reclaim_buf, buf, buf_size);
-
- /* Convert from memory to destination file */
- if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
-
- HDmemcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
-
- if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
- } /* end if */
- else {
- HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
- HDmemcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
- } /* end else */
- } /* end if(attr_src->shared->data) */
-
- /* Recompute the version to encode the destination attribute */
- if(H5A_set_version(file_dst, attr_dst) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
-
- /* Indicate that the fill values aren't to be written out */
- attr_dst->shared->initialized = TRUE;
-
- /* Set return value */
- ret_value = attr_dst;
+ if ( NULL == (ret_value=H5A_attr_copy_file((H5A_t *)native_src, file_dst, recompute_size, cpy_info, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy attribute")
done:
- if(buf_sid > 0)
- if(H5I_dec_ref(buf_sid, FALSE) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary dataspace ID")
- if(tid_src > 0)
- /* Don't decrement ID, we want to keep underlying datatype */
- if(H5I_remove(tid_src) == NULL)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
- if(tid_dst > 0)
- /* Don't decrement ID, we want to keep underlying datatype */
- if(H5I_remove(tid_dst) == NULL)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
- if(tid_mem > 0)
- /* Decrement the memory datatype ID, it's transient */
- if(H5I_dec_ref(tid_mem, FALSE) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
- if(buf)
- buf = H5FL_BLK_FREE(attr_buf, buf);
- if(reclaim_buf)
- reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
-
- /* Release destination attribute information on failure */
- if(!ret_value && attr_dst && H5A_close(attr_dst) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
-
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_attr_copy_file() */
@@ -916,48 +679,14 @@ static herr_t
H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info)
{
- const H5A_t *attr_src = (const H5A_t *)mesg_src;
- H5A_t *attr_dst = (H5A_t *)mesg_dst;
- H5F_t *file_src = src_oloc->file;
- H5F_t *file_dst = dst_oloc->file;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_post_copy_file)
- /* check args */
- HDassert(attr_src);
- HDassert(file_src);
- HDassert(attr_dst);
- HDassert(file_dst);
-
- /* Only need to fix reference attribute with real data being copied to
- * another file.
- */
- if((NULL != attr_src->shared->data) &&
- (H5T_get_class(attr_src->shared->dt, FALSE) == H5T_REFERENCE) &&
- (file_src != file_dst)) {
-
- /* copy object pointed by reference. The current implementation does not
- * deal with nested reference such as reference in a compound structure
- */
-
- /* Check for expanding references */
- if(cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
-
- /* Copy objects referenced in source buffer to destination file and set destination elements */
- if(H5O_copy_expand_ref(file_src, attr_src->shared->data, dxpl_id,
- file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_src->shared->dt), cpy_info) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
- } /* end if */
- else
- /* Reset value to zero */
- HDmemset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
- } /* end if */
+ if ( H5A_attr_post_copy_file(src_oloc, (const H5A_t *)mesg_src,
+ dst_oloc, (H5A_t *)mesg_dst, dxpl_id, cpy_info) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/test/objcopy.c b/test/objcopy.c
index aca041f..61963b5 100755
--- a/test/objcopy.c
+++ b/test/objcopy.c
@@ -55,7 +55,8 @@ const char *FILENAME[] = {
#define CONFIG_SHARE_SRC 1
#define CONFIG_SHARE_DST 2
#define CONFIG_NEW_FORMAT 4
-#define MAX_CONFIGURATION 7
+#define CONFIG_DENSE 8
+#define MAX_CONFIGURATION 15
#define FILE_EXT "objcopy_ext.dat"
/* The fill_old.h5 is generated from gen_old_fill.c in HDF5 'test' directory
@@ -69,6 +70,7 @@ const char *FILENAME[] = {
#define NAME_DATATYPE_VL "vlen of int"
#define NAME_DATATYPE_VL_VL "vlen of vlen of int"
#define NAME_DATASET_SIMPLE "dataset_simple"
+#define NAME_DATASET_SIMPLE2 "dataset_simple_copy"
#define NAME_DATASET_COMPOUND "dataset_compound"
#define NAME_DATASET_CHUNKED "dataset_chunked"
#define NAME_DATASET_COMPACT "dataset_compact"
@@ -104,7 +106,6 @@ const char *FILENAME[] = {
#define NAME_OLD_FORMAT "/dset1"
#define NAME_BUF_SIZE 1024
-#define NUM_ATTRIBUTES 4
#define ATTR_NAME_LEN 80
#define DIM_SIZE_1 12
#define DIM_SIZE_2 6
@@ -116,6 +117,8 @@ const char *FILENAME[] = {
char src_obj_full_name[215]; /* the full path + name of the object to be copied */
+int num_attributes_g; /* Number of attributes created */
+
/* Table containing object id and object name */
/* (Used for detecting duplicate objects when comparing groups */
static struct {
@@ -535,7 +538,7 @@ test_copy_attach_attributes(hid_t loc_id, hid_t type_id)
if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 )
goto done;
- for (i=0; i<NUM_ATTRIBUTES; i++) {
+ for (i=0; i<num_attributes_g; i++) {
sprintf(attr_name, "%d attr", i);
/* Set attribute data */
@@ -588,7 +591,7 @@ test_copy_attach_paired_attributes(hid_t loc_id, hid_t loc_id2, hid_t type_id)
if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 ) goto done;
- for (i=0; i<NUM_ATTRIBUTES; i++) {
+ for (i=0; i<num_attributes_g; i++) {
sprintf(attr_name, "%d attr", i);
/* Set attribute data */
@@ -1779,6 +1782,112 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_copy_dataset_simple_samefile
+ *
+ * Purpose: Create a simple dataset in SRC file and copy it to SRC file
+ *
+ * Return: Success: 0
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Thursday, January 15, 2009
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_copy_dataset_simple_samefile(hid_t fcpl, hid_t fapl, int config)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t did = -1, did2 = -1; /* Dataset IDs */
+ int buf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */
+ hsize_t dim2d[2]; /* Dataset dimensions */
+ int i, j; /* local index variables */
+ char filename[NAME_BUF_SIZE];
+
+ TESTING("H5Ocopy(): simple dataset within the same file");
+
+ /* Initialize write buffer */
+ for (i=0; i<DIM_SIZE_1; i++)
+ for (j=0; j<DIM_SIZE_2; j++)
+ buf[i][j] = 10000 + 100*i+j;
+
+ /* Initialize the filenames */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+
+ /* Reset file address checking info */
+ addr_reset();
+
+ /* create source file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) TEST_ERROR
+
+ /* Set dataspace dimensions */
+ dim2d[0] = DIM_SIZE_1;
+ dim2d[1] = DIM_SIZE_2;
+
+ /* create 2D dataspace */
+ if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR
+
+ /* create 2D int dataset at SRC file */
+ if((did = H5Dcreate2(fid, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* write data into file */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
+
+ /* close dataspace */
+ if(H5Sclose(sid) < 0) TEST_ERROR
+
+ /* attach attributes to the dataset */
+ if(test_copy_attach_attributes(did, H5T_NATIVE_INT) < 0) TEST_ERROR
+
+ /* close the dataset */
+ if(H5Dclose(did) < 0) TEST_ERROR
+
+ /* close the SRC file */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* open the source file with read-write */
+ if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR
+
+ /* copy the dataset from SRC to DST */
+ if(H5Ocopy(fid, NAME_DATASET_SIMPLE, fid, NAME_DATASET_SIMPLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* open the dataset for copy */
+ if((did = H5Dopen2(fid, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* open the destination dataset */
+ if((did2 = H5Dopen2(fid, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Check if the datasets are equal */
+ if(compare_datasets(did, did2, H5P_DEFAULT, buf) != TRUE) TEST_ERROR
+
+ /* close the destination dataset */
+ if(H5Dclose(did2) < 0) TEST_ERROR
+
+ /* close the source dataset */
+ if(H5Dclose(did) < 0) TEST_ERROR
+
+ /* close the SRC file */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Dclose(did2);
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_copy_dataset_simple_samefile */
+
+
+/*-------------------------------------------------------------------------
* Function: test_copy_dataset_simple_empty
*
* Purpose: Create a simple dataset in SRC file and copy it to DST file
@@ -7150,7 +7259,8 @@ main(void)
{
int nerrors = 0;
hid_t fapl, fapl2;
- hid_t fcpl_shared;
+ hid_t fcpl_shared, ocpl;
+ unsigned max_compact, min_dense;
int configuration; /* Configuration of tests. */
int ExpressMode;
@@ -7173,6 +7283,11 @@ main(void)
if(H5Pset_shared_mesg_nindexes(fcpl_shared, 1) < 0) TEST_ERROR
if(H5Pset_shared_mesg_index(fcpl_shared, 0, H5O_SHMESG_ALL_FLAG, (size_t) 10) < 0) TEST_ERROR
+ /* Obtain the default attribute storage phase change values */
+ if((ocpl = H5Pcreate(H5P_OBJECT_CREATE)) < 0) TEST_ERROR
+ if(H5Pget_attr_phase_change(ocpl, &max_compact, &min_dense) < 0) TEST_ERROR
+ if(H5Pclose(ocpl) < 0) TEST_ERROR
+
/* Test in all configurations */
for(configuration = 0; configuration <= MAX_CONFIGURATION; configuration++) {
hid_t my_fapl;
@@ -7207,40 +7322,29 @@ main(void)
my_fapl = fapl;
} /* end else */
+ /* Test with and without dense attributes */
+ if(configuration & CONFIG_DENSE) {
+ puts("Testing with dense attributes:");
+ num_attributes_g = max_compact + 1;
+ }
+ else {
+ puts("Testing without dense attributes:");
+ num_attributes_g = MAX(min_dense, 2) - 1;
+ }
/* The tests... */
- nerrors += test_copy_named_datatype(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_named_datatype_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_named_datatype_vl_vl(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_simple(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_simple_samefile(fcpl_src, my_fapl, configuration);
nerrors += test_copy_dataset_simple_empty(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compound(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_chunked(fcpl_src, fcpl_dst, my_fapl);
-
nerrors += test_copy_dataset_chunked_empty(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_chunked_sparse(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compressed(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_compact(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_external(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_named_dtype(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_named_dtype_hier(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_named_dtype_hier_outside(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_multi_ohdr_chunks(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_dataset_attr_named_dtype(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_contig_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_chunked_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compact_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compressed_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_attribute_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compact_named_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_contig_named_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_chunked_named_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compressed_named_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compact_vl_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_contig_vl_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_chunked_vl_vl(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_dataset_compressed_vl_vl(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_group_empty(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_root_group(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_group(fcpl_src, fcpl_dst, my_fapl);
@@ -7254,8 +7358,7 @@ main(void)
#endif /* H5_CANNOT_OPEN_TWICE */
nerrors += test_copy_exist(fcpl_src, fcpl_dst, my_fapl);
nerrors += test_copy_path(fcpl_src, fcpl_dst, my_fapl);
- nerrors += test_copy_same_file_named_datatype(fcpl_src, my_fapl);
- nerrors += test_copy_old_layout(fcpl_dst, my_fapl);
+
nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_WITHOUT_ATTR_FLAG,
FALSE, "H5Ocopy(): without attributes");
nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, 0, TRUE,
@@ -7271,6 +7374,36 @@ main(void)
nerrors += test_copy_option(fcpl_src, fcpl_dst, my_fapl, H5O_COPY_WITHOUT_ATTR_FLAG |
H5O_COPY_PRESERVE_NULL_FLAG, TRUE, "H5Ocopy(): preserve NULL messages");
+ /* Tests that do not use attributes and do not need to be tested
+ * multiple times for different attribute configurations */
+ if(configuration < CONFIG_DENSE) {
+ nerrors += test_copy_named_datatype(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_named_datatype_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_named_datatype_vl_vl(fcpl_src, fcpl_dst, my_fapl);
+
+ nerrors += test_copy_dataset_external(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_named_dtype(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_named_dtype_hier(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_named_dtype_hier_outside(fcpl_src, fcpl_dst, my_fapl);
+
+ nerrors += test_copy_dataset_contig_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_chunked_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compact_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compressed_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_attribute_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compact_named_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_contig_named_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_chunked_named_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compressed_named_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compact_vl_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_contig_vl_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_chunked_vl_vl(fcpl_src, fcpl_dst, my_fapl);
+ nerrors += test_copy_dataset_compressed_vl_vl(fcpl_src, fcpl_dst, my_fapl);
+
+ nerrors += test_copy_same_file_named_datatype(fcpl_src, my_fapl);
+ nerrors += test_copy_old_layout(fcpl_dst, my_fapl);
+ }
+
/* 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);