diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2011-10-14 00:03:09 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2011-10-14 00:03:09 (GMT) |
commit | 363988bd77243b36c6324734b3a985c4fe07f650 (patch) | |
tree | fb23cc6accc028589d934362d56fad83a7e3b947 | |
parent | 682a4f2b5d383d6abf6741a4a5a573f1c67e668e (diff) | |
download | hdf5-363988bd77243b36c6324734b3a985c4fe07f650.zip hdf5-363988bd77243b36c6324734b3a985c4fe07f650.tar.gz hdf5-363988bd77243b36c6324734b3a985c4fe07f650.tar.bz2 |
[svn-r21557] Port r21556 to 1.8 branch
Purpose: Fix bug in H5Ocopy
Description:
H5Ocopy could get confused when copying a named datatype containing an
attribute which used that named datatype as its datatype. This happened
because H5Ocopy would recurse into the attribute's datatype before the object
the attribute was in was fully copied (i.e. before the "post-copy" pass).
Modified H5Ocopy to avoid recursing before the post-copy step in this case.
Required many changes, including to how non-committed shared messages are
copied.
Tested: jam, koala, heiwa (h5committest); durandal
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5A.c | 4 | ||||
-rw-r--r-- | src/H5Adense.c | 2 | ||||
-rw-r--r-- | src/H5Aint.c | 186 | ||||
-rw-r--r-- | src/H5Apkg.h | 2 | ||||
-rw-r--r-- | src/H5Oainfo.c | 15 | ||||
-rw-r--r-- | src/H5Oattribute.c | 2 | ||||
-rw-r--r-- | src/H5Ocopy.c | 12 | ||||
-rw-r--r-- | src/H5Odtype.c | 2 | ||||
-rw-r--r-- | src/H5Ofill.c | 4 | ||||
-rw-r--r-- | src/H5Omessage.c | 8 | ||||
-rw-r--r-- | src/H5Opline.c | 2 | ||||
-rw-r--r-- | src/H5Osdspace.c | 2 | ||||
-rw-r--r-- | src/H5Oshared.c | 22 | ||||
-rw-r--r-- | src/H5Oshared.h | 9 | ||||
-rw-r--r-- | src/H5Ounknown.c | 2 | ||||
-rwxr-xr-x | src/H5SM.c | 266 | ||||
-rwxr-xr-x | src/H5SMprivate.h | 2 | ||||
-rwxr-xr-x | test/objcopy.c | 150 |
19 files changed, 410 insertions, 285 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index a84793b..129f612 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -115,6 +115,9 @@ Bug Fixes since HDF5-1.8.7 Library ------- + - Fixed a bug that occurred when using H5Ocopy on a committed datatype + containing an attribute using that committed datatype. + (NAF - 2011/10/13 - Issue 5854) - #ifdef _WIN32 instances have been changed to #ifdef H5_HAVE_WIN32_API. H5_HAVE_VISUAL_STUDIO checks have been added where necessary. This is in CMake only as configure never sets _WIN32. (ADB - 2011/09/12) @@ -451,9 +451,9 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, /* Check if any of the pieces should be (or are already) shared in the * SOHM table */ - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0) + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, FALSE, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed") - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0) + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, FALSE, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed") /* Check whether datatype is committed & increment ref count diff --git a/src/H5Adense.c b/src/H5Adense.c index 889889e..6724736 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -470,7 +470,7 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr) mesg_flags |= H5O_MSG_FLAG_SHARED; else { /* Should this attribute be written as a SOHM? */ - if(H5SM_try_share(f, dxpl_id, NULL, H5O_ATTR_ID, attr, &mesg_flags) < 0) + if(H5SM_try_share(f, dxpl_id, NULL, FALSE, H5O_ATTR_ID, attr, &mesg_flags) < 0) HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared") /* Attributes can't be "unique be shareable" yet */ diff --git a/src/H5Aint.c b/src/H5Aint.c index 123f265..3f00c76 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -863,37 +863,14 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si 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, - NULL, NULL) < 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(!H5T_committed(attr_src->shared->dt)) { /* 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 */ + } /* end if */ /* Copy the dataspace for the attribute. Make sure the maximal dimension is also copied. * Otherwise the comparison in the test may complain about it. SLU 2011/4/12 */ @@ -906,13 +883,13 @@ H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_si 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) + /* Use try_share_virtual and move try_share to post copy? -NAF */ + if(H5SM_try_share(file_dst, dxpl_id, NULL, FALSE, 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) + if(H5SM_try_share(file_dst, dxpl_id, NULL, FALSE, 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 @@ -1081,20 +1058,47 @@ done: *------------------------------------------------------------------------- */ herr_t -H5A_attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t UNUSED *attr_src, +H5A_attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src, H5O_loc_t *dst_oloc, const 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; + H5F_t *file_src, *file_dst; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5A_attr_post_copy_file) /* check args */ + HDassert(src_oloc); + HDassert(dst_oloc); HDassert(attr_dst); + HDassert(attr_src); + + file_src = src_oloc->file; + file_dst = dst_oloc->file; + + HDassert(file_src); HDassert(file_dst); + if(H5T_committed(attr_src->shared->dt)) { + H5O_loc_t *src_oloc_dt; /* Pointer to source datatype's object location */ + H5O_loc_t *dst_oloc_dt; /* Pointer to dest. datatype's object location */ + + /* Get group entries for source & destination */ + src_oloc_dt = H5T_oloc(attr_src->shared->dt); + HDassert(src_oloc_dt); + dst_oloc_dt = H5T_oloc(attr_dst->shared->dt); + HDassert(dst_oloc_dt); + + /* Reset object location for new object */ + H5O_loc_reset(dst_oloc_dt); + dst_oloc_dt->file = file_dst; + + /* Copy the shared object from source to destination */ + if(H5O_copy_header_map(src_oloc_dt, dst_oloc_dt, dxpl_id, cpy_info, FALSE, NULL, NULL) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Update shared message info from named datatype info */ + H5T_update_shared(attr_dst->shared->dt); + } /* end if */ /* Only need to fix reference attribute with real data being copied to * another file. @@ -1128,7 +1132,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_dense_copy_file_cb + * Function: H5A_dense_post_copy_file_cb * * Purpose: Callback routine for copying a dense attribute from SRC to DST. * @@ -1142,13 +1146,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5A_dense_copy_file_cb(const H5A_t *attr_src, void *_udata) +H5A_dense_post_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) + FUNC_ENTER_NOAPI_NOINIT(H5A_dense_post_copy_file_cb) /* check arguments */ HDassert(attr_src); @@ -1161,6 +1165,10 @@ H5A_dense_copy_file_cb(const H5A_t *attr_src, void *_udata) udata->recompute_size, udata->cpy_info, udata->dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") + if(H5A_attr_post_copy_file(udata->oloc_src, attr_src, 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") + /* 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") @@ -1174,105 +1182,20 @@ done: HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close destination attribute") 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, - const 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) -} /* end H5A_dense_copy_file_all */ - - -/*------------------------------------------------------------------------- - * 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; - 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. + * Purpose: Copy all dense attributes from SRC to DST. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Peter Cao * xcao@hdfgroup.org - * July 25, 2007 + * July 20, 2007 * *------------------------------------------------------------------------- */ @@ -1281,21 +1204,19 @@ H5A_dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo 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 */ + H5A_attr_iter_op_t attr_op; /* Attribute operator */ + hbool_t recompute_size = FALSE; /* recompute the size */ + 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.ainfo = ainfo_dst; /* Destination dense information */ + udata.file = dst_oloc->file; /* 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 */ udata.oloc_src = src_oloc; @@ -1304,11 +1225,12 @@ H5A_dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo 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, + + if(H5A_dense_iterate(src_oloc->file, 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) -} +} /* end H5A_dense_post_copy_file_all */ diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 27f500e..20aa5b9 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -283,8 +283,6 @@ H5_DLL H5A_t *H5A_attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t 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, const 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, - const 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); diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index 158f795..20ebf26 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -403,7 +403,7 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_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 UNUSED *udata, hid_t dxpl_id) + hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) { H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src; H5O_ainfo_t *ainfo_dst = NULL; @@ -430,9 +430,6 @@ H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, 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") } /* end if */ /* Set return value */ @@ -452,7 +449,7 @@ done: * * 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 + * post copy because H5O_post_copy_file() fails in the case that * an object may have a reference attribute that points to the * object itself. * @@ -475,10 +472,10 @@ H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, 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") - } + 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") + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 4cb6afc..a5facbc 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -796,7 +796,7 @@ H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5A_t *attr, /* Store new version of message as a SOHM */ /* (should always work, since we're not changing the size of the attribute) */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, H5O_ATTR_ID, attr, NULL)) == 0) + if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, FALSE, H5O_ATTR_ID, attr, NULL)) == 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "attribute changed sharing status") else if(shared_mesg < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't share attribute") diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index fcca34a..45ca431 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -688,6 +688,12 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, 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") + /* Insert destination object header in cache. Insert before post copy loop + * so anything that references this object header can find it. Insert + * pinned so we can continue using oh_dst. */ + if(H5AC_insert_entry(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, H5AC__PIN_ENTRY_FLAG) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header") + /* "post copy" loop over messages, to fix up any messages which require a complete * object header for destination object */ @@ -738,9 +744,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, oh_dst->nlink += (unsigned)addr_map->inc_ref_count; } /* end if */ - /* Insert destination object header in cache */ - if(H5AC_insert_entry(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header") + /* Unpin oh_dst */ + if(H5AC_unpin_entry(oh_dst) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "can't unpin object header") oh_dst = NULL; /* Set obj_type and udata, if requested */ diff --git a/src/H5Odtype.c b/src/H5Odtype.c index f419e44..39c97cb 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -104,7 +104,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ H5O_dtype_can_share, /* can share method */ H5O_dtype_pre_copy_file, /* pre copy native value to file */ H5O_dtype_shared_copy_file, /* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_dtype_shared_post_copy_file, /* post copy native value to file */ NULL, /* get creation index */ NULL, /* set creation index */ H5O_dtype_shared_debug /* debug the message */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index c7c743a..f333410 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -120,7 +120,7 @@ const H5O_msg_class_t H5O_MSG_FILL[1] = {{ NULL, /*can share method */ NULL, /* pre copy native value to file */ H5O_fill_shared_copy_file, /* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_fill_shared_post_copy_file, /* post copy native value to file */ NULL, /* get creation index */ NULL, /* set creation index */ H5O_fill_shared_debug /*debug the message */ @@ -144,7 +144,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ NULL, /*can share method */ NULL, /* pre copy native value to file */ H5O_fill_new_shared_copy_file, /* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_fill_new_shared_post_copy_file, /* post copy native value to file */ NULL, /* get creation index */ NULL, /* set creation index */ H5O_fill_new_shared_debug /*debug the message */ diff --git a/src/H5Omessage.c b/src/H5Omessage.c index c151e5b..e2d3ac4 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -419,7 +419,7 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty * XXX: This doesn't handle freeing extra space in object header from * a message shrinking. */ - if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), idx_msg->type->id, mesg, &mesg_flags)) < 0) + if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), FALSE, idx_msg->type->id, mesg, &mesg_flags)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message") if(status == FALSE && (mesg_flags & H5O_MSG_FLAG_SHARED)) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status") @@ -1546,6 +1546,10 @@ H5O_msg_can_share(unsigned type_id, const void *mesg) ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE; } /* end else */ + /* If the message is shareable, both copy_file and post_copy_file must be + * defined */ + HDassert((type->post_copy_file && type->copy_file) || ret_value == FALSE); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_msg_can_share() */ @@ -1928,7 +1932,7 @@ H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type, } /* end if */ else { /* Attempt to share message */ - if(H5SM_try_share(f, dxpl_id, oh, type->id, native, mesg_flags) < 0) + if(H5SM_try_share(f, dxpl_id, oh, FALSE, type->id, native, mesg_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared") } /* end else */ diff --git a/src/H5Opline.c b/src/H5Opline.c index 89bdd36..518bcdf 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -83,7 +83,7 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ NULL, /*can share method */ H5O_pline_pre_copy_file, /* pre copy native value to file */ H5O_pline_shared_copy_file, /* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_pline_shared_post_copy_file, /* post copy native value to file */ NULL, /* get creation index */ NULL, /* set creation index */ H5O_pline_shared_debug /* debug the message */ diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 323bec9..62d5b63 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -77,7 +77,7 @@ const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{ NULL, /*can share method */ H5O_sdspace_pre_copy_file, /* pre copy native value to file */ H5O_sdspace_shared_copy_file,/* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_sdspace_shared_post_copy_file,/* post copy native value to file */ NULL, /* get creation index */ NULL, /* set creation index */ H5O_sdspace_shared_debug /* debug the message */ diff --git a/src/H5Oshared.c b/src/H5Oshared.c index ac33702..432151c 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -285,7 +285,7 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, } /* end if */ /* Check for incrementing reference count on message */ else if(adjust > 0) { - if(H5SM_try_share(f, dxpl_id, open_oh, type->id, shared, NULL) < 0) + if(H5SM_try_share(f, dxpl_id, open_oh, FALSE, type->id, shared, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "error trying to share message") } /* end if */ } /* end else */ @@ -610,7 +610,11 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, /* Committed shared messages create a shared message at the destination * and also copy the committed object that they point to. * - * SOHMs try to share the destination message. + * Other messages simulate sharing the destination message to determine how + * it will eventually be shared (if at all), but do not actually share the + * message until "post copy". The "H5O_shared_t" part of the message will + * be updated (to allow calculation of the final size) but the message is + * not actually shared. */ if(shared_src->type == H5O_SHARE_TYPE_COMMITTED) { H5O_loc_t dst_oloc; @@ -628,11 +632,8 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, dst_oloc.addr) } /* end if */ else { - /* Try to share new message in the destination file. */ - /* Message is always shared in heap in dest. file because the dest. - * object header doesn't quite exist yet - JML - */ - if(H5SM_try_share(file_dst, dxpl_id, NULL, mesg_type->id, _native_dst, NULL) < 0) + /* Simulate trying to share new message in the destination file. */ + if(H5SM_try_share(file_dst, dxpl_id, NULL, TRUE, mesg_type->id, _native_dst, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared") } /* end else */ @@ -679,12 +680,8 @@ H5O_shared_post_copy_file(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *mesg) /* save the type id for later use */ msg_type_id = old_sh_mesg->msg_type_id; - /* Remove the old message from the SOHM storage */ - if(H5SM_delete(f, dxpl_id, oh, old_sh_mesg) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to find attribute information for object") - /* Add the new message */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, msg_type_id, mesg, NULL)) == 0) + if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, FALSE, msg_type_id, mesg, NULL)) == 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status") else if(shared_mesg < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message") @@ -693,7 +690,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_post_copy_file() */ - /*------------------------------------------------------------------------- * Function: H5O_shared_debug diff --git a/src/H5Oshared.h b/src/H5Oshared.h index c0f5cd6..569889d 100644 --- a/src/H5Oshared.h +++ b/src/H5Oshared.h @@ -408,11 +408,14 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy native message to another file") #endif /* H5O_SHARED_POST_COPY_FILE_REAL */ - /* update only shared message after the post copy */ - if(H5O_msg_is_shared(shared_dst->msg_type_id, mesg_dst)) { + /* Update only shared message after the post copy. Do not update committed + * messages as they have already been dealt with in the copy pass. + * (Move copy of target of committed messages to post copy? -NAF) */ + if(shared_dst->type == H5O_SHARE_TYPE_SOHM + || shared_dst->type == H5O_SHARE_TYPE_HERE) { if(H5O_shared_post_copy_file(oloc_dst->file, dxpl_id, cpy_info->oh_dst, mesg_dst) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to fix shared message in post copy") - } + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Ounknown.c b/src/H5Ounknown.c index d4a3801..68bb64b 100644 --- a/src/H5Ounknown.c +++ b/src/H5Ounknown.c @@ -40,7 +40,7 @@ const H5O_msg_class_t H5O_MSG_UNKNOWN[1] = {{ H5O_UNKNOWN_ID, /*message id number */ "unknown", /*message name for debugging */ 0, /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ NULL, /*decode message */ NULL, /*encode message */ NULL, /*copy the native value */ @@ -65,7 +65,7 @@ static herr_t H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header static herr_t H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_id); static herr_t H5SM_incr_ref(void *record, void *_op_data, hbool_t *changed); static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, - H5SM_index_header_t *header, unsigned type_id, void *mesg, + H5SM_index_header_t *header, hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr); static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed); static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, @@ -988,6 +988,10 @@ done: * header it needs (which can cause an error if that OH is * already protected!). * + * The DEFER flag indicates whether the sharing operation + * should actually occur, or whether this is just a set up call + * for a future sharing operation. + * * MESG_FLAGS will have the H5O_MSG_FLAG_SHAREABLE or * H5O_MSG_FLAG_SHARED flag set if one is appropriate. This is * the only way to tell the difference between a message that @@ -1025,8 +1029,8 @@ done: *------------------------------------------------------------------------- */ htri_t -H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, - void *mesg, unsigned *mesg_flags) +H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, hbool_t defer, + unsigned type_id, void *mesg, unsigned *mesg_flags) { H5SM_master_table_t *table = NULL; H5SM_table_cache_ud_t cache_udata; /* User-data for callback */ @@ -1071,13 +1075,13 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, * message to become shared (if it is unique, it will not be shared). */ if(H5SM_write_mesg(f, dxpl_id, open_oh, &(table->indexes[index_num]), - type_id, mesg, &cache_flags) < 0) + defer, type_id, mesg, &cache_flags) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "can't write shared message") - /* Set flags if this message was "written" without error; it is now - * either fully shared or "shareable". + /* Set flags if this message was "written" without error and wasn't a + * 'defer' attempt; it is now either fully shared or "shareable". */ - if(mesg_flags) { + if(mesg_flags && !defer) { if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE) *mesg_flags |= H5O_MSG_FLAG_SHAREABLE; else @@ -1157,19 +1161,28 @@ done: /*------------------------------------------------------------------------- * Function: H5SM_write_mesg * - * Purpose: Adds a shareable message to an index. If this is the first - * such message and we have an object header location for this - * message, we record it in the index but don't modify the - * message passed in. - * - * If the message is already in the index or we don't have an - * object header location for it, it is shared in the heap - * and this function sets its sharing struct to reflect this. + * Purpose: This routine adds a shareable message to an index. + * The behavior is controlled by the DEFER parameter: + * + * If DEFER is TRUE, this routine Simulates adding a shareable + * message to an index. It determines what the outcome would + * be with DEFER set the FALSE and updates the shared message + * info, but does not actually add the message to a heap, list, + * or b-tree. Assumes that an open object header will be + * available when H5SM_write_mesg is called with DEFER set to + * FALSE. + * + * If DEFER is FALSE, this routine adds a shareable message to + * an index. If this is the first such message and we have an + * object header location for this message, we record it in the + * index but don't modify the message passed in. If the message + * is already in the index or we don't have an object header + * location for it, it is shared in the heap and this function + * sets its sharing struct to reflect this. * * The index could be a list or a B-tree. * - * Return: TRUE if message is now shared - * FALSE if message is in index but is not shared + * Return: Non-negative on success * Negative on failure * * Programmer: James Laird @@ -1179,7 +1192,7 @@ done: */ static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, - H5SM_index_header_t *header, unsigned type_id, void *mesg, + H5SM_index_header_t *header, hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr) { H5SM_list_t *list = NULL; /* List index */ @@ -1234,7 +1247,7 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, cache_udata.header = header; /* The index is a list; get it from the cache */ - if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC_WRITE))) + if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, defer ? H5AC_READ : H5AC_WRITE))) HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index") /* See if the message is already in the index and get its location. @@ -1242,55 +1255,75 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, * later. */ list_pos = H5SM_find_in_list(list, &key, &empty_pos); - if(list_pos != UFAIL) { - /* If the message was previously shared in an object header, share - * it in the heap now. - */ - if(list->messages[list_pos].location == H5SM_IN_OH) { - /* Put the message in the heap and record its new heap ID */ - if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - - list->messages[list_pos].location = H5SM_IN_HEAP; - list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id; - list->messages[list_pos].u.heap_loc.ref_count = 2; - } /* end if */ - else { - /* If the message was already in the heap, increase its ref count */ - HDassert(list->messages[list_pos].location == H5SM_IN_HEAP); - ++(list->messages[list_pos].u.heap_loc.ref_count); - } /* end else */ - - /* Set up the shared location to point to the shared location */ - shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id; - found = TRUE; + if(defer) { + if(list_pos != UFAIL) + found = TRUE; } /* end if */ + else { + if(list_pos != UFAIL) { + /* If the message was previously shared in an object header, share + * it in the heap now. + */ + if(list->messages[list_pos].location == H5SM_IN_OH) { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + + list->messages[list_pos].location = H5SM_IN_HEAP; + list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id; + list->messages[list_pos].u.heap_loc.ref_count = 2; + } /* end if */ + else { + /* If the message was already in the heap, increase its ref count */ + HDassert(list->messages[list_pos].location == H5SM_IN_HEAP); + ++(list->messages[list_pos].u.heap_loc.ref_count); + } /* end else */ + + /* Set up the shared location to point to the shared location */ + shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id; + found = TRUE; + } /* end if */ + } /* end else */ } /* end if */ /* Index is a B-tree */ else { - H5SM_incr_ref_opdata op_data; - HDassert(header->index_type == H5SM_BTREE); /* Open the index v2 B-tree */ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") - /* Set up callback info */ - op_data.key = &key; - op_data.dxpl_id = dxpl_id; + if(defer) { + htri_t bt2_find; /* Result from searching in the v2 B-tree */ - /* If this returns failure, it means that the message wasn't found. */ - /* If it succeeds, set the heap_id in the shared struct. It will - * return a heap ID, since a message with a reference count greater - * than 1 is always shared in the heap. - */ - if(H5B2_modify(bt2, dxpl_id, &key, H5SM_incr_ref, &op_data) >= 0) { - shared.u.heap_id = op_data.fheap_id; - found = TRUE; + /* If this returns 0, it means that the message wasn't found. */ + /* If it return 1, set the heap_id in the shared struct. It will + * return a heap ID, since a message with a reference count greater + * than 1 is always shared in the heap. + */ + if((bt2_find = H5B2_find(bt2, dxpl_id, &key, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "can't search for message in index") + found = (hbool_t)bt2_find; } /* end if */ - else - H5E_clear_stack(NULL); /*ignore error*/ + else { + H5SM_incr_ref_opdata op_data; + + /* Set up callback info */ + op_data.key = &key; + op_data.dxpl_id = dxpl_id; + + /* If this returns failure, it means that the message wasn't found. */ + /* If it succeeds, set the heap_id in the shared struct. It will + * return a heap ID, since a message with a reference count greater + * than 1 is always shared in the heap. + */ + if(H5B2_modify(bt2, dxpl_id, &key, H5SM_incr_ref, &op_data) >= 0) { + shared.u.heap_id = op_data.fheap_id; + found = TRUE; + } /* end if */ + else + H5E_clear_stack(NULL); /*ignore error*/ + } /* end else */ } /* end else */ if(found) @@ -1308,75 +1341,94 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'share in ohdr' check returned error") /* If this message can be shared in an object header location, it is - * "shareable" but not shared in the heap. Insert it in the index - * but don't modify the original message. + * "shareable" but not shared in the heap. + * + * If 'defer' flag is set: + * We will insert it in the index but not modify the original + * message. + * If it can't be shared in an object header location, we will + * insert it in the heap. Note that we assume there will + * be an "open_oh" available when it is time to call + * H5SM_write_mesg with defer flag disabled. * - * If it can't be shared in an object header location or there's no - * object header location available, insert it in the heap. + * If 'defer' flag is not set: + * Insert it in the index but don't modify the original message. + * If it can't be shared in an object header location or there's + * no object header location available, insert it in the + * heap. */ - if(share_in_ohdr && open_oh) { + if(share_in_ohdr && (defer || open_oh)) { /* Set up shared component info */ shared.type = H5O_SHARE_TYPE_HERE; /* Retrieve any creation index from the native message */ if(H5O_msg_get_crt_index(type_id, mesg, &shared.u.loc.index) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to retrieve creation index") - shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh); - /* Copy shared component info into key for inserting into index */ - key.message.location = H5SM_IN_OH; - key.message.u.mesg_loc = shared.u.loc; + if(defer) + shared.u.loc.oh_addr = HADDR_UNDEF; + else { + shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh); + + /* Copy shared component info into key for inserting into index */ + key.message.location = H5SM_IN_OH; + key.message.u.mesg_loc = shared.u.loc; + } /* end else */ } /* end if */ else { - /* Put the message in the heap and record its new heap ID */ - if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - /* Set up shared component info */ - /* (heap ID set above) */ + /* (heap ID set below, if not deferred) */ shared.type = H5O_SHARE_TYPE_SOHM; - key.message.location = H5SM_IN_HEAP; - key.message.u.heap_loc.fheap_id = shared.u.heap_id; - key.message.u.heap_loc.ref_count = 1; - } /* end else */ - - /* Set common information */ - key.message.msg_type_id = type_id; + if(!defer) { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - /* Check whether the list has grown enough that it needs to become a B-tree */ - if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max) - if(H5SM_convert_list_to_btree(f, header, &list, fheap, open_oh, dxpl_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree") - - /* Insert the new message into the SOHM index */ - if(header->index_type == H5SM_LIST) { - /* Index is a list. Find an empty spot if we haven't already */ - if(empty_pos == UFAIL) - if((H5SM_find_in_list(list, NULL, &empty_pos) == UFAIL) || empty_pos == UFAIL) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list") - - /* Insert message into list */ - HDassert(list->messages[empty_pos].location == H5SM_NO_LOC); - HDassert(key.message.location != H5SM_NO_LOC); - list->messages[empty_pos] = key.message; - } /* end if */ - /* Index is a B-tree */ - else { - HDassert(header->index_type == H5SM_BTREE); + key.message.location = H5SM_IN_HEAP; + key.message.u.heap_loc.fheap_id = shared.u.heap_id; + key.message.u.heap_loc.ref_count = 1; + } /* end if */ + } /* end else */ - /* Open the index v2 B-tree, if it isn't already */ - if(NULL == bt2) { - if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) - HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") + if(!defer) { + /* Set common information */ + key.message.msg_type_id = type_id; + + /* Check whether the list has grown enough that it needs to become a B-tree */ + if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max) + if(H5SM_convert_list_to_btree(f, header, &list, fheap, open_oh, dxpl_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree") + + /* Insert the new message into the SOHM index */ + if(header->index_type == H5SM_LIST) { + /* Index is a list. Find an empty spot if we haven't already */ + if(empty_pos == UFAIL) + if((H5SM_find_in_list(list, NULL, &empty_pos) == UFAIL) || empty_pos == UFAIL) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list") + + /* Insert message into list */ + HDassert(list->messages[empty_pos].location == H5SM_NO_LOC); + HDassert(key.message.location != H5SM_NO_LOC); + list->messages[empty_pos] = key.message; } /* end if */ + /* Index is a B-tree */ + else { + HDassert(header->index_type == H5SM_BTREE); - if(H5B2_insert(bt2, dxpl_id, &key) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") - } /* end else */ + /* Open the index v2 B-tree, if it isn't already */ + if(NULL == bt2) { + if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) + HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") + } /* end if */ + + if(H5B2_insert(bt2, dxpl_id, &key) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") + } /* end else */ - ++(header->num_messages); - (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; + ++(header->num_messages); + (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; + } /* end if */ } /* end else */ /* Set the file pointer & message type for the shared component */ @@ -1395,7 +1447,7 @@ done: HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index") /* If we got a list out of the cache, release it (it is always dirty after writing a message) */ - if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0) + if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, defer ? H5AC__NO_FLAGS_SET : H5AC__DIRTIED_FLAG) < 0) HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") if(encoding_buf) diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h index 1465357..5fc9915 100755 --- a/src/H5SMprivate.h +++ b/src/H5SMprivate.h @@ -44,7 +44,7 @@ H5_DLL herr_t H5SM_init(H5F_t *f, H5P_genplist_t *fc_plist, H5_DLL htri_t H5SM_can_share(H5F_t *f, hid_t dxpl_id, H5SM_master_table_t *table, ssize_t *sohm_index_num, unsigned type_id, const void *mesg); H5_DLL htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, - unsigned type_id, void *mesg, unsigned *mesg_flags); + hbool_t defer, unsigned type_id, void *mesg, unsigned *mesg_flags); H5_DLL herr_t H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg); H5_DLL herr_t H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, diff --git a/test/objcopy.c b/test/objcopy.c index 0f56f99..e87acf2 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -1748,7 +1748,150 @@ error: H5Fclose(fid_src); } H5E_END_TRY; return 1; -} /* end test_copy_named_datatype_vl */ +} /* end test_copy_named_datatype_vl_vl */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_named_datatype_attr_self + * + * Purpose: Create name datatype in SRC file, with an attribute that + * uses that named datatype as its datatype, and copy it to + * DST file + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil + * Friday, March 11, 2011 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_named_datatype_attr_self(hid_t fcpl_src, hid_t fcpl_dst, hid_t fapl) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1, tid2 = -1; /* Datatype IDs */ + hid_t aid = -1; /* Attribute ID */ + hid_t sid = -1; /* Dataspace ID */ + hsize_t dims[2] = {3, 4}; /* Dataspace dimensions */ + H5O_info_t oinfo, oinfo2; /* Object info */ + H5G_info_t ginfo; /* Group info */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING("H5Ocopy(): named datatype with self-referential attribute"); + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, fapl)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR + + /* create named datatype */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataspace */ + if((sid = H5Screate_simple(2, dims, NULL)) < 0) TEST_ERROR + + /* create attribute */ + if((aid = H5Acreate2(tid, "attr_self", tid, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* attach other attributes to the dataset */ + if(test_copy_attach_attributes(tid, tid) < 0) TEST_ERROR + + /* close the attribute */ + if(H5Aclose(aid) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, fapl)) < 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 + + /* copy the datatype from SRC to DST */ + if(H5Ocopy(fid_src, NAME_DATATYPE_SIMPLE, fid_dst, NAME_DATATYPE_SIMPLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* open the source datatype */ + if((tid = H5Topen2(fid_src, NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + /* open the copied datatype */ + if((tid2 = H5Topen2(fid_dst, NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + + /* Compare the datatypes */ + if(H5Tequal(tid, tid2) != TRUE) TEST_ERROR + + /* close the source datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* open the destination attribute */ + if((aid = H5Aopen(tid2, "attr_self", H5P_DEFAULT)) < 0) TEST_ERROR + + /* open the destination attribute's datatype */ + if((tid = H5Aget_type(aid)) < 0) TEST_ERROR + + /* verify that the attribute's datatype is committed */ + if(H5Tcommitted(tid) != TRUE) TEST_ERROR + + /* verify that the addresses of the datatypes are the same */ + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(H5Oget_info(tid2, &oinfo2) < 0) TEST_ERROR + if(oinfo.fileno != oinfo2.fileno || oinfo.addr != oinfo2.addr) + FAIL_PUTS_ERROR("destination attribute does not use the same committed datatype") + + /* Verify that there are only 2 links int he destination root group */ + if(H5Gget_info(fid_dst, &ginfo) < 0) + if(ginfo.nlinks != 2) + FAIL_PUTS_ERROR("unexpected number of links in destination root group") + + /* close the attribute */ + if(H5Aclose(aid) < 0) TEST_ERROR + + /* close the datatypes */ + if(H5Tclose(tid2) < 0) TEST_ERROR + if(H5Tclose(tid) < 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 + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Tclose(tid2); + H5Tclose(tid); + H5Sclose(sid); + H5Aclose(aid); + H5Fclose(fid_dst); + H5Fclose(fid_src); + } H5E_END_TRY; + return 1; +} /* end test_copy_named_datatype_attr_self */ /*------------------------------------------------------------------------- @@ -7811,7 +7954,7 @@ error: * Failure: number of errors * * Programmer: Neil Fortner - * Wednesday, March 31, 2005 + * Wednesday, March 31, 2010 * *------------------------------------------------------------------------- */ @@ -8341,7 +8484,7 @@ main(void) } else { puts("Testing without dense attributes:"); - num_attributes_g = MAX(min_dense, 2) - 1; + num_attributes_g = MAX(min_dense, 2) - 2; } } /* end if */ else { @@ -8351,6 +8494,7 @@ main(void) } /* end else */ /* The tests... */ + nerrors += test_copy_named_datatype_attr_self(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); nerrors += test_copy_dataset_simple_empty(fcpl_src, fcpl_dst, my_fapl); |