From b643da672a7d0f0a52ecfef2c229e73876e0e13d Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Wed, 28 Mar 2012 01:21:14 -0500 Subject: [svn-r22164] Fixed a bug in H5Ocopy(): When copying an opened object, call the object's flush class action to ensure that cached data is flushed so that H5Ocopy will get the correct data. (HDFFV-7853) --- release_docs/RELEASE.txt | 4 + src/H5Dint.c | 1 - src/H5Doh.c | 50 +++++++- src/H5Dpkg.h | 1 + src/H5Goh.c | 3 +- src/H5O.c | 6 +- src/H5Ocopy.c | 35 +++++- src/H5Opkg.h | 3 +- src/H5Toh.c | 3 +- test/objcopy.c | 314 +++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 408 insertions(+), 12 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 6992d8c..6c61597 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -373,6 +373,10 @@ Bug Fixes since HDF5-1.8.0 release Library ------- + - Fixed a bug in H5Ocopy(): When copying an opened object, call the + object's flush class action to ensure that cached data is flushed + so that H5Ocopy will get the correct data. + (VC - 2012/3/27 - HDFFV-7853) - When an application tries to write or read many small data chunks and runs out of memory, the library had a seg fault. The fix is to return the error stack with proper information. (SLU - 2012/3/23. diff --git a/src/H5Dint.c b/src/H5Dint.c index 9a80bfc..5c905bb 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -68,7 +68,6 @@ static herr_t H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space) static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id); static herr_t H5D_open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id); -static herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id); /*********************/ diff --git a/src/H5Doh.c b/src/H5Doh.c index 7a657ec..e6a715f 100644 --- a/src/H5Doh.c +++ b/src/H5Doh.c @@ -56,6 +56,8 @@ static H5O_loc_t *H5O_dset_get_oloc(hid_t obj_id); static herr_t H5O_dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info); +static herr_t H5O_dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id); + /*********************/ /* Package Variables */ @@ -81,7 +83,8 @@ const H5O_obj_class_t H5O_OBJ_DATASET[1] = {{ H5O_dset_open, /* open an object of this class */ H5O_dset_create, /* create an object of this class */ H5O_dset_get_oloc, /* get an object header location for an object */ - H5O_dset_bh_info /* get the index & heap info for an object */ + H5O_dset_bh_info, /* get the index & heap info for an object */ + H5O_dset_flush /* flush an opened object of this class */ }}; /* Declare a free list to manage the H5D_copy_file_ud_t struct */ @@ -431,3 +434,48 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dset_bh_info() */ + +/*------------------------------------------------------------------------- + * Function: H5O_dset_flush + * + * Purpose: To flush any dataset information cached in memory + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Vailin Choi + * February 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id) +{ + H5D_t *dset; /* Dataset opened */ + H5O_type_t obj_type; /* Type of object at location */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(obj_loc); + HDassert(obj_loc->oloc); + + /* Check that the object found is the correct type */ + if(H5O_obj_type(obj_loc->oloc, &obj_type, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object type") + + if(obj_type != H5O_TYPE_DATASET) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset") + + /* Open the dataset */ + if(NULL == (dset = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset") + + if(H5D_flush_real(dset, dxpl_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info") + +done: + if(dset && H5D_close(dset) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataset") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_dset_flush() */ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 16de07f..40317f3 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -548,6 +548,7 @@ H5_DLL herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache); H5_DLL herr_t H5D_flush_sieve_buf(H5D_t *dataset, hid_t dxpl_id); H5_DLL herr_t H5D_mark(H5D_t *dataset, hid_t dxpl_id, unsigned flags); +H5_DLL herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id); /* Functions that perform direct serial I/O operations */ H5_DLL herr_t H5D_select_read(const H5D_io_info_t *io_info, diff --git a/src/H5Goh.c b/src/H5Goh.c index 194e3ec..c6115db 100644 --- a/src/H5Goh.c +++ b/src/H5Goh.c @@ -81,7 +81,8 @@ const H5O_obj_class_t H5O_OBJ_GROUP[1] = {{ H5O_group_open, /* open an object of this class */ H5O_group_create, /* create an object of this class */ H5O_group_get_oloc, /* get an object header location for an object */ - H5O_group_bh_info /* get the index & heap info for an object */ + H5O_group_bh_info, /* get the index & heap info for an object */ + NULL /* flush an opened object of this class */ }}; /* Declare the external free list to manage the H5O_ginfo_t struct */ diff --git a/src/H5O.c b/src/H5O.c index 50d9c23..104a9ae 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -79,12 +79,12 @@ typedef struct { /********************/ static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh); -static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id); static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type); static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id, hid_t dxpl_id); static herr_t H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr); +static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); /*********************/ @@ -2364,7 +2364,7 @@ H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type) * *------------------------------------------------------------------------- */ -static const H5O_obj_class_t * +const H5O_obj_class_t * H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id) { H5O_t *oh = NULL; /* Object header for location */ @@ -2401,7 +2401,7 @@ done: * *------------------------------------------------------------------------- */ -const H5O_obj_class_t * +static const H5O_obj_class_t * H5O_obj_class_real(H5O_t *oh) { size_t i; /* Local index variable */ diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index dd649ff..e2d792a 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -38,6 +38,7 @@ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5HGprivate.h" /* Global Heaps */ +#include "H5FOprivate.h" /* File objects */ #include "H5Lprivate.h" /* Links */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ @@ -281,6 +282,13 @@ done: * Programmer: Peter Cao * May 30, 2005 * + * Modifications: + * Vailin Choi; Feb 2012 + * Bug fix for HDFFV-7853 + * When the object is opened, call the object's flush class action + * to ensure that cached data is flushed so that H5Ocopy will get + * the correct data. + * *------------------------------------------------------------------------- */ static herr_t @@ -316,14 +324,33 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(oloc_dst->file); HDassert(cpy_info); + /* Get pointer to object class for this object */ + if((obj_class = H5O_obj_class(oloc_src, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") + + /* Check if the object at the address is already open in the file */ + if(H5FO_opened(oloc_src->file, oloc_src->addr) != NULL) { + + H5G_loc_t tmp_loc; /* Location of object */ + H5O_loc_t tmp_oloc; /* Location of object */ + H5G_name_t tmp_path; /* Object's path */ + + tmp_loc.oloc = &tmp_oloc; + tmp_loc.path = &tmp_path; + tmp_oloc.file = oloc_src->file; + tmp_oloc.addr = oloc_src->addr; + tmp_oloc.holding_file = oloc_src->holding_file; + H5G_name_reset(tmp_loc.path); + + /* Flush the object of this class */ + if(obj_class->flush && obj_class->flush(&tmp_loc, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object") + } + /* Get source object header */ if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") - /* Get pointer to object class for this object */ - if(NULL == (obj_class = H5O_obj_class_real(oh_src))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type") - /* Retrieve user data for particular type of object to copy */ if(obj_class->get_copy_file_udata && (NULL == (cpy_udata = (obj_class->get_copy_file_udata)()))) diff --git a/src/H5Opkg.h b/src/H5Opkg.h index a5d01bd..d4df79b 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -325,6 +325,7 @@ typedef struct H5O_obj_class_t { void *(*create)(H5F_t *, void *, H5G_loc_t *, hid_t ); /*create an object of this class */ H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */ herr_t (*bh_info)(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info); /*get the index & heap info for an object */ + herr_t (*flush)(H5G_loc_t *loc, hid_t dxpl_id); /*flush an opened object of this class */ } H5O_obj_class_t; /* Node in skip list to map addresses from one file to another during object header copy */ @@ -527,7 +528,7 @@ H5_DLL herr_t H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg); H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh); H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref); H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg); -H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); +H5_DLL const H5O_obj_class_t * H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id); H5_DLL int H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted); H5_DLL herr_t H5O_inc_rc(H5O_t *oh); H5_DLL herr_t H5O_dec_rc(H5O_t *oh); diff --git a/src/H5Toh.c b/src/H5Toh.c index 5878075..be853f1 100644 --- a/src/H5Toh.c +++ b/src/H5Toh.c @@ -77,7 +77,8 @@ const H5O_obj_class_t H5O_OBJ_DATATYPE[1] = {{ H5O_dtype_open, /* open an object of this class */ H5O_dtype_create, /* create an object of this class */ H5O_dtype_get_oloc, /* get an object header location for an object */ - NULL /* get the index & heap info for an object */ + NULL, /* get the index & heap info for an object */ + NULL /* flush an opened object of this class */ }}; diff --git a/test/objcopy.c b/test/objcopy.c index 5c20ee8..9188713 100644 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -8388,6 +8388,319 @@ error: /*------------------------------------------------------------------------- + * Function: test_copy_dataset_open + * + * Purpose: To ensure that H5Ocopy() copies data of opened dataset correctly. + * This is for bug fix HDFFV-7853. + * + * Test Case 1: + * Create a dataset with attributes in SRC file + * Copy the opened dataset to another location in the same file + * Copy the opened dataset to DST file + * Close the dataset + * + * Test Case 2: + * Reopen the dataset, write new data to the dataset + * Copy the opened dataset to another location in the same file + * Copy the opened dataset to to DST file + * Close the dataset + * + * Test Case 3: + * Create a committed datatype + * Create a dataset with the committed datatype in SRC file + * Open the committed datatype + * Copy the opened dataset (with the opened committed datatype) to another location in the same file + * Copy the opened dataset (with the opened committed datatype) to DST file + * Close the dataset and the committed datatype + * + * Test Case 4: + * Create a group with attributes, create a dataset in the group + * Copy the opened group (together with the opened dataset) to another location in the same file + * Copy the opened group (together with the opened dataset) to DST file + * Close the group and the dataset + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi + * Feb 7, 2012 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_dataset_open(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t sid = -1; /* Dataspace ID */ + hid_t tid = -1; /* Datatype ID */ + hid_t did = -1, did2 = -1; /* Dataset IDs */ + hid_t gid = -1, gid2 = -1; /* Group IDs */ + int buf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */ + int newbuf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */ + hsize_t dim2d[2]; /* Dataset dimensions */ + int i, j; /* local index variables */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING("H5Ocopy(): copying objects while opened"); + + /* Initialize write buffer */ + for (i=0; i