From 0e573bd2406448e9380d15d17c41bb1d8b5300e7 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 30 Mar 2012 23:40:52 -0500 Subject: [svn-r22215] Description: Bring r22171 from trunk to 1.8 branch: Bring "merge committed datatypes during H5Ocopy" feature from branch to trunk. (Also has some minor bugfixes with it) Tested on: Mac OSX/64 10.7.3 (amazon) w/debug (h5committest coming up) --- release_docs/RELEASE.txt | 42 +- src/H5A.c | 30 + src/H5Apkg.h | 26 - src/H5Aprivate.h | 32 + src/H5Oainfo.c | 14 +- src/H5Oattr.c | 1 + src/H5Oattribute.c | 5 +- src/H5Ocopy.c | 778 ++++++++++- src/H5Odtype.c | 38 + src/H5Oefl.c | 8 +- src/H5Ofill.c | 2 + src/H5Olayout.c | 8 +- src/H5Olinfo.c | 16 +- src/H5Olink.c | 16 +- src/H5Omessage.c | 6 +- src/H5Opkg.h | 12 +- src/H5Opline.c | 1 + src/H5Oprivate.h | 22 +- src/H5Opublic.h | 11 +- src/H5Osdspace.c | 1 + src/H5Oshared.c | 17 +- src/H5Oshared.h | 21 +- src/H5Ostab.c | 18 +- src/H5Pdcpl.c | 2 +- src/H5Pocpypl.c | 443 ++++++- src/H5Ppublic.h | 5 + src/H5SM.c | 5 +- test/objcopy.c | 3220 +++++++++++++++++++++++++++++++++++++++++++++- 28 files changed, 4642 insertions(+), 158 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 4bdb2b3..9f70403 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -60,6 +60,11 @@ New Features Library ------- + - Added new feature to merge committed datatypes when copying objects, + using new H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG, modified by new API + routines: H5Padd_merge_committed_dtype_path(), + H5Pfree_merge_committed_dtype_paths(), H5Pset_mcdt_search_cb() and + H5_DLL herr_t H5Pget_mcdt_search_cb(). (QAK - 2012/03/30) - None Parallel Library @@ -131,8 +136,22 @@ Bug Fixes since HDF5-1.8.8 Library ------- + - Windows and STDIO correctness changes have been propagated from the SEC2 + and old Windows drivers to the STDIO VFD. (DER - 2012/3/30, HDFFV-7917) - Fixed an error that would occur when copying an object with attribute creation order tracked and indexed. (NAF - 2012/3/28 - HDFFV-7762) + - 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) + - The istore test will now skip the sparse 50x50x50 test when the VFD does + not support sparse files on that platform. The most important platforms + on which this will be skipped are Windows (NTFS sparse files are not + supported) and Mac OS-X (HFS sparse files are not supported). This + fixes CTest timeout issues on Windows. (DER - 2012/3/27, HDFFV-7769) + - Windows and POSIX correctness changes have been propagated from the SEC2 + VFD to the core VFD. This mainly affects file operations on the + driver's backing store and fixes a problem on Windows where large files + could not be read. (DER - 2012/3/27, HDFFV-7916, HDFFV-7603) - 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. @@ -144,32 +163,23 @@ Bug Fixes since HDF5-1.8.8 header format. (NAF - 2012/3/15 - HDFFV-7879) - Fixed error when creating a contiguous dataset with a zero-sized dataspace and space allocation time set to 'early'. (QAK - 2012/3/12) + - Changed Windows thread creation to use _beginthread() instead of + CreateThread(). Threads created by the latter can be killed in + low-memory situations. (DER - 2012/2/10, HDFFV-7780) - Creating a dataset in a read-only file caused seg fault when the file is closed. It's fixed. The attemp to create a dataset will fail with the error stack indicating the file is read-only. (SLU - 2012/1/25. Issue 7756) - Fixed a seg fault that could occur when shrinking a dataset with chunks larger than 1 MB. (NAF - 2011/11/30 - HDFFV-7833) + - Fixed a bug that could cause H5Oget_info to return the wrong address + after copying a named datatype. (NAF - 2011/11/14) - The library allowed the conversion of strings between ASCII and UTF8 (Issue 7582). We have corrected it to report an error under this situation. (SLU - 2011/11/8) - - The library had seg fault when it tried to shrink the size of compound + - Fixed seg fault when library tried to shrink the size of compound type through H5Tset_size immediately after the type was created (Issue - 7618). It's fixed now. (SLU - 2011/11/4) - - Changed Windows thread creation to use _beginthread() instead of - CreateThread(). Threads created by the latter can be killed in - low-memory situations. (DER - 2012/2/10, HDFFV-7780) - - The istore test will now skip the sparse 50x50x50 test when the VFD does - not support sparse files on that platform. The most important platforms - on which this will be skipped are Windows (NTFS sparse files are not - supported) and Mac OS-X (HFS sparse files are not supported). This - fixes CTest timeout issues on Windows. (DER - 2012/3/27, HDFFV-7769) - - Windows and POSIX correctness changes have been propagated from the SEC2 - VFD to the core VFD. This mainly affects file operations on the - driver's backing store and fixes a problem on Windows where large files - could not be read. (DER - 2012/3/27, HDFFV-7916, HDFFV-7603) - - Windows and STDIO correctness changes have been propagated from the SEC2 - and old Windows drivers to the STDIO VFD. (DER - 2012/3/30, HDFFV-7917) + 7618). (SLU - 2011/11/4) Parallel Library ---------------- diff --git a/src/H5A.c b/src/H5A.c index 8945669..221d190 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -2523,6 +2523,36 @@ done: /*------------------------------------------------------------------------- + * Function: H5A_type + * + * Purpose: Return the datatype for an attribute. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Neil Fortner + * Friday, November 11, 2011 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5A_type(const H5A_t *attr) +{ + H5T_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + HDassert(attr); + + /* Set return value */ + ret_value = attr->shared->dt; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_type() */ + + +/*------------------------------------------------------------------------- * Function: H5Aexists * * Purpose: Checks if an attribute with a given name exists on an opened diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 20aa5b9..26c8dff 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -158,29 +158,6 @@ typedef struct { H5A_t **attrs; /* Pointer to array of attribute pointers */ } H5A_attr_table_t; -/* Attribute iteration operator for internal library callbacks */ -typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); - -/* Describe kind of callback to make for each attribute */ -typedef enum H5A_attr_iter_op_type_t { -#ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_ATTR_OP_APP, /* Application callback */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5A_ATTR_OP_APP2, /* Revised application callback */ - H5A_ATTR_OP_LIB /* Library internal callback */ -} H5A_attr_iter_op_type_t; - -typedef struct H5A_attr_iter_op_t { - H5A_attr_iter_op_type_t op_type; - union { -#ifndef H5_NO_DEPRECATED_SYMBOLS - H5A_operator1_t app_op; /* Application callback for each attribute */ -#endif /* H5_NO_DEPRECATED_SYMBOLS */ - H5A_operator2_t app_op2; /* Revised application callback for each attribute */ - H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ - } u; -} H5A_attr_iter_op_t; - /*****************************/ /* Package Private Variables */ @@ -268,9 +245,6 @@ H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr); H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name); -H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type, - H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, - const H5A_attr_iter_op_t *op, void *op_data); H5_DLL herr_t H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); H5_DLL herr_t H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type, diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 0c0e519..6646fa2 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -24,6 +24,8 @@ /* Private headers needed by this file */ #include "H5Gprivate.h" /* Groups */ +#include "H5Oprivate.h" /* Object headers */ +#include "H5Tprivate.h" /* Datatypes */ /**************************/ @@ -38,6 +40,29 @@ /* Forward references of package typedefs */ typedef struct H5A_t H5A_t; +/* Attribute iteration operator for internal library callbacks */ +typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); + +/* Describe kind of callback to make for each attribute */ +typedef enum H5A_attr_iter_op_type_t { +#ifndef H5_NO_DEPRECATED_SYMBOLS + H5A_ATTR_OP_APP, /* Application callback */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_ATTR_OP_APP2, /* Revised application callback */ + H5A_ATTR_OP_LIB /* Library internal callback */ +} H5A_attr_iter_op_type_t; + +typedef struct H5A_attr_iter_op_t { + H5A_attr_iter_op_type_t op_type; + union { +#ifndef H5_NO_DEPRECATED_SYMBOLS + H5A_operator1_t app_op; /* Application callback for each attribute */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + H5A_operator2_t app_op2; /* Revised application callback for each attribute */ + H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ + } u; +} H5A_attr_iter_op_t; + /*****************************/ /* Library-private Variables */ @@ -51,6 +76,13 @@ typedef struct H5A_t H5A_t; /* General attribute routines */ H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr); H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr); +H5_DLL H5T_t *H5A_type(const H5A_t *attr); +H5_DLL herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, + hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, + hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data); +H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id, H5_index_t idx_type, + H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, + const H5A_attr_iter_op_t *op, void *op_data); #endif /* _H5Aprivate_H */ diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index 78b17e0..8a146c4 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -46,11 +46,11 @@ static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); 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); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + 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); + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, 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); @@ -403,7 +403,8 @@ 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 UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + 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; @@ -462,7 +463,8 @@ done: */ 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_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src; herr_t ret_value = SUCCEED; /* Return value */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 8cd243b..510d64f 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -61,6 +61,7 @@ static herr_t H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #define H5O_SHARED_COPY_FILE_REAL H5O_attr_copy_file #define H5O_SHARED_POST_COPY_FILE H5O_attr_shared_post_copy_file #define H5O_SHARED_POST_COPY_FILE_REAL H5O_attr_post_copy_file +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_attr_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_attr_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index e36d4ab..bbaf72b 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -135,9 +135,6 @@ typedef struct { /********************/ /* Local Prototypes */ /********************/ -static herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, - hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, - hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data); static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_to_open); @@ -1283,7 +1280,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data) diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index d9a4b42..95a2e75 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -34,6 +34,7 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ @@ -54,6 +55,20 @@ /* Local Typedefs */ /******************/ +/* Key object for skiplist of committed datatypes */ +typedef struct H5O_copy_search_comm_dt_key_t { + H5T_t *dt; /* Datatype */ + unsigned long fileno; /* File number */ +} H5O_copy_search_comm_dt_key_t; + +/* Callback struct for building a list of committed datatypes */ +typedef struct H5O_copy_search_comm_dt_ud_t { + H5SL_t *dst_dt_list; /* Skip list of committed datatypes */ + H5G_loc_t *dst_root_loc; /* Starting location for iteration */ + H5O_loc_t obj_oloc; /* Object location (for attribute iteration callback) */ + hid_t dxpl_id; /* Dataset transfer property list id */ +} H5O_copy_search_comm_dt_ud_t; + /********************/ /* Package Typedefs */ @@ -65,14 +80,23 @@ /********************/ static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data); -static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, +static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata); -static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, unsigned cpy_option); +static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, + hid_t dxpl_id, hid_t ocpypl_id); static herr_t H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id); static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info); +static herr_t H5O_copy_free_comm_dt_cb(void *item, void *key, void *op_data); +static int H5O_copy_comm_dt_cmp(const void *dt1, const void *dt2); +static herr_t H5O_copy_search_comm_dt_cb(hid_t group, const char *name, + const H5L_info_t *linfo, void *udata); +static htri_t H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info); +static herr_t H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + /*********************/ /* Package Variables */ @@ -81,6 +105,12 @@ static herr_t H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, /* Declare a free list to manage the H5O_addr_map_t struct */ H5FL_DEFINE(H5O_addr_map_t); +/* Declare a free list to manage the H5O_copy_search_comm_dt_key_t struct */ +H5FL_DEFINE(H5O_copy_search_comm_dt_key_t); + +/* Declare a free list to manage haddr_t variables */ +H5FL_DEFINE(haddr_t); + /*****************************/ /* Library Private Variables */ @@ -284,8 +314,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, void **udata) +H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, + hid_t dxpl_id, H5O_copy_t *cpy_info, H5O_type_t *obj_type, + void **udata /*out*/) { H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ H5O_t *oh_src = NULL; /* Object header for source object */ @@ -329,6 +360,53 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, (NULL == (cpy_udata = (obj_class->get_copy_file_udata)()))) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to retrieve copy user data") + /* If we are merging committed datatypes, check for a match in the destination + * file now */ + if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE) { + unsigned long fileno_src; /* fileno for source file */ + unsigned long fileno_dst; /* fileno for destination file */ + htri_t merge; /* Whether we found a match in the destination file */ + + /* Check if the source and dest file are the same. If so, just return + * the source object address */ + H5F_GET_FILENO(oloc_src->file, fileno_src); + H5F_GET_FILENO(oloc_dst->file, fileno_dst); + if(fileno_src == fileno_dst) { + merge = TRUE; + oloc_dst->addr = oloc_src->addr; + } /* end if */ + else + /* Search for a matching committed datatype, building the list if + * necessary */ + if((merge = H5O_copy_search_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't search for matching committed datatype") + + if(merge) { + /* Found a match, add to skip list and exit */ + /* Allocate space for the address mapping of the object copied */ + if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Insert the address mapping for the found object into the copied + * list */ + addr_map->src_obj_pos.fileno = fileno_src; + addr_map->src_obj_pos.addr = oloc_src->addr; + addr_map->dst_addr = oloc_dst->addr; + addr_map->is_locked = TRUE; /* We've locked the object currently */ + addr_map->inc_ref_count = 0; /* Start with no additional ref counts to add */ + addr_map->obj_class = obj_class; + addr_map->udata = cpy_udata; + + /* Insert into skip list */ + if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) { + addr_map = H5FL_FREE(H5O_addr_map_t, addr_map); + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + } /* end if */ + + HGOTO_DONE(SUCCEED) + } /* end if */ + } /* end if */ + /* Flush any dirty messages in source object header to update the header chunks */ if(H5O_flush_msgs(oloc_src->file, oh_src) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages") @@ -470,38 +548,33 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* copy this message into destination file */ if(copy_type->copy_file) { - htri_t is_shared; /* Whether message is shared */ hbool_t recompute_size; /* Whether copy_file callback created a shared message */ + unsigned mesg_flags; /* Message flags */ /* Decode the message if necessary. */ H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL) + /* Get destination message flags, and unset shared and shareable + * flags. mesg_dst->flags will contain the original flags for now. + */ + mesg_flags = (unsigned)mesg_dst->flags & ~H5O_MSG_FLAG_SHARED + & ~H5O_MSG_FLAG_SHAREABLE; + /* Copy the source message */ recompute_size = FALSE; - if((mesg_dst->native = H5O_msg_copy_file(copy_type, - oloc_src->file, mesg_src->native, oloc_dst->file, - &recompute_size, cpy_info, cpy_udata, dxpl_id)) == NULL) + if((mesg_dst->native = H5O_msg_copy_file(copy_type, oloc_src->file, + mesg_src->native, oloc_dst->file, &recompute_size, + &mesg_flags, cpy_info, cpy_udata, dxpl_id)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") - /* Check if new message is shared */ - if((is_shared = H5O_msg_is_shared(copy_type->id, mesg_dst->native)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to query message's shared status") - - /* In being copied, the message may have become shared or stopped - * being shared, set/unset its sharing flag. + /* Check if the sharing state changed, and recompute the size if so */ - if(is_shared && !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - mesg_dst->flags |= H5O_MSG_FLAG_SHARED; - - /* Recompute message size (mesg_dst->native is really shared) */ - recompute_size = TRUE; - } /* end if */ - else if(!is_shared && (mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - mesg_dst->flags &= ~H5O_MSG_FLAG_SHARED; - - /* Recompute message size (msg_dest->native is no longer shared) */ + if(!(mesg_flags & H5O_MSG_FLAG_SHARED) + != !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) recompute_size = TRUE; - } /* end if */ + + /* Set destination message flags */ + mesg_dst->flags = (uint8_t)mesg_flags; /* Recompute message's size */ /* (its sharing status or one of its components (for attributes) @@ -671,6 +744,13 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, oloc_dst->addr = addr_new; + /* If we are merging committed datatypes and this is a committed datatype, insert + * the copied datatype into the list of committed datatypes in the target file. + */ + if(cpy_info->merge_comm_dt && obj_class->type == H5O_TYPE_NAMED_DATATYPE) + if(H5O_copy_insert_comm_dt(oloc_src->file, oh_src, oloc_dst, dxpl_id, cpy_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't insert committed datatype into destination list") + /* Allocate space for the address mapping of the object copied */ if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") @@ -686,8 +766,10 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, addr_map->udata = cpy_udata; /* Insert into skip list */ - if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) + if(H5SL_insert(cpy_info->map_list, addr_map, &(addr_map->src_obj_pos)) < 0) { + addr_map = H5FL_FREE(H5O_addr_map_t, addr_map); HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + } /* end if */ /* "post copy" loop over messages, to fix up any messages which require a complete * object header for destination object @@ -716,17 +798,26 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(copy_type); if(copy_type->post_copy_file && mesg_src->native) { + unsigned mesg_flags; /* Message flags */ + /* Sanity check destination message */ HDassert(mesg_dst->type == mesg_src->type); HDassert(mesg_dst->native); + /* Get destination message flags. mesg_dst->flags will contain the + * original flags for now. */ + mesg_flags = (unsigned)mesg_dst->flags; + /* the object header is needed in the post copy for shared message */ cpy_info->oh_dst = oh_dst; /* Perform "post copy" operation on message */ if((copy_type->post_copy_file)(oloc_src, mesg_src->native, oloc_dst, - mesg_dst->native, dxpl_id, cpy_info) < 0) + mesg_dst->native, &mesg_flags, dxpl_id, cpy_info) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'post copy' operation on message") + + /* Verify that the flags did not change */ + HDassert(mesg_flags == (unsigned) mesg_dst->flags); } /* end if */ } /* end for */ @@ -787,9 +878,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, +H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, hid_t dxpl_id, H5O_copy_t *cpy_info, hbool_t inc_depth, - H5O_type_t *obj_type, void **udata) + H5O_type_t *obj_type, void **udata /*out*/) { H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ H5_obj_t src_obj_pos; /* Position of source object */ @@ -927,9 +1018,13 @@ H5O_copy_free_addrmap_cb(void *_item, void UNUSED *key, void UNUSED *op_data) */ static herr_t H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, - hid_t dxpl_id, unsigned cpy_option) + hid_t dxpl_id, hid_t ocpypl_id) { H5O_copy_t cpy_info; /* Information for copying object */ + H5P_genplist_t *ocpy_plist; /* Object copy property list created */ + H5O_copy_dtype_merge_list_t *dt_list = NULL; /* List of datatype merge suggestions */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + unsigned cpy_option = 0; /* Copy options */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -939,6 +1034,22 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(H5F_addr_defined(oloc_src->addr)); HDassert(oloc_dst->file); + /* Get the copy property list */ + if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* Retrieve the copy parameters */ + if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag") + + /* Retrieve the marge committed datatype list */ + if(H5P_get(ocpy_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed datatype list") + + /* Get callback info */ + if(H5P_get(ocpy_plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + /* Convert copy flags into copy struct */ HDmemset(&cpy_info, 0, sizeof(H5O_copy_t)); if((cpy_option & H5O_COPY_SHALLOW_HIERARCHY_FLAG) > 0) { @@ -958,9 +1069,18 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, cpy_info.copy_without_attr = TRUE; if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0) cpy_info.preserve_null = TRUE; + if((cpy_option & H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) > 0) + cpy_info.merge_comm_dt = TRUE; + + /* Add dt_list to copy struct */ + cpy_info.dst_dt_suggestion_list = dt_list; + + /* Add set callback information */ + cpy_info.mcdt_cb = cb_info.func; + cpy_info.mcdt_ud = cb_info.user_data; /* Create a skip list to keep track of which objects are copied */ - if((cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL) + if(NULL == (cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ, NULL))) HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list") /* copy the object from the source file to the destination file */ @@ -970,6 +1090,8 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, done: if(cpy_info.map_list) H5SL_destroy(cpy_info.map_list, H5O_copy_free_addrmap_cb, NULL); + if(cpy_info.dst_dt_list) + H5SL_destroy(cpy_info.dst_dt_list, H5O_copy_free_comm_dt_cb, NULL); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_copy_header() */ @@ -991,14 +1113,12 @@ static herr_t H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id) { - H5P_genplist_t *ocpy_plist=NULL; /* Object copy property list created */ - hid_t dxpl_id=H5AC_dxpl_id; H5G_name_t new_path; /* Copied object group hier. path */ H5O_loc_t new_oloc; /* Copied object object location */ H5G_loc_t new_loc; /* Group location of object copied */ H5F_t *cached_dst_file; /* Cached destination file */ - hbool_t entry_inserted=FALSE; /* Flag to indicate that the new entry was inserted into a group */ - unsigned cpy_option = 0; /* Copy options */ + hbool_t entry_inserted = FALSE; /* Flag to indicate that the new entry was inserted into a group */ + hid_t dxpl_id = H5AC_dxpl_id; /* DXPL for operation */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1009,14 +1129,6 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, HDassert(dst_loc->oloc->file); HDassert(dst_name); - /* Get the copy property list */ - if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* Retrieve the copy parameters */ - if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag") - /* Set up copied object location to fill in */ new_loc.oloc = &new_oloc; new_loc.path = &new_path; @@ -1029,7 +1141,7 @@ H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name, cached_dst_file = dst_loc->oloc->file; /* Copy the object from the source file to the destination file */ - if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, cpy_option) < 0) + if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, ocpypl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") /* Patch dst_loc. Again, this can be removed once oloc's point to shared @@ -1245,3 +1357,579 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_copy_expand_ref() */ + +/*------------------------------------------------------------------------- + * Function: H5O_copy_free_comm_dt_cb + * + * Purpose: Frees the merge committed dt skip list key and object. + * + * Return: SUCCEED (never fails) + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_free_comm_dt_cb(void *item, void *_key, void UNUSED *op_data) +{ + haddr_t *addr = (haddr_t *)item; + H5O_copy_search_comm_dt_key_t *key = (H5O_copy_search_comm_dt_key_t *)_key; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(addr); + HDassert(key); + HDassert(key->dt); + + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + addr = H5FL_FREE(haddr_t, addr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_copy_free_comm_dt_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_comm_dt_cmp + * + * Purpose: Skiplist callback used to compare 2 keys for the merge + * committed dt list. Mostly a wrapper for H5T_cmp. + * + * Return: 0 if key1 and key2 are equal. + * <0 if key1 is less than key2. + * >0 if key1 is greater than key2. + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static int +H5O_copy_comm_dt_cmp(const void *_key1, const void *_key2) +{ + const H5O_copy_search_comm_dt_key_t *key1 = (const H5O_copy_search_comm_dt_key_t *)_key1; + const H5O_copy_search_comm_dt_key_t *key2 = (const H5O_copy_search_comm_dt_key_t *)_key2; + int ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT + + /* Check fileno. It is unlikely to be different so check if they are equal + * first so only one comparison needs to be made. */ + if(key1->fileno != key2->fileno) { + if(key1->fileno < key2->fileno) + HGOTO_DONE(-1) + if(key1->fileno > key2->fileno) + HGOTO_DONE(1) + } /* end if */ + + ret_value = H5T_cmp(key1->dt, key2->dt, FALSE); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_comm_dt_cmp */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_attr_cb + * + * Purpose: Callback for H5O_attr_iterate_real from + * H5O_copy_search_comm_dt_check. Checks if the attribute's + * datatype is committed. If it is, adds it to the merge + * committed dt skiplist present in udata if it does not match + * any already present. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Nov 3 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_attr_cb(const H5A_t *attr, void *_udata) +{ + H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata; + H5T_t *dt = NULL; /* Datatype */ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination address */ + hbool_t obj_inserted = FALSE; /* Object inserted into skip list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(attr); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(H5F_addr_defined(udata->obj_oloc.addr)); + + /* Get attribute datatype */ + if(NULL == (dt = H5A_type(attr))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get attribute datatype") + + /* Check if the datatype is committed and search the skip list if so */ + if(H5T_committed(dt)) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy datatype into key */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_copy(H5O_DTYPE_ID, dt, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy datatype message") + + /* Get datatype object fileno */ + H5F_GET_FILENO(udata->obj_oloc.file, key->fileno); + + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + +done: + /* Release resources */ + if(!obj_inserted) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) { + HDassert(ret_value < 0); + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_attr_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_check + * + * Purpose: Check if the object at obj_oloc is or contains a reference + * to a committed datatype. If it does, adds it to the merge + * committed dt skiplist present in udata if it does not match + * any already present. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Nov 3 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_check(H5O_loc_t *obj_oloc, + H5O_copy_search_comm_dt_ud_t *udata) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination address */ + hbool_t obj_inserted = FALSE; /* Object inserted into skip list */ + H5O_info_t oinfo; /* Object info */ + H5A_attr_iter_op_t attr_op; /* Attribute iteration operator */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(obj_oloc); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(udata->dst_root_loc); + + /* Get the object's info */ + if(H5O_get_info(obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info") + + /* Check if the object is a datatype, a dataset using a committed + * datatype, or contains an attribute using a committed datatype */ + if(oinfo.type == H5O_TYPE_NAMED_DATATYPE) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the destination datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(obj_oloc->file, key->fileno); + + /* Check if the datatype is already present in the skip list */ + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = obj_oloc->addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + else if(oinfo.type == H5O_TYPE_DATASET) { + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the destination datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read(obj_oloc, H5O_DTYPE_ID, NULL, udata->dxpl_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Check if the datatype is committed and search the skip list if so + */ + if(H5T_committed(key->dt)) { + /* Get datatype object fileno */ + H5F_GET_FILENO(obj_oloc->file, key->fileno); + + if(!H5SL_search(udata->dst_dt_list, key)) { + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = ((H5O_shared_t *)(key->dt))->u.loc.oh_addr; + if(H5SL_insert(udata->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + obj_inserted = TRUE; + } /* end if */ + } /* end if */ + } /* end else */ + + /* Search within attributes */ + attr_op.op_type = H5A_ATTR_OP_LIB; + attr_op.u.lib_op = H5O_copy_search_comm_dt_attr_cb; + udata->obj_oloc.file = obj_oloc->file; + udata->obj_oloc.addr = obj_oloc->addr; + if(H5O_attr_iterate_real((hid_t)-1, obj_oloc, udata->dxpl_id, H5_INDEX_NAME, H5_ITER_NATIVE, 0, NULL, &attr_op, udata) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "error iterating over attributes"); + +done: + /* Release resources */ + if(!obj_inserted) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) { + HDassert(ret_value < 0); + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_check */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt_cb + * + * Purpose: H5G_visit callback to add committed datatypes to the merge + * committed dt skiplist. Mostly a wrapper for + * H5O_copy_search_comm_dt_check. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_search_comm_dt_cb(hid_t UNUSED group, const char *name, + const H5L_info_t *linfo, void *_udata) +{ + H5O_copy_search_comm_dt_ud_t *udata = (H5O_copy_search_comm_dt_ud_t *)_udata; /* Skip list of dtypes in dest file */ + H5G_loc_t obj_loc; /* Location of object */ + H5O_loc_t obj_oloc; /* Object's object location */ + H5G_name_t obj_path; /* Object's group hier. path */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(name); + HDassert(linfo); + HDassert(udata); + HDassert(udata->dst_dt_list); + HDassert(udata->dst_root_loc); + + /* Check if this is a hard link */ + if(linfo->type == H5L_TYPE_HARD) { + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Find the object */ + if(H5G_loc_find(udata->dst_root_loc, name, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found") + obj_found = TRUE; + + /* Check object and add to skip list if appropriate */ + if(H5O_copy_search_comm_dt_check(&obj_oloc, udata) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "can't check object") + } /* end if */ + +done: + /* Release resources */ + if(obj_found && H5G_loc_free(&obj_loc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt_cb */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_search_comm_dt + * + * Purpose: Checks if the committed datatype present in oh_src matches any + * in the destination file, building the destination file + * skiplist as necessary. + * + * Return: TRUE if a match is found in the destination file + * - oloc_dst will contain the address + * FALSE if a match is not found + * Negative on failure + * + * Programmer: Neil Fortner + * Sep 27 2011 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src, + H5O_loc_t *oloc_dst/*in, out*/, hid_t dxpl_id, H5O_copy_t *cpy_info) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *dst_addr; /* Destination datatype address */ + H5G_loc_t dst_root_loc = {NULL, NULL}; /* Destination root group location */ + H5O_copy_search_comm_dt_ud_t udata; /* Group iteration user data */ + herr_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(oh_src); + HDassert(oloc_dst); + HDassert(oloc_dst->file); + HDassert(H5F_FILE_ID(oloc_dst->file) >= 0); + HDassert(cpy_info); + + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the source datatype */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(oloc_dst->file, key->fileno); + + /* Check if the destination dtype list exists, create it if it does not */ + if(!cpy_info->dst_dt_list) { + /* Create the skip list */ + if(NULL == (cpy_info->dst_dt_list = H5SL_create(H5SL_TYPE_GENERIC, H5O_copy_comm_dt_cmp))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for committed datatypes") + + /* Add suggested types to list, if they are present */ + if(cpy_info->dst_dt_suggestion_list) { + H5O_copy_dtype_merge_list_t *suggestion = cpy_info->dst_dt_suggestion_list; + H5G_loc_t obj_loc; /* Location of object */ + H5O_loc_t obj_oloc; /* Object's object location */ + H5G_name_t obj_path; /* Object's group hier. path */ + + /* Set up the root group in the destination file */ + if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group") + if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group") + + /* Set up opened group location to fill in */ + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + H5G_loc_reset(&obj_loc); + + /* Build udata */ + udata.dst_dt_list = cpy_info->dst_dt_list; + udata.dst_root_loc = &dst_root_loc; + udata.obj_oloc.file = NULL; + udata.obj_oloc.addr = HADDR_UNDEF; + udata.dxpl_id = dxpl_id; + + /* Walk through the list of datatype suggestions */ + while(suggestion) { + /* Find the object */ + if(H5G_loc_find(&dst_root_loc, suggestion->path, &obj_loc/*out*/, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0) + /* Ignore errors - i.e. suggestions not present in + * destination file */ + H5E_clear_stack(NULL); + else + /* Check object and add to skip list if appropriate */ + if(H5O_copy_search_comm_dt_check(&obj_oloc, &udata) < 0) { + if(H5G_loc_free(&obj_loc) < 0) + HERROR(H5E_OHDR, H5E_CANTRELEASE, "can't free location"); + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't check object") + } /* end if */ + + /* Free location */ + if(H5G_loc_free(&obj_loc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location"); + + /* Advance the suggestion pointer */ + suggestion = suggestion->next; + } /* end while */ + } /* end if */ + } + + if(!cpy_info->dst_dt_list_complete) { + /* Search for the type in the destination file, and return its address + * if found, but only if the list is populated with and only with + * suggested types. We will search complete lists later. */ + if(cpy_info->dst_dt_suggestion_list + && NULL != (dst_addr = (haddr_t *)H5SL_search( + cpy_info->dst_dt_list, key))) { + oloc_dst->addr = *dst_addr; + ret_value = TRUE; + } /* end if */ + else { + H5O_mcdt_search_ret_t search_cb_ret = H5O_MCDT_SEARCH_CONT; + + /* Make callback to see if we should search destination file */ + if(cpy_info->mcdt_cb) + if((search_cb_ret = cpy_info->mcdt_cb(cpy_info->mcdt_ud)) == H5O_MCDT_SEARCH_ERROR) + HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "callback returned error") + + if(search_cb_ret == H5O_MCDT_SEARCH_CONT) { + /* Build the complete dst dt list */ + /* Set up the root group in the destination file, if necessary */ + if(!dst_root_loc.oloc) { + HDassert(!dst_root_loc.path); + if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group") + if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(oloc_dst->file)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group") + } /* end if */ + else + HDassert(dst_root_loc.path); + + /* Build udata. Note that this may be done twice in some cases, but + * it should be rare and should be cheaper on average than trying to + * keep track of whether it was done before. */ + udata.dst_dt_list = cpy_info->dst_dt_list; + udata.dst_root_loc = &dst_root_loc; + udata.obj_oloc.file = NULL; + udata.obj_oloc.addr = HADDR_UNDEF; + udata.dxpl_id = dxpl_id; + + /* Traverse the destination file, adding committed datatypes to the skip + * list */ + if(H5G_visit(H5F_FILE_ID(oloc_dst->file), "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5O_copy_search_comm_dt_cb, &udata, H5P_LINK_ACCESS_DEFAULT, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed") + cpy_info->dst_dt_list_complete = TRUE; + } /* end if */ + else + if(search_cb_ret != H5O_MCDT_SEARCH_STOP) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown return value for callback") + } /* end if */ + } /* end if */ + + /* Search for the type in the destination file, and return its address if + * found, but only if the list is complete */ + if(cpy_info->dst_dt_list_complete) { + if(NULL != (dst_addr = (haddr_t *)H5SL_search(cpy_info->dst_dt_list, key))) { + oloc_dst->addr = *dst_addr; + ret_value = TRUE; + } /* end if */ + } /* end if */ + +done: + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_search_comm_dt */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_insert_comm_dt + * + * Purpose: Insert the committed datatype at oloc_dst into the merge committed + * dt skiplist. The datatype must not be present already. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * Oct 6 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_insert_comm_dt(H5F_t *file_src, H5O_t *oh_src, H5O_loc_t *oloc_dst, + hid_t dxpl_id, H5O_copy_t *cpy_info) +{ + H5O_copy_search_comm_dt_key_t *key = NULL; /* Skiplist key */ + haddr_t *addr = NULL; /* Destination object address */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity checks */ + HDassert(oh_src); + HDassert(oloc_dst); + HDassert(oloc_dst->file); + HDassert(oloc_dst->addr != HADDR_UNDEF); + HDassert(cpy_info); + HDassert(cpy_info->dst_dt_list); + + /* Allocate key */ + if(NULL == (key = H5FL_MALLOC(H5O_copy_search_comm_dt_key_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the datatype. Read from the source file because the destination + * object could be changed in the post-copy. */ + if(NULL == (key->dt = (H5T_t *)H5O_msg_read_oh(file_src, dxpl_id, oh_src, H5O_DTYPE_ID, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read DTYPE message") + + /* Get destination object fileno */ + H5F_GET_FILENO(oloc_dst->file, key->fileno); + + /* Allocate destination address */ + if(NULL == (addr = H5FL_MALLOC(haddr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add the destination datatype to the skip list */ + *addr = oloc_dst->addr; + if(H5SL_insert(cpy_info->dst_dt_list, addr, key) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + +done: + if(ret_value < 0) { + if(key) { + if(key->dt) + key->dt = (H5T_t *)H5O_msg_free(H5O_DTYPE_ID, key->dt); + key = H5FL_FREE(H5O_copy_search_comm_dt_key_t, key); + } /* end if */ + if(addr) + addr = H5FL_FREE(haddr_t, addr); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_insert_comm_dt */ + diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 9ccb51b..1b602c7 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -43,6 +43,9 @@ static herr_t H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src, static void *H5O_dtype_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, void *native_src, H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_dtype_shared_post_copy_upd(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_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -63,6 +66,7 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #define H5O_SHARED_COPY_FILE_REAL H5O_dtype_copy_file #define H5O_SHARED_POST_COPY_FILE H5O_dtype_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#define H5O_SHARED_POST_COPY_FILE_UPD H5O_dtype_shared_post_copy_upd #define H5O_SHARED_DEBUG H5O_dtype_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_dtype_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ @@ -1575,6 +1579,40 @@ done: } /* end H5O_dtype_copy_file() */ +/*------------------------------------------------------------------------- + * Function: H5O_dtype_shared_post_copy_upd + * + * Purpose: Update a message after the shared message operations + * during the post-copy loop + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * November 8, 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_dtype_shared_post_copy_upd(const H5O_loc_t UNUSED *src_oloc, + const void UNUSED *mesg_src, H5O_loc_t UNUSED *dst_oloc, void *mesg_dst, + hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info) +{ + H5T_t *dt_dst = (H5T_t *)mesg_dst; /* Destination datatype */ + + FUNC_ENTER_NOAPI_NOINIT + + if(dt_dst->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { + HDassert(H5T_committed(dt_dst)); + dt_dst->oloc.file = dt_dst->sh_loc.file; + dt_dst->oloc.addr = dt_dst->sh_loc.u.loc.oh_addr; + } /* end if */ + else + HDassert(!H5T_committed(dt_dst)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_dtype_shared_post_copy_upd */ + + /*-------------------------------------------------------------------------- NAME H5O_dtype_debug diff --git a/src/H5Oefl.c b/src/H5Oefl.c index b71af5e..c8b6d01 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -36,8 +36,8 @@ static void *H5O_efl_copy(const void *_mesg, void *_dest); static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); static void *H5O_efl_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); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -455,8 +455,8 @@ done: */ static void * H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, - void UNUSED *_udata, hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void UNUSED *_udata, hid_t dxpl_id) { H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; H5O_efl_t *efl_dst = NULL; diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 9fa6108..f5569dc 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -63,6 +63,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_fill_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_fill_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ @@ -95,6 +96,7 @@ static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *s #undef H5O_SHARED_POST_COPY_FILE #define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #undef H5O_SHARED_DEBUG #define H5O_SHARED_DEBUG H5O_fill_new_shared_debug #undef H5O_SHARED_DEBUG_REAL diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 1b17bff..e912d8c 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -46,8 +46,8 @@ static herr_t H5O_layout_free(void *_mesg); static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_layout_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); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -587,8 +587,8 @@ done: */ static void * H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id) { H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */ H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src; diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index 4939bab..8eabc1b 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -46,10 +46,11 @@ static herr_t H5O_linfo_free(void *_mesg); static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_linfo_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, - void *udata, hid_t dxpl_id); -static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, - void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -379,8 +380,8 @@ done: */ static void * H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id) { H5O_linfo_t *linfo_src = (H5O_linfo_t *) native_src; H5O_linfo_t *linfo_dst = NULL; @@ -495,7 +496,8 @@ done: */ static herr_t H5O_linfo_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_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_linfo_t *linfo_src = (const H5O_linfo_t *)mesg_src; H5O_linfo_t *linfo_dst = (H5O_linfo_t *)mesg_dst; diff --git a/src/H5Olink.c b/src/H5Olink.c index ccc6d0e..88c9e28 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -49,10 +49,11 @@ static herr_t H5O_link_free(void *_mesg); static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_link_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, - hid_t dxpl_id); -static herr_t H5O_link_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); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); +static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -710,8 +711,8 @@ H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_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) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id) { H5O_link_t *link_src = (H5O_link_t *)native_src; void *ret_value; /* Return value */ @@ -751,7 +752,8 @@ done: */ static herr_t H5O_link_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_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_link_t *link_src = (const H5O_link_t *)mesg_src; H5O_link_t *link_dst = (H5O_link_t *)mesg_dst; diff --git a/src/H5Omessage.c b/src/H5Omessage.c index 8d1c318..48461fc 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -1865,7 +1865,7 @@ done: void * H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_src, H5F_t *file_dst, hbool_t *recompute_size, - H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) + unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) { void *ret_value; @@ -1883,7 +1883,7 @@ H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, /* The copy_file callback will return an H5O_shared_t only if the message * to be copied is a committed datatype. */ - if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id))) + if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata, dxpl_id))) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file") done: @@ -1996,7 +1996,7 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx, HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header") /* Update the message flags */ - idx_msg->flags = mesg_flags; + idx_msg->flags = (uint8_t)mesg_flags; /* Mark the message as modified */ idx_msg->dirty = TRUE; diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 34a413c..1b612fc 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -234,8 +234,8 @@ struct H5O_msg_class_t { herr_t (*set_share)(void*, const H5O_shared_t*); /* Set shared information */ htri_t (*can_share)(const void *); /* Is message allowed to be shared? */ herr_t (*pre_copy_file)(H5F_t *, const void *, hbool_t *, const H5O_copy_t *, void *); /*"pre copy" action when copying native value to file */ - void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, H5O_copy_t *, void *, hid_t); /*copy native value to file */ - herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ + void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, unsigned *, H5O_copy_t *, void *, hid_t); /*copy native value to file */ + herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, unsigned *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ herr_t (*get_crt_index)(const void *, H5O_msg_crt_idx_t *); /* Get message's creation index */ herr_t (*set_crt_index)(void *, H5O_msg_crt_idx_t); /* Set message's creation index */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); @@ -546,7 +546,7 @@ H5_DLL herr_t H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *ty int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id); H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, 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); + unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id); @@ -583,10 +583,12 @@ H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg); H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); + hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_shared_post_copy_file (H5F_t *f, const H5O_msg_class_t *mesg_type, const H5O_shared_t *shared_src, - H5O_shared_t *shared_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); + H5O_shared_t *shared_dst, unsigned *mesg_flags, hid_t dxpl_id, + H5O_copy_t *cpy_info); H5_DLL herr_t H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth); diff --git a/src/H5Opline.c b/src/H5Opline.c index 89ce865..f626106 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -61,6 +61,7 @@ static herr_t H5O_pline_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_pline_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_pline_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_pline_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 2640dee..ae31932 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -99,7 +99,9 @@ typedef struct H5O_t H5O_t; #endif /* H5O_ENABLE_BAD_MESG_COUNT */ /* ========= Object Copy properties ============ */ -#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ +#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ +#define H5O_CPY_MERGE_COMM_DT_LIST_NAME "merge committed dtype list" /* List of datatype paths to search in the dest file for merging */ +#define H5O_CPY_MCDT_SEARCH_CB_NAME "committed dtype list search" /* Callback function when the search for a matching committed datatype is complete */ /* If the module using this macro is allowed access to the private variables, access them directly */ #ifdef H5O_PACKAGE @@ -133,6 +135,18 @@ typedef struct H5O_loc_t { * its file's count of open objects. */ } H5O_loc_t; +/* Typedef for linked list of datatype merge suggestions */ +typedef struct H5O_copy_dtype_merge_list_t { + char *path; /* Path to datatype in destination file */ + struct H5O_copy_dtype_merge_list_t *next; /* Next object in list */ +} H5O_copy_dtype_merge_list_t; + +/* Structure for callback property before searching the global list of committed datatypes at destination */ +typedef struct H5O_mcdt_cb_info_t { + H5O_mcdt_search_cb_t func; + void *user_data; +} H5O_mcdt_cb_info_t; + /* Settings/flags for copying an object */ typedef struct H5O_copy_t { hbool_t copy_shallow; /* Flag to perform shallow hierarchy copy */ @@ -141,10 +155,16 @@ typedef struct H5O_copy_t { hbool_t expand_ref; /* Flag to expand object references */ hbool_t copy_without_attr; /* Flag to not copy attributes */ hbool_t preserve_null; /* Flag to not delete NULL messages */ + hbool_t merge_comm_dt; /* Flag to merge committed datatypes in dest file */ + H5O_copy_dtype_merge_list_t *dst_dt_suggestion_list; /* Suggestions for merging committed datatypes */ int curr_depth; /* Current depth in hierarchy copied */ int max_depth; /* Maximum depth in hierarchy to copy */ H5SL_t *map_list; /* Skip list to hold address mappings */ + H5SL_t *dst_dt_list; /* Skip list to hold committed datatypes in dest file */ + hbool_t dst_dt_list_complete; /* Whether the destination datatype list is complete (i.e. not only populated with "suggestions" from H5Padd_merge_committed_dtype_path) */ H5O_t *oh_dst; /* The destination object header */ + H5O_mcdt_search_cb_t mcdt_cb; /* The callback to invoke before searching the global list of committed datatypes at destination */ + void *mcdt_ud; /* User data passed to callback */ } H5O_copy_t; /* Header message IDs */ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index c5ae3c1..32945e8 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -43,7 +43,8 @@ #define H5O_COPY_EXPAND_REFERENCE_FLAG (0x0008u) /* Copy objects that are pointed by references */ #define H5O_COPY_WITHOUT_ATTR_FLAG (0x0010u) /* Copy object without copying attributes */ #define H5O_COPY_PRESERVE_NULL_FLAG (0x0020u) /* Copy NULL messages (empty space) */ -#define H5O_COPY_ALL (0x003Fu) /* All object copying flags (for internal checking) */ +#define H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG (0x0040u) /* Merge committed datatypes in dest file */ +#define H5O_COPY_ALL (0x007Fu) /* All object copying flags (for internal checking) */ /* Flags for shared message indexes. * Pass these flags in using the mesg_type_flags parameter in @@ -131,6 +132,14 @@ typedef uint32_t H5O_msg_crt_idx_t; typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info, void *op_data); +typedef enum H5O_mcdt_search_ret_t { + H5O_MCDT_SEARCH_ERROR = -1, /* Abort H5Ocopy */ + H5O_MCDT_SEARCH_CONT, /* Continue the global search of all committed datatypes in the destination file */ + H5O_MCDT_SEARCH_STOP /* Stop the search, but continue copying. The committed datatype will be copied but not merged. */ +} H5O_mcdt_search_ret_t; + +/* Callback to invoke when completing the search for a matching committed datatype from the committed dtype list */ +typedef H5O_mcdt_search_ret_t (*H5O_mcdt_search_cb_t)(void *op_data); /********************/ /* Public Variables */ diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 8ae73f7..905c4e9 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -55,6 +55,7 @@ static herr_t H5O_sdspace_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #undef H5O_SHARED_COPY_FILE_REAL #define H5O_SHARED_POST_COPY_FILE H5O_sdspace_shared_post_copy_file #undef H5O_SHARED_POST_COPY_FILE_REAL +#undef H5O_SHARED_POST_COPY_FILE_UPD #define H5O_SHARED_DEBUG H5O_sdspace_shared_debug #define H5O_SHARED_DEBUG_REAL H5O_sdspace_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 45c0a7d..8a18c4a 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -589,8 +589,8 @@ done: herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void UNUSED *udata, hid_t dxpl_id) { const H5O_shared_t *shared_src = (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */ H5O_shared_t *shared_dst = (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */ @@ -618,13 +618,15 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, */ if(shared_src->type != H5O_SHARE_TYPE_COMMITTED) { /* Simulate trying to share new message in the destination file. */ - if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, NULL) < 0) + if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, mesg_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared") } /* end if */ - else + else { /* Mark the message as committed - as it will be committed in post copy */ H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, HADDR_UNDEF) + *mesg_flags |= H5O_MSG_FLAG_SHARED; + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -651,8 +653,8 @@ done: */ herr_t H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, - const H5O_shared_t *shared_src, H5O_shared_t *shared_dst, hid_t dxpl_id, - H5O_copy_t *cpy_info) + const H5O_shared_t *shared_src, H5O_shared_t *shared_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info) { herr_t ret_value = SUCCEED; /* Return value */ @@ -669,6 +671,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, H5O_loc_t src_oloc; /* Copy the shared object from source to destination */ + H5O_loc_reset(&dst_oloc); dst_oloc.file = f; src_oloc.file = shared_src->file; src_oloc.addr = shared_src->u.loc.oh_addr; @@ -682,7 +685,7 @@ H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type, else /* Share the message */ if(H5SM_try_share(f, dxpl_id, NULL, H5SM_WAS_DEFERRED, mesg_type->id, - shared_dst, NULL) < 0) + shared_dst, mesg_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message") done: diff --git a/src/H5Oshared.h b/src/H5Oshared.h index ddacc25..3ec5709 100644 --- a/src/H5Oshared.h +++ b/src/H5Oshared.h @@ -320,7 +320,8 @@ done: */ static H5_inline void * H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst, - hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) + hbool_t *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id) { void *dst_mesg = NULL; /* Destination message */ void *ret_value; /* Return value */ @@ -348,8 +349,8 @@ H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst, HDmemset(dst_mesg, 0, sizeof(H5O_shared_t)); /* Handle sharing destination message */ - if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, - _native_src, dst_mesg, recompute_size, cpy_info, udata, dxpl_id) < 0) + if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, _native_src, + dst_mesg, recompute_size, mesg_flags, cpy_info, udata, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "unable to determine if message should be shared") /* Set return value */ @@ -383,7 +384,8 @@ done: */ static H5_inline herr_t H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, - H5O_loc_t *oloc_dst, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) + H5O_loc_t *oloc_dst, void *mesg_dst, unsigned *mesg_flags, hid_t dxpl_id, + H5O_copy_t *cpy_info) { const H5O_shared_t *shared_src = (const H5O_shared_t *)mesg_src; /* Alias to shared info in native source */ H5O_shared_t *shared_dst = (H5O_shared_t *)mesg_dst; /* Alias to shared info in native destination */ @@ -405,7 +407,7 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, #endif /* H5O_SHARED_POST_COPY_FILE */ #ifdef H5O_SHARED_POST_COPY_FILE_REAL - /* Call native message's copy file callback to copy the message */ + /* Call native message's post copy file callback to copy the message */ if(H5O_SHARED_POST_COPY_FILE_REAL(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) <0 ) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy native message to another file") #endif /* H5O_SHARED_POST_COPY_FILE_REAL */ @@ -414,9 +416,16 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src, * production if the DEFER pass determined it will not be shared; debug mode * verifies that it is indeed the case */ if(H5O_shared_post_copy_file(oloc_dst->file, H5O_SHARED_TYPE, - shared_src, shared_dst, dxpl_id, cpy_info) < 0) + shared_src, shared_dst, mesg_flags, dxpl_id, cpy_info) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to fix shared message in post copy") +#ifdef H5O_SHARED_POST_COPY_FILE_UPD + /* Call native message's post copy file update callback to update the + * message */ + if(H5O_SHARED_POST_COPY_FILE_UPD(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to update native message") +#endif /* H5O_SHARED_POST_COPY_FILE_UPD */ + /* Make sure that if the the source or destination is committed, both are * committed */ HDassert((shared_src->type == H5O_SHARE_TYPE_COMMITTED) diff --git a/src/H5Ostab.c b/src/H5Ostab.c index c43a76b..bb0c22d 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -44,10 +44,11 @@ static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void * static herr_t H5O_stab_free(void *_mesg); static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *_udata, - hid_t dxpl_id); -static herr_t H5O_stab_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); + H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags, + H5O_copy_t *cpy_info, void *_udata, hid_t dxpl_id); +static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, + const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, + unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -307,8 +308,8 @@ done: */ static void * H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, - hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void *_udata, - hid_t dxpl_id) + hbool_t UNUSED *recompute_size, unsigned UNUSED *mesg_flags, + H5O_copy_t UNUSED *cpy_info, void *_udata, hid_t dxpl_id) { H5O_stab_t *stab_src = (H5O_stab_t *) native_src; H5O_stab_t *stab_dst = NULL; @@ -364,8 +365,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_stab_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_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, + H5O_loc_t *dst_oloc, void *mesg_dst, unsigned UNUSED *mesg_flags, + hid_t dxpl_id, H5O_copy_t *cpy_info) { const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src; H5O_stab_t *stab_dst = (H5O_stab_t *)mesg_dst; diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index 6a3067d..32793e6 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -392,7 +392,7 @@ H5P_dcrt_layout_cmp(const void *_layout1, const void *_layout2, size_t UNUSED si /* Sanity check */ HDassert(layout1); - HDassert(layout1); + HDassert(layout2); HDassert(size == sizeof(H5O_layout_t)); /* Check for different layout type */ diff --git a/src/H5Pocpypl.c b/src/H5Pocpypl.c index af50d80..e61a0d7 100644 --- a/src/H5Pocpypl.c +++ b/src/H5Pocpypl.c @@ -35,7 +35,9 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ @@ -47,7 +49,13 @@ /* Definitions for copy options */ #define H5O_CPY_OPTION_SIZE sizeof(unsigned) #define H5O_CPY_OPTION_DEF 0 - +/* Definitions for merge committed dtype list */ +#define H5O_CPY_MERGE_COMM_DT_LIST_SIZE sizeof(char *) +#define H5O_CPY_MERGE_COMM_DT_LIST_DEF NULL +#define H5O_CPY_MERGE_COMM_DT_LIST_CMP H5P_ocpy_merge_comm_dt_list_cmp +/* Definitions for callback function when completing the search for a matching committed datatype from the committed dtype list */ +#define H5O_CPY_MCDT_SEARCH_CB_SIZE sizeof(H5O_mcdt_cb_info_t) +#define H5O_CPY_MCDT_SEARCH_CB_DEF {NULL,NULL} /******************/ /* Local Typedefs */ @@ -63,8 +71,17 @@ /* Local Prototypes */ /********************/ +/* General routines */ +static H5O_copy_dtype_merge_list_t *H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list); + /* Property class callbacks */ static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass); +static herr_t H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, + void *copy_data); +static herr_t H5P_ocpy_close(hid_t ocpypl_id, void *close_data); + +/* Property callbacks */ +static int H5P_ocpy_merge_comm_dt_list_cmp(const void *value1, const void *value2, size_t size); /*********************/ @@ -80,9 +97,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ H5P_ocpy_reg_prop, /* Default property registration routine */ NULL, /* Class creation callback */ NULL, /* Class creation callback info */ - NULL, /* Class copy callback */ + H5P_ocpy_copy, /* Class copy callback */ NULL, /* Class copy callback info */ - NULL, /* Class close callback */ + H5P_ocpy_close, /* Class close callback */ NULL /* Class close callback info */ }}; @@ -96,6 +113,9 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ /* Local Variables */ /*******************/ +/* Declare a free list to manage the H5O_copy_dtype_merge_list_t struct */ +H5FL_DEFINE(H5O_copy_dtype_merge_list_t); + /*------------------------------------------------------------------------- @@ -109,10 +129,12 @@ const H5P_libclass_t H5P_CLS_OCPY[1] = {{ * October 31, 2006 *------------------------------------------------------------------------- */ -herr_t +static herr_t H5P_ocpy_reg_prop(H5P_genclass_t *pclass) { unsigned ocpy_option = H5O_CPY_OPTION_DEF; /* Default object copy flags */ + H5O_copy_dtype_merge_list_t *merge_comm_dtype_list = H5O_CPY_MERGE_COMM_DT_LIST_DEF; /* Default merge committed dtype list */ + H5O_mcdt_cb_info_t mcdt_cb = H5O_CPY_MCDT_SEARCH_CB_DEF; /* Default callback before searching the global list of committed datatypes at destination */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -121,12 +143,222 @@ H5P_ocpy_reg_prop(H5P_genclass_t *pclass) if(H5P_register_real(pclass, H5O_CPY_OPTION_NAME, H5O_CPY_OPTION_SIZE, &ocpy_option, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register merge named dtype list property */ + if(H5P_register_real(pclass, H5O_CPY_MERGE_COMM_DT_LIST_NAME, H5O_CPY_MERGE_COMM_DT_LIST_SIZE, &merge_comm_dtype_list, NULL, NULL, NULL, NULL, NULL, H5O_CPY_MERGE_COMM_DT_LIST_CMP, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register property for callback when completing the search for a matching named datatype from the named dtype list */ + if(H5P_register_real(pclass, H5O_CPY_MCDT_SEARCH_CB_NAME, H5O_CPY_MCDT_SEARCH_CB_SIZE, &mcdt_cb, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_ocpy_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P_ocpy_copy + * + * Purpose: Callback routine which is called whenever any object + * copy property list is copied. This routine copies + * the properties from the old list to the new list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data) +{ + H5O_copy_dtype_merge_list_t *src_dt_list, *dst_dt_list = NULL; /* Source & destination merge named datatype lists */ + H5O_copy_dtype_merge_list_t *dst_dt_list_tail = NULL, *tmp_dt_list = NULL; /* temporary merge named datatype lists */ + H5P_genplist_t *src_plist; /* Pointer to source property list */ + H5P_genplist_t *dst_plist; /* Pointer to destination property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Verify property list IDs */ + if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge committed dtype list property from the old property list */ + if(H5P_get(src_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &src_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Make copy of merge committed dtype list */ + while(src_dt_list) { + /* Copy src_dt_list */ + if(NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (tmp_dt_list->path = H5MM_strdup(src_dt_list->path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Add copied node to dest dtype list */ + if(dst_dt_list_tail) { + dst_dt_list_tail->next = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end if */ + else { + dst_dt_list = tmp_dt_list; + dst_dt_list_tail = tmp_dt_list; + } /* end else */ + tmp_dt_list = NULL; + + /* Advance src_dt_list pointer */ + src_dt_list = src_dt_list->next; + } /* end while */ + + /* Set the merge named dtype list property for the destination property list + */ + if(H5P_set(dst_plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dst_dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + if(ret_value < 0) { + dst_dt_list = H5P_free_merge_comm_dtype_list(dst_dt_list); + if(tmp_dt_list) { + tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path); + tmp_dt_list = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_close + * + * Purpose: Callback routine which is called whenever any object copy + * property list is closed. This routine performs any generic + * cleanup needed on the properties the library put into the + * list. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5P_ocpy_close(hid_t ocpypl_id, void UNUSED *close_data) +{ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge named datatype list */ + H5P_genplist_t *plist; /* Property list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(ocpypl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object copy property list") + + /* Get the merge named dtype list property from the old property list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Free the merge named dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_ocpy_merge_comm_dt_list_cmp + * + * Purpose: Callback routine which is called whenever the merge + * named dtype property in the object copy property list + * is compared. + * + * Return: positive if VALUE1 is greater than VALUE2, negative if + * VALUE2 is greater than VALUE1 and zero if VALUE1 and + * VALUE2 are equal. + * + * Programmer: Neil Fortner + * Friday, October 28, 2011 + * + *------------------------------------------------------------------------- + */ +static int +H5P_ocpy_merge_comm_dt_list_cmp(const void *_dt_list1, const void *_dt_list2, + size_t UNUSED size) +{ + const H5O_copy_dtype_merge_list_t *dt_list1 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list1, /* Create local aliases for values */ + *dt_list2 = *(H5O_copy_dtype_merge_list_t * const *)_dt_list2; + herr_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(_dt_list1); + HDassert(_dt_list2); + HDassert(size == sizeof(H5O_copy_dtype_merge_list_t *)); + + /* Walk through the lists, comparing each path. For the lists to be the + * same, the paths must be in the same order. */ + while(dt_list1 && dt_list2) { + /* Compare paths */ + ret_value = HDstrcmp(dt_list1->path, dt_list2->path); + if(ret_value != 0) HGOTO_DONE(ret_value) + + /* Advance to next node */ + dt_list1 = dt_list1->next; + dt_list2 = dt_list2->next; + } /* end while */ + + /* Check if one list is longer than the other */ + if(dt_list1) HGOTO_DONE(1) + if(dt_list2) HGOTO_DONE(-1) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_ocpy_merge_comm_dt_list_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_free_merge_comm_dtype_list + * + * Purpose: Frees the provided merge named dtype list + * + * Return: NULL + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +static H5O_copy_dtype_merge_list_t * +H5P_free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list) +{ + H5O_copy_dtype_merge_list_t *tmp_node; + + FUNC_ENTER_NOAPI_NOINIT + + /* Free the list */ + while(dt_list) { + tmp_node = dt_list->next; + (void)H5MM_xfree(dt_list->path); + (void)H5FL_FREE(H5O_copy_dtype_merge_list_t, dt_list); + dt_list = tmp_node; + } /* end while */ + + FUNC_LEAVE_NOAPI(NULL); +} /* H5P_free_merge_comm_dtype_list */ + + +/*------------------------------------------------------------------------- * Function: H5Pset_copy_object * * Purpose: Set properties when copying an object (group, dataset, and datatype) @@ -207,3 +439,206 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_copy_object() */ + +/*------------------------------------------------------------------------- + * Function: H5Padd_merge_committed_dtype_path + * + * Purpose: Adds path to the list of paths to search first in the + * target file when merging committed datatypes during H5Ocopy + * (i.e. when using the H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG flag + * as set by H5Pset_copy_object). If the source named + * dataype is not found in the list of paths created by this + * function, the entire file will be searched. + * + * Usage: H5Padd_merge_committed_dtype_path(plist_id, path) + * hid_t plist_id; IN: Property list to copy object + * const char *path; IN: Path to add to list + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *old_list; /* Merge committed dtype list currently present */ + H5O_copy_dtype_merge_list_t *new_obj = NULL; /* New object to add to list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check parameters */ + if(!path) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no path specified") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &old_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list") + + /* Add the new path to the list */ + if(NULL == (new_obj = H5FL_CALLOC(H5O_copy_dtype_merge_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (new_obj->path = H5MM_strdup(path))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + new_obj->next = old_list; + + /* Update the list stored in the property list */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &new_obj) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge named dtype list") + +done: + if(ret_value < 0) + if(new_obj) { + new_obj->path = (char *)H5MM_xfree(new_obj->path); + new_obj = H5FL_FREE(H5O_copy_dtype_merge_list_t, new_obj); + } /* end if */ + + FUNC_LEAVE_API(ret_value) +} /* end H5Padd_merge_committed_dtype_path() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pfree_merge_committed_dtype_paths + * + * Purpose: Frees and clears the list of paths created by + * H5Padd_merge_committed_dtype_path. A new list may then be + * created by calling H5Padd_merge_committed_dtype_path again. + * + * Usage: H5Pfree_merge_committed_dtype_paths(plist_id) + * hid_t plist_id; IN: Property list to copy object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * October 27, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pfree_merge_committed_dtype_paths(hid_t plist_id) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_copy_dtype_merge_list_t *dt_list; /* Merge committed dtype list currently present */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get dtype list */ + if(H5P_get(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed dtype list") + + /* Free dtype list */ + dt_list = H5P_free_merge_comm_dtype_list(dt_list); + + /* Update the list stored in the property list (to NULL) */ + if(H5P_set(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pfree_merge_committed_dtype_paths() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_mcdt_search_cb + * + * Purpose: Set the callback function when a matching committed datatype is not found + * from the list of paths stored in the object copy property list. + * H5Ocopy will invoke this callback before searching all committed datatypes + * at destination. + * + * Usage: H5Pset_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t func, void *op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t func; IN: The callback function + * void *op_data; IN: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 28, 2011 + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check if the callback function is NULL and the user data is non-NULL. + * This is almost certainly an error as the user data will not be used. */ + if(!func && op_data) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not") + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Populate the callback info struct */ + cb_info.func = func; + cb_info.user_data = op_data; + + /* Set callback info */ + if(H5P_set(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_mcdt_search_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_mcdt_search_cb + * + * Purpose: Retrieves the callback function and user data from the specified + * object copy property list. + * + * Usage: H5Pget_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t *func, void **op_data) + * hid_t plist_id; IN: Property list to copy object + * H5O_mcdt_search_cb_t *func; OUT: The callback function + * void **op_data; OUT: The user data + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; November 29, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_mcdt_cb_info_t cb_info; /* Callback info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get callback info */ + if(H5P_get(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info") + + if(func) + *func = cb_info.func; + + if(op_data) + *op_data = cb_info.user_data; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_mcdt_search_cb() */ + diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 53818f1..e33b685 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -30,6 +30,7 @@ #include "H5FDpublic.h" #include "H5Ipublic.h" #include "H5Lpublic.h" +#include "H5Opublic.h" #include "H5MMpublic.h" #include "H5Tpublic.h" #include "H5Zpublic.h" @@ -428,6 +429,10 @@ H5_DLL herr_t H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void ** /* Object copy property list (OCPYPL) routines */ H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned crt_intmd); H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *crt_intmd /*out*/); +H5_DLL herr_t H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path); +H5_DLL herr_t H5Pfree_merge_committed_dtype_paths(hid_t plist_id); +H5_DLL herr_t H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data); +H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data); /* Symbols defined for compatibility with previous versions of the HDF5 API. * diff --git a/src/H5SM.c b/src/H5SM.c index 2fcaf7a..46e3140 100644 --- a/src/H5SM.c +++ b/src/H5SM.c @@ -1099,7 +1099,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags, /* 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 && !(defer_flags & H5SM_DEFER)) { + if(mesg_flags) { if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE) *mesg_flags |= H5O_MSG_FLAG_SHAREABLE; else { @@ -1109,7 +1109,8 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned defer_flags, } /* end if */ done: - HDassert(!ret_value || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE + HDassert((ret_value != TRUE) + || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE || ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_SOHM); #ifndef NDEBUG /* If we previously deferred this operation, make sure the saved message diff --git a/test/objcopy.c b/test/objcopy.c index 5807947..0501f89 100644 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -47,6 +47,7 @@ const char *FILENAME[] = { "objcopy_src", "objcopy_dst", "objcopy_ext", + "objcopy_src2", NULL }; @@ -73,6 +74,7 @@ const char *FILENAME[] = { #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_SIMPLE3 "dataset_simple_another_copy" #define NAME_DATASET_COMPOUND "dataset_compound" #define NAME_DATASET_CHUNKED "dataset_chunked" #define NAME_DATASET_CHUNKED2 "dataset_chunked2" @@ -90,6 +92,8 @@ const char *FILENAME[] = { #define NAME_GROUP_EMPTY "/empty" #define NAME_GROUP_TOP "/g0" #define NAME_GROUP_TOP2 "/g1" +#define NAME_GROUP_TOP3 "/g2" +#define NAME_GROUP_TOP4 "/g3" #define NAME_GROUP_SUB "/g0/g00" #define NAME_GROUP_SUB_2 "/g0/g01" #define NAME_GROUP_SUB_SUB "/g0/g00/g000" @@ -8272,6 +8276,3190 @@ error: /*------------------------------------------------------------------------- + * Function: test_copy_committed_datatype_merge + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Tuesday, October 11, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_datatype_merge(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src1 = -1, fid_src2 = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src1_filename[NAME_BUF_SIZE]; + char src2_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + if(reopen) { + TESTING("H5Ocopy(): merging committed datatypes with reopen") + } /* end if */ + else + TESTING("H5Ocopy(): merging committed datatypes") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src1_filename, sizeof src1_filename); + h5_fixname(FILENAME[3], src_fapl, src2_filename, sizeof src2_filename); + h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source files */ + if((fid_src1 = H5Fcreate(src1_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + if((fid_src2 = H5Fcreate(src2_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file 1 + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src1, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src1, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file 1 */ + if(H5Fclose(fid_src1) < 0) TEST_ERROR + + /* + * Populate source file 2 + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src2, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src2, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file 1 */ + if(H5Fclose(fid_src2) < 0) TEST_ERROR + + + /* open the source files with read-only */ + if((fid_src1 = H5Fopen(src1_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + if((fid_src2 = H5Fopen(src2_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge named dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy each entire file to the destination file (each with their own + * group), and verify the committed datatypes are merged + */ + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, 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 SRC1 to DST */ + if(H5Ocopy(fid_src1, "/", fid_dst, NAME_GROUP_TOP, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid_src2, "/", fid_dst, NAME_GROUP_TOP2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open SRC1 committed dtype, get address */ + if((tid = H5Topen2(fid_dst, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open SRC1 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open SRC2 committed dtype, check address */ + if((tid = H5Topen2(fid_dst, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open SRC2 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Now copy only the datasets to the destination file, and verify the committed + * datatypes are merged + */ + /* recreate destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, 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 SRC1 to DST */ + if(H5Ocopy(fid_src1, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid_src2, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open SRC1 dset dtype, get address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open SRC2 dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC files */ + if(H5Fclose(fid_src1) < 0) TEST_ERROR + if(H5Fclose(fid_src2) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src1); + H5Fclose(fid_src2); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_datatype_merge */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_datatype_merge_same_file + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, + * while copying to the same file. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Tuesday, October 11, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_datatype_merge_same_file(hid_t fcpl, hid_t fapl, hbool_t reopen) +{ + hid_t fid = -1; /* File ID */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t gid = -1; /* Group ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes to the source file with reopen") + else + TESTING("H5Ocopy(): merging committed datatypes to the source file") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filename */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create file */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate first group + */ + /* Create group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset */ + if((did = H5Dcreate2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* + * Populate second group + */ + /* Create group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset */ + if((did = H5Dcreate2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy each group to the destination group 3 (each with their own + * group), and verify the committed datatypes are merged as expected. All + * datatypes copied should reference (share an address with) the + * corresponding source datatype. + */ + /* Create destination group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* copy group 1 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP, fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy group 2 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP2, fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid) < 0) TEST_ERROR + if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open group 1 source committed dtype, get address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 1 source dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 1 committed dtype, check address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 1 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 source committed dtype, get address and make sure it is + * different from group 1 source committed dtype */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 2 source dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 committed dtype, check address */ + if((tid = H5Topen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2 "/" NAME_DATATYPE_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open group 2 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP3 "/" NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* + * Now copy only the datasets to the destination group, and verify the committed + * datatypes are merged as expected + */ + /* Create destination group */ + if((gid = H5Gcreate2(fid, NAME_GROUP_TOP4, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* copy SRC1 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC2 to DST */ + if(H5Ocopy(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid) < 0) TEST_ERROR + if((fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open group 1 source dset dtype, get address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 1 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 source dset dtype, get address and make sure it is + * different from group 1 source dset dtype */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP2 "/" NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open group 2 dset dtype, check address */ + if((did = H5Dopen2(fid, NAME_GROUP_TOP4 "/" NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_datatype_merge_same_file */ + + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_dt_merge_sugg + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, and + * uses the suggestion list feature + * (H5Padd_merge_committed_dtype_path). + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Thursday, November 3, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_dt_merge_sugg(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes with suggestions and reopen") + else + TESTING("H5Ocopy(): merging committed datatypes with suggestions") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_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, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Now free suggestions, copy dataset without any suggestions, and verify + * that it uses datatype "a" in the destination file + */ + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete destination dataset */ + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset 2 dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_dt_merge_sugg */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_committed_dt_merge_attr + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy, with + * an attribute using an anonymous committed type in the + * destination. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Neil Fortner + * Thursday, November 3, 2011 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_committed_dt_merge_attr(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t aid = -1; /* Attribute ID */ + hid_t gid = -1; /* Group ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + if(reopen) + TESTING("H5Ocopy(): merging committed datatypes with attributes and reopen") + else + TESTING("H5Ocopy(): merging committed datatypes with attributes") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_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, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* Create group */ + if((gid = H5Gcreate2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* create anonymous committed data type */ + if((H5Tcommit_anon(fid_dst, tid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create attribute at SRC file */ + if((aid = H5Acreate2(gid, "attr", tid, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Awrite(aid, tid, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the attribute */ + if(H5Aclose(aid) < 0) TEST_ERROR + + /* close the group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * Copy dataset and verify that it uses the same committed datatype as the + * already existing attribute in the destination file. + */ + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open attribute dtype, get address */ + if((aid = H5Aopen_by_name(fid_dst, NAME_GROUP_TOP, "attr", H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Aget_type(aid)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Aclose(aid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Aclose(aid); + H5Gclose(gid); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_committed_dt_merge_attr */ + +/* + * Defines used for the committed datatype tests + */ +#define SRC_ROOT_GROUP "src_root" +#define ROOT_NDT_INT "root_ndt_int" +#define GROUP_NDT_SHORT "group_ndt_short" + +#define SRC_GRP "src_grp" +#define DST_GRP "dst_grp" +#define DST_GRP2 "dst_grp2" + +#define SRC_NDT_SHORT "src_ndt_short" +#define SRC_NDT_INT "src_ndt_int" +#define SRC_NDT_INT2 "src_ndt_int2" +#define SRC_NDT_FLOAT "src_ndt_float" +#define SRC_NDT_DOUBLE "src_ndt_double" + +#define DST_NDT_SHORT "dst_ndt_short" +#define DST_NDT_INT "dst_ndt_int" +#define DST_NDT_FLOAT "dst_ndt_float" +#define DST_NDT_DOUBLE "dst_ndt_double" + +#define SRC_NDT_DSET "src_ndt_dset" +#define SRC_NDT_DSET2 "src_ndt_dset2" +#define SRC_NDT_DSET3 "src_ndt_dset3" + +#define SRC_DSET "src_dset" +#define SRC_DSET1 "src_dset1" + +#define SRC_ATTR "src_attr" + +#define DST_ATTR_ANON_SHORT "dst_attr_anon_short" +#define DST_ATTR_ANON_INT "dst_attr_anon_int" + +#define DST_ATTR "dst_attr" +#define DST_ATTR2 "dst_attr2" + +/*------------------------------------------------------------------------- + * Function: test_copy_cdt_hier_merge + * + * Purpose: Tests the "merge committed datatypes" feature of H5Ocopy: + * SRC file: + * Create committed datatypes at / and /g0 + * Create datasets with native type and committed datatypes at /g0 + * DST file: + * Create attributes with anonymous committed datatypes at /uncopied + * + * Copy / at SRC to DST + * Copy /g0 at SRC to DST + * Copy the datasets in /g0 at SRC to DST /uncopied + * Verify that committed datatypes are copied and merged correctly + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; January 2012 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_cdt_hier_merge(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t gid = -1; /* Group IDs */ + hid_t f_tid = -1; /* Datatype ID for root group */ + hid_t g_tid = -1; /* Datatype ID for group */ + hid_t anon_tid = -1; /* Anonymous datatype */ + hid_t aid = -1; /* Attribute ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + int i; /* Local index variable */ + hsize_t dim1d[1]; /* dimension sizes */ + int buf[DIM_SIZE_1]; /* Buffer for data */ + haddr_t exp_addr_int, exp_addr_short; /* Expected object addresses */ + H5O_info_t oinfo; /* Object info */ + char src_filename[NAME_BUF_SIZE]; /* Source file name */ + char dst_filename[NAME_BUF_SIZE]; /* Destination file name */ + + if(reopen) + TESTING("H5Ocopy(): hier. of committed datatypes and merging with reopen") + else + TESTING("H5Ocopy(): hier. of committed datatypes and merging ") + + /* set initial data values */ + for (i=0; icalled++; + return(udata->search_action); +} /* mcdt_search_cb() */ + +static int +test_copy_set_mcdt_search_cb(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + H5O_info_t oinfo; /* Object info */ + haddr_t exp_addr; /* Expected object address */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + mcdt_search_cb_ud cb_udata; /* User data for callback */ + + if(reopen) + TESTING("H5Ocopy(): H5Pset_mcdt_search_cb and reopen") + else + TESTING("H5Ocopy(): H5Pset_mcdt_search_cb") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_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, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* named data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied group in destination file */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open dset dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Set callback to continue the search + */ + cb_udata.search_action = H5O_MCDT_SEARCH_CONT; + cb_udata.called = 0; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* Add datatype suggestion to group "/uncopied" */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, NAME_GROUP_UNCOPIED) < 0) TEST_ERROR + + /* Continue the global search */ + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cb, &cb_udata) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open copied dataset and its dtype, check address */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE2, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr != exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype + */ + cb_udata.search_action = H5O_MCDT_SEARCH_STOP; + cb_udata.called = 0; + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype. + * Disable suggestion list. + */ + cb_udata.search_action = H5O_MCDT_SEARCH_STOP; + cb_udata.called = 0; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete dataset */ + if(H5Ldelete(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify callback has been called exactly once */ + if(cb_udata.called != 1) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Open committed dtype "a", get address */ + if((tid = H5Topen2(fid_dst, "/a", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Open committed dtype "b", get address */ + if((tid = H5Topen2(fid_dst, "/b", H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + exp_addr = oinfo.addr; + if(H5Tclose(tid) < 0) TEST_ERROR + + /* Open the copied dataset and get its dtype, addresses should not be equal */ + if((did = H5Dopen2(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT)) < 0) TEST_ERROR + if((tid = H5Dget_type(did)) < 0) TEST_ERROR + if(H5Oget_info(tid, &oinfo) < 0) TEST_ERROR + if(oinfo.addr == exp_addr) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_set_mcdt_search_cb */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_set_get_mcdt_cb + * + * Purpose: Tests for the "H5Pset/get_mcdt_search_cb" feature of H5Ocopy. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; January 2012 + * + *------------------------------------------------------------------------- + */ + +/* The user callback functions */ +static H5O_mcdt_search_ret_t +mcdt_search_cbA(void *_udata) +{ + H5O_mcdt_search_ret_t *action = (H5O_mcdt_search_ret_t *)_udata; + + return(*action); +} /* mcdt_search_cb() */ + +static H5O_mcdt_search_ret_t +mcdt_search_cbB(void *_udata) +{ + H5O_mcdt_search_ret_t *action = (H5O_mcdt_search_ret_t *)_udata; + + return(*action); +} /* mnt_search_cb() */ + +/* The main test function */ +static int +test_copy_set_get_mcdt_search_cb(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, + hid_t dst_fapl, hbool_t reopen) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1; /* Datatype ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + hid_t ocpypl_id = -1; /* Object copy plist ID */ + unsigned int i; /* Local index variables */ + hsize_t dim1d[1]; /* Dataset dimensions */ + int buf[DIM_SIZE_1]; /* Buffer for writing data */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + H5O_mcdt_search_cb_t mcdt_cb = NULL; /* The callback function */ + H5O_mcdt_search_ret_t mcdt_udataA; /* User data for callback */ + H5O_mcdt_search_ret_t mcdt_udataB; /* User data for callback */ + H5O_mcdt_search_ret_t *mcdt_udata_p = NULL; /* Pointer to user data for callback */ + + if(reopen) + TESTING("H5Ocopy(): H5Pset/get_mcdt_search_cb and reopen") + else + TESTING("H5Ocopy(): H5Pset/get_mcdt_search_cb") + + /* set initial data values */ + for(i = 0; i < DIM_SIZE_1; i++) + buf[i] = (int)i; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], dst_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, src_fapl)) < 0) TEST_ERROR + + /* Set dataspace dimensions */ + dim1d[0]=DIM_SIZE_1; + + /* create dataspace */ + if((sid = H5Screate_simple(1, dim1d, NULL)) < 0) TEST_ERROR + + /* + * Populate source file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type */ + if((H5Tcommit2(fid_src, NAME_DATATYPE_SIMPLE, tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* create dataset at SRC file */ + if((did = H5Dcreate2(fid_src, NAME_DATASET_SIMPLE, tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* write data into file */ + if(H5Dwrite(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the dataset */ + if(H5Dclose(did) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* create destination file */ + if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR + + /* Create an uncopied group in destination file */ + if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* + * Populate destination file + */ + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "a" */ + if((H5Tcommit2(fid_dst, "/a", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* create datatype */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0)TEST_ERROR + + /* committed data type "b" */ + if((H5Tcommit2(fid_dst, "/b", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + + /* close the datatype */ + if(H5Tclose(tid) < 0) TEST_ERROR + + /* close the DST file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* open the source file with read-only */ + if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR + + /* Create ocpl and set merge committed dtype flag */ + if((ocpypl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR + if(H5Pset_copy_object(ocpypl_id, H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG) < 0) TEST_ERROR + + /* + * First copy dataset using "/b" as a suggestion, and verify that it uses + * datatype "b" in the destination file + */ + /* Add datatype suggestion */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, "/b") < 0) TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != NULL) TEST_ERROR + if(mcdt_udata_p != NULL) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* + * Set callback to continue the search + */ + mcdt_udataA = H5O_MCDT_SEARCH_CONT; + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + /* Add datatype suggestion to group "/uncopied" */ + if(H5Padd_merge_committed_dtype_path(ocpypl_id, NAME_GROUP_UNCOPIED) < 0) TEST_ERROR + + /* Continue the global search */ + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbA, &mcdt_udataA) < 0) + TEST_ERROR + + /* open the destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE2, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbA) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataA) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + + /* + * Stop the search, default action is to create an anonymous committed datatype + */ + mcdt_udataB = H5O_MCDT_SEARCH_STOP; + + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbA, &mcdt_udataB) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbA) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataB) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* Free suggestions */ + if(H5Pfree_merge_committed_dtype_paths(ocpypl_id) < 0) TEST_ERROR + + if(H5Pset_mcdt_search_cb(ocpypl_id, mcdt_search_cbB, &mcdt_udataB) < 0) + TEST_ERROR + + /* open destination file */ + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDWR, dst_fapl)) < 0) TEST_ERROR + + /* Delete dataset */ + if(H5Ldelete(fid_dst, NAME_DATASET_SIMPLE3, H5P_DEFAULT) < 0) TEST_ERROR + + /* copy SRC dset to DST */ + if(H5Ocopy(fid_src, NAME_DATASET_SIMPLE, fid_dst, NAME_DATASET_SIMPLE3, ocpypl_id, H5P_DEFAULT) < 0) TEST_ERROR + + if(reopen) { + /* Reopen file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + if((fid_dst = H5Fopen(dst_filename, H5F_ACC_RDONLY, dst_fapl)) < 0) TEST_ERROR + } /* end if */ + + mcdt_cb = NULL; + mcdt_udata_p = NULL; + + /* Verify "get" routine functionality */ + if(H5Pget_mcdt_search_cb(ocpypl_id, &mcdt_cb, (void **) &mcdt_udata_p) < 0) TEST_ERROR + + if(mcdt_cb != mcdt_search_cbB) TEST_ERROR + if(mcdt_udata_p != &mcdt_udataB) TEST_ERROR + + /* Close destination file */ + if(H5Fclose(fid_dst) < 0) TEST_ERROR + + /* close the SRC file */ + if(H5Fclose(fid_src) < 0) TEST_ERROR + + /* close property list */ + if(H5Pclose(ocpypl_id) < 0) TEST_ERROR + + /* close dataspace */ + if(H5Sclose(sid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid_src); + H5Fclose(fid_dst); + H5Tclose(tid); + H5Sclose(sid); + H5Dclose(did); + H5Pclose(ocpypl_id); + } H5E_END_TRY; + return 1; +} /* end test_copy_set_get_mcdt_search_cb */ + + +/*------------------------------------------------------------------------- * Function: test_copy_option * * Purpose: Create a group in SRC file and copy it to DST file @@ -8589,6 +11777,7 @@ main(void) unsigned max_compact, min_dense; int configuration; /* Configuration of tests. */ int ExpressMode; + hbool_t same_file; /* Whether to run tests that only use one file */ /* Setup */ h5_reset(); @@ -8621,6 +11810,11 @@ main(void) hid_t fcpl_src; hid_t fcpl_dst; + /* Start with same_file == TRUE. Use source file settings for these + * tests. Don't run with a non-default destination file setting, as + * destination settings have no effect. */ + same_file = TRUE; + /* No need to test dense attributes with old format */ if(!(configuration & CONFIG_SRC_NEW_FORMAT) && (configuration & CONFIG_DENSE)) continue; @@ -8637,6 +11831,7 @@ main(void) if(configuration & CONFIG_SHARE_DST) { puts("Testing with shared dst messages:"); fcpl_dst = fcpl_shared; + same_file = FALSE; } else { puts("Testing without shared dst messages:"); @@ -8659,7 +11854,7 @@ main(void) } } /* end if */ else { - puts("Testing with oldest file format for source file:"); + puts("Testing with oldest file format for source file:"); src_fapl = fapl; num_attributes_g = 4; } /* end else */ @@ -8668,6 +11863,7 @@ main(void) if(configuration & CONFIG_DST_NEW_FORMAT) { puts("Testing with latest format for destination file:"); dst_fapl = fapl2; + same_file = FALSE; } /* end if */ else { puts("Testing with oldest file format for destination file:"); @@ -8736,10 +11932,32 @@ main(void) /* Tests that do not use attributes and do not need to be tested * multiple times for different attribute configurations */ if(configuration < CONFIG_DENSE) { + hbool_t reopen; + nerrors += test_copy_named_datatype(fcpl_src, fcpl_dst, src_fapl, dst_fapl); nerrors += test_copy_named_datatype_vl(fcpl_src, fcpl_dst, src_fapl, dst_fapl); nerrors += test_copy_named_datatype_vl_vl(fcpl_src, fcpl_dst, src_fapl, dst_fapl); + /* Loop over reopening the file */ + for(reopen = FALSE; reopen <= TRUE; reopen++) { + nerrors += test_copy_committed_datatype_merge(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + + if(same_file) + nerrors += test_copy_committed_datatype_merge_same_file(fcpl_src, src_fapl, reopen); + + nerrors += test_copy_committed_dt_merge_sugg(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_committed_dt_merge_attr(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + + /* tests added for merging committed datatypes + suggestions + callback */ + nerrors += test_copy_cdt_hier_merge(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_cdt_merge_cdt(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_cdt_merge_suggs(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_cdt_merge_dset_suggs(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_cdt_merge_all_suggs(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_set_mcdt_search_cb(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + nerrors += test_copy_set_get_mcdt_search_cb(fcpl_src, fcpl_dst, src_fapl, dst_fapl, reopen); + } /* end for */ + nerrors += test_copy_dataset_external(fcpl_src, fcpl_dst, src_fapl, dst_fapl); nerrors += test_copy_dataset_named_dtype(fcpl_src, fcpl_dst, src_fapl, dst_fapl); nerrors += test_copy_dataset_named_dtype_hier(fcpl_src, fcpl_dst, src_fapl, dst_fapl); -- cgit v0.12