diff --git a/src/H5Dint.c b/src/H5Dint.c index d408ef30c81..8f363ebadbe 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -3977,3 +3977,24 @@ H5D__refresh(H5D_t *dset, hid_t dset_id) FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__refresh() */ + +/*------------------------------------------------------------------------- + * Function: H5D_get_dcpl_id + * + * Purpose: Quick and dirty routine to retrieve the + * dcpl_id (dataset creation property list) from the + * dataset creation operation struct + * + * Return: 'dcpl_id' on success/abort on failure (shouldn't fail) + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_dcpl_id(const H5D_obj_create_t *d) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + assert(d); + + FUNC_LEAVE_NOAPI(d->dcpl_id); +} /* end H5D_get_dcpl_id() */ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 684780e8e85..5a0b586594f 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -578,12 +578,12 @@ typedef enum { } H5D_time_alloc_t; /* Typedef for dataset creation operation */ -typedef struct { +struct H5D_obj_create_t { hid_t type_id; /* Datatype for dataset */ const H5S_t *space; /* Dataspace for dataset */ hid_t dcpl_id; /* Dataset creation property list */ hid_t dapl_id; /* Dataset access property list */ -} H5D_obj_create_t; +}; /* Typedef for filling a buffer with a fill value */ typedef struct H5D_fill_buf_info_t { diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index fa8b0770359..e539d872f9e 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -124,12 +124,19 @@ /* Default virtual dataset list size */ #define H5D_VIRTUAL_DEF_LIST_SIZE 8 +#ifdef H5D_MODULE +#define H5D_OBJ_ID(D) (((H5D_obj_create_t *)(D))->dcpl_id) +#else /* H5D_MODULE */ +#define H5D_OBJ_ID(D) (H5D_get_dcpl_id(D)) +#endif + /****************************/ /* Library Private Typedefs */ /****************************/ /* Typedef for dataset in memory (defined in H5Dpkg.h) */ -typedef struct H5D_t H5D_t; +typedef struct H5D_t H5D_t; +typedef struct H5D_obj_create_t H5D_obj_create_t; /* Typedef for cached dataset creation property list information */ typedef struct H5D_dcpl_cache_t { @@ -171,6 +178,7 @@ H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset); H5_DLL herr_t H5D_flush_all(H5F_t *f); H5_DLL hid_t H5D_get_create_plist(const H5D_t *dset); H5_DLL hid_t H5D_get_access_plist(const H5D_t *dset); +H5_DLL hid_t H5D_get_dcpl_id(const H5D_obj_create_t *d); /* Functions that operate on chunked storage */ H5_DLL herr_t H5D_chunk_idx_reset(H5O_storage_chunk_t *storage, bool reset_addr); diff --git a/src/H5Gint.c b/src/H5Gint.c index 46559d82291..34072df90e6 100644 --- a/src/H5Gint.c +++ b/src/H5Gint.c @@ -1377,3 +1377,24 @@ H5G__get_info_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t id FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__get_info_by_idx() */ + +/*------------------------------------------------------------------------- + * Function: H5G_get_gcpl_id + * + * Purpose: Quick and dirty routine to retrieve the + * gcpl_id (group creation property list) from the + * group creation operation struct + * + * Return: 'gcpl_id' on success/abort on failure (shouldn't fail) + *------------------------------------------------------------------------- + */ +hid_t +H5G_get_gcpl_id(const H5G_obj_create_t *g) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + assert(g); + + FUNC_LEAVE_NOAPI(g->gcpl_id); +} /* end H5G_get_gcpl_id() */ diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 77a8e4c4fff..a90ada92ba9 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -279,11 +279,11 @@ typedef struct H5G_bt2_ud_ins_t { } H5G_bt2_ud_ins_t; /* Typedef for group creation operation */ -typedef struct H5G_obj_create_t { +struct H5G_obj_create_t { hid_t gcpl_id; /* Group creation property list */ H5G_cache_type_t cache_type; /* Type of symbol table entry cache */ H5G_cache_t cache; /* Cached data for symbol table entry */ -} H5G_obj_create_t; +}; /* Callback information for copying groups */ typedef struct H5G_copy_file_ud_t { diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 8f8da1a23bb..bb172eb2af7 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -94,8 +94,10 @@ /* If the module using this macro is allowed access to the private variables, access them directly */ #ifdef H5G_MODULE #define H5G_MOUNTED(G) ((G)->shared->mounted) +#define H5G_OBJ_ID(G) (((H5G_obj_create_t *)(G))->gcpl_id) #else /* H5G_MODULE */ #define H5G_MOUNTED(G) (H5G_mounted(G)) +#define H5G_OBJ_ID(G) (H5G_get_gcpl_id(G)) #endif /* H5G_MODULE */ /* @@ -109,6 +111,7 @@ #define H5G_TARGET_UDLINK 0x0004 #define H5G_TARGET_EXISTS 0x0008 #define H5G_CRT_INTMD_GROUP 0x0010 +#define H5G_CRT_OBJ 0x0020 /* Type of operation being performed for call to H5G_name_replace() */ typedef enum { @@ -136,6 +139,7 @@ typedef struct H5G_name_t { /* Forward declarations (for prototypes & struct definitions) */ struct H5O_loc_t; struct H5O_link_t; +typedef struct H5G_obj_create_t H5G_obj_create_t; /* * The "location" of an object in a group hierarchy. This points to an object @@ -235,6 +239,7 @@ H5_DLL herr_t H5G_obj_remove_by_idx(const struct H5O_loc_t *grp_oloc, H5RS_str_t H5_DLL herr_t H5G_obj_lookup_by_idx(const struct H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, struct H5O_link_t *lnk); H5_DLL hid_t H5G_get_create_plist(const H5G_t *grp); +H5_DLL hid_t H5G_get_gcpl_id(const H5G_obj_create_t *g); /* * These functions operate on symbol table nodes. diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 67f8e479e15..00732c3c987 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -30,6 +30,7 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ +#include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ #include "H5Gpkg.h" /* Groups */ @@ -613,6 +614,7 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5G const H5O_linfo_t *linfo; /* Link info settings for new group */ const H5O_pline_t *pline; /* Filter pipeline settings for new group */ H5G_obj_create_t gcrt_info; /* Group creation info */ + H5O_obj_create_t *ocrt_info; /* Object creation info in op_data */ /* Check for the parent group having a group info message */ /* (OK if not found) */ @@ -665,8 +667,15 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5G pline = &def_pline; /* Create the intermediate group */ - /* XXX: Should we allow user to control the group creation params here? -QAK */ - gcrt_info.gcpl_id = H5P_GROUP_CREATE_DEFAULT; + gcrt_info.gcpl_id = H5P_GROUP_CREATE_DEFAULT; + /* Propagate the object creation properties when creating intermedidate groups */ + if ((target & H5G_CRT_OBJ) && (ocrt_info = H5L_OCRT_INFO(op_data)) != NULL) { + if (ocrt_info->obj_type == H5O_TYPE_GROUP) + gcrt_info.gcpl_id = H5G_OBJ_ID(ocrt_info->crt_info); + else if (ocrt_info->obj_type == H5O_TYPE_DATASET) + gcrt_info.gcpl_id = H5D_OBJ_ID(ocrt_info->crt_info); + } + gcrt_info.cache_type = H5G_NOTHING_CACHED; memset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache)); if (H5G__obj_create_real(grp_oloc.file, ginfo, linfo, pline, &gcrt_info, diff --git a/src/H5Lint.c b/src/H5Lint.c index e33ad939ef8..d02e8c48a48 100644 --- a/src/H5Lint.c +++ b/src/H5Lint.c @@ -91,13 +91,13 @@ typedef struct { } H5L_trav_gnbi_t; /* User data for path traversal callback to creating a link */ -typedef struct { +struct H5L_trav_cr_t { H5F_t *file; /* Pointer to the file */ H5P_genplist_t *lc_plist; /* Link creation property list */ H5G_name_t *path; /* Path to object being linked */ H5O_obj_create_t *ocrt_info; /* Pointer to object creation info */ H5O_link_t *lnk; /* Pointer to link information to insert */ -} H5L_trav_cr_t; +}; /* User data for path traversal routine for moving and renaming a link */ typedef struct { @@ -706,6 +706,9 @@ H5L__create_real(const H5G_loc_t *link_loc, const char *link_name, H5G_name_t *o target_flags |= H5G_CRT_INTMD_GROUP; } /* end if */ + if (ocrt_info != NULL) + target_flags |= H5G_CRT_OBJ; + /* Set up user data * FILE is used to make sure that hard links don't cross files, and * should be NULL for other link types. @@ -2152,3 +2155,22 @@ H5L_iterate(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5L_iterate() */ + +/*------------------------------------------------------------------------- + * Function: H5L_get_ocrt_info + * + * Purpose: Quick and dirty routine to retrieve the link's object_creation info + * + * Return: 'ocrt_info' on success/abort on failure (shouldn't fail) + *------------------------------------------------------------------------- + */ +H5O_obj_create_t * +H5L_get_ocrt_info(const H5L_trav_cr_t *l) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + assert(l); + + FUNC_LEAVE_NOAPI(l->ocrt_info); +} /* end H5L_get_ocrt_info() */ diff --git a/src/H5Lprivate.h b/src/H5Lprivate.h index 150a07986e1..ff3ace83dbd 100644 --- a/src/H5Lprivate.h +++ b/src/H5Lprivate.h @@ -47,6 +47,12 @@ /* callback function for external link traversal */ #define H5L_ACS_ELINK_CB_NAME "external link callback" +#ifdef H5L_MODULE +#define H5L_OCRT_INFO(L) (((H5L_trav_cr_t *)(L))->ocrt_info) +#else /* H5L_MODULE */ +#define H5L_OCRT_INFO(L) (H5L_get_ocrt_info(L)) +#endif + /****************************/ /* Library Private Typedefs */ /****************************/ @@ -57,6 +63,8 @@ typedef struct H5L_elink_cb_t { void *user_data; } H5L_elink_cb_t; +typedef struct H5L_trav_cr_t H5L_trav_cr_t; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -75,6 +83,7 @@ H5_DLL herr_t H5L_get_info(const H5G_loc_t *loc, const char *name, H5L_info2_t * H5_DLL herr_t H5L_register_external(void); H5_DLL herr_t H5L_iterate(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op, void *op_data); +H5_DLL H5O_obj_create_t *H5L_get_ocrt_info(const H5L_trav_cr_t *l); /* User-defined link functions */ H5_DLL herr_t H5L_register(const H5L_class_t *cls); diff --git a/test/tmisc.c b/test/tmisc.c index be1cebfcfdf..67e92c0898b 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -339,6 +339,7 @@ typedef struct { #define MISC38_FILE "type_conversion_path_table_issue.h5" #define MISC39_FILE "set_est_link_info.h5" +#define MISC40_FILE "obj_props_intermediate.h5" /**************************************************************** ** @@ -6640,6 +6641,223 @@ test_misc39(void) } /* end test_misc39() */ +/**************************************************************** +** +** test_misc40(): Test that object creation properties are propagated +** to intermediate groups. +** +****************************************************************/ +static void +test_misc40(void) +{ + hid_t lcpl = H5I_INVALID_HID; + hid_t gcpl = H5I_INVALID_HID; + hid_t gcpl2 = H5I_INVALID_HID; + hid_t def_gcpl = H5I_INVALID_HID; + hid_t dcpl = H5I_INVALID_HID; + hid_t fid = H5I_INVALID_HID; + hid_t gid = H5I_INVALID_HID; + hid_t gid2 = H5I_INVALID_HID; + hid_t def_gid = H5I_INVALID_HID; + hid_t did = H5I_INVALID_HID; + hid_t sid = H5I_INVALID_HID; + hsize_t dims[1] = {10}; + unsigned cr_order = 0; + bool track_times = false; + herr_t status; + + /* Output message about test being performed */ + MESSAGE(5, ("Testing object creation properties are propagated to intermediate groups\n")); + + lcpl = H5Pcreate(H5P_LINK_CREATE); + CHECK(lcpl, FAIL, "H5Pcreate"); + + status = H5Pset_create_intermediate_group(lcpl, 1); + CHECK(status, FAIL, "H5Pset_create_intermediate_group"); + + fid = H5Fcreate(MISC40_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* + * Verify default creation properties when creating + * group with intermdiate group + */ + + /* Create groups that use default creation properties */ + def_gid = H5Gcreate2(fid, "def_group1/def_group2", lcpl, H5P_DEFAULT, H5P_DEFAULT); + CHECK(def_gid, FAIL, "H5Gcreate2"); + + status = H5Gclose(def_gid); + CHECK(status, FAIL, "H5Gclose"); + + def_gid = H5Gopen2(fid, "def_group1", H5P_DEFAULT); + CHECK(def_gid, FAIL, "H5Gopen2"); + + def_gcpl = H5Gget_create_plist(def_gid); + CHECK(def_gcpl, FAIL, "H5Gget_create_plist"); + + /* Default is true */ + status = H5Pget_obj_track_times(def_gcpl, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, true, "H5Pget_obj_track_times"); + + /* Default is false */ + status = H5Pget_attr_creation_order(def_gcpl, &cr_order); + CHECK(status, FAIL, "H5Pget_attr_creation_order"); + VERIFY(cr_order, false, "H5Pget_attr_creation_order"); + + status = H5Gclose(def_gid); + CHECK(status, FAIL, "H5Gclose"); + + status = H5Pclose(def_gcpl); + CHECK(status, FAIL, "H5Pclose"); + + /* + * Verify non-default creation properties when creating + * group with intermediate groups + */ + gcpl = H5Pcreate(H5P_GROUP_CREATE); + CHECK(gcpl, FAIL, "H5Pcreate"); + + status = H5Pset_attr_creation_order(gcpl, H5P_CRT_ORDER_TRACKED); + CHECK(status, FAIL, "H5Pset_attr_creation_order"); + + status = H5Pset_obj_track_times(gcpl, false); + CHECK(status, FAIL, "H5Pset_obj_track_times"); + + gid = H5Gcreate2(fid, "group1/group2/group3", lcpl, gcpl, H5P_DEFAULT); + CHECK(gid, FAIL, "H5Gcreate2"); + + status = H5Pclose(gcpl); + CHECK(status, FAIL, "H5Pclose"); + + /* Verify group3 */ + gcpl = H5Gget_create_plist(gid); + CHECK(gcpl, FAIL, "H5Gget_create_plist"); + + status = H5Pget_attr_creation_order(gcpl, &cr_order); + CHECK(status, FAIL, "H5Pget_attr_creation_order"); + VERIFY(cr_order, H5P_CRT_ORDER_TRACKED, "H5Pget_attr_creation_order"); + + status = H5Pget_obj_track_times(gcpl, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, false, "H5Pget_obj_track_times"); + + status = H5Gclose(gid); + CHECK(status, FAIL, "H5Gclose"); + status = H5Pclose(gcpl); + CHECK(status, FAIL, "H5Pclose"); + + /* Verify group1 */ + gid = H5Gopen2(fid, "group1", H5P_DEFAULT); + CHECK(gid, FAIL, "H5Gopen2"); + + gcpl = H5Gget_create_plist(gid); + CHECK(gcpl, FAIL, "H5Gget_create_plist"); + + status = H5Pget_attr_creation_order(gcpl, &cr_order); + CHECK(status, FAIL, "H5Pget_attr_creation_order"); + VERIFY(cr_order, H5P_CRT_ORDER_TRACKED, "H5Pget_attr_creation_order"); + + status = H5Pget_obj_track_times(gcpl, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, false, "H5Pget_obj_track_times"); + + /* Verify group2 */ + gid2 = H5Gopen2(gid, "group2", H5P_DEFAULT); + CHECK(gid2, FAIL, "H5Gopen2"); + + gcpl2 = H5Gget_create_plist(gid2); + CHECK(gcpl2, FAIL, "H5Gget_create_plist"); + + status = H5Pget_attr_creation_order(gcpl2, &cr_order); + CHECK(status, FAIL, "H5Pget_attr_creation_order"); + VERIFY(cr_order, H5P_CRT_ORDER_TRACKED, "H5Pget_attr_creation_order"); + + status = H5Pget_obj_track_times(gcpl2, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, false, "H5Pget_obj_track_times"); + + status = H5Gclose(gid2); + CHECK(status, FAIL, "H5Gclose"); + status = H5Pclose(gcpl2); + CHECK(status, FAIL, "H5Pclose"); + + status = H5Gclose(gid); + CHECK(status, FAIL, "H5Gclose"); + status = H5Pclose(gcpl); + CHECK(status, FAIL, "H5Pclose"); + + /* + * Verify non-default creation properties when creating + * dataset with intermediate group + */ + dcpl = H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl, FAIL, "H5Pcreate"); + + status = H5Pset_attr_creation_order(dcpl, H5P_CRT_ORDER_TRACKED); + CHECK(status, FAIL, "H5Pset_attr_creation_order"); + + sid = H5Screate_simple(1, dims, NULL); + CHECK(sid, FAIL, "H5Screate_simple"); + + did = H5Dcreate2(fid, "path1/dname", H5T_NATIVE_INT, sid, lcpl, dcpl, H5P_DEFAULT); + CHECK(did, FAIL, "H5Dcreate2"); + + status = H5Dclose(did); + CHECK(status, FAIL, "H5Dclose"); + status = H5Sclose(sid); + CHECK(status, FAIL, "H5Sclose"); + status = H5Pclose(dcpl); + CHECK(status, FAIL, "H5Pclose"); + + /* Verify path1 */ + gid = H5Gopen2(fid, "path1", H5P_DEFAULT); + CHECK(gid, FAIL, "H5Gopen2"); + + gcpl = H5Gget_create_plist(gid); + CHECK(gcpl, FAIL, "H5Gget_create_plist"); + + status = H5Pget_attr_creation_order(gcpl, &cr_order); + CHECK(status, FAIL, "H5Pget_attr_creation_order"); + VERIFY(cr_order, H5P_CRT_ORDER_TRACKED, "H5Pget_attr_creation_order"); + + status = H5Pget_obj_track_times(gcpl, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, true, "H5Pget_obj_track_times"); + + /* Verify dname */ + did = H5Dopen2(gid, "dname", H5P_DEFAULT); + CHECK(did, FAIL, "H5Dopen2"); + + dcpl = H5Dget_create_plist(did); + CHECK(dcpl, FAIL, "H5Dget_create_plist"); + + status = H5Pget_attr_creation_order(dcpl, &cr_order); + VERIFY(cr_order, H5P_CRT_ORDER_TRACKED, "H5Pget_attr_creation_order"); + + status = H5Pget_obj_track_times(dcpl, &track_times); + CHECK(status, FAIL, "H5Pget_obj_track_times"); + VERIFY(track_times, true, "H5Pget_obj_track_times"); + + status = H5Dclose(did); + CHECK(status, FAIL, "H5Dclose"); + status = H5Pclose(dcpl); + CHECK(status, FAIL, "H5Pclose"); + + status = H5Gclose(gid); + CHECK(status, FAIL, "H5Gclose"); + status = H5Pclose(gcpl); + CHECK(status, FAIL, "H5Pclose"); + + status = H5Fclose(fid); + CHECK(status, FAIL, "H5Fclose"); + + status = H5Pclose(lcpl); + CHECK(status, FAIL, "H5Pclose"); + +} /* end test_misc40() */ + /**************************************************************** ** ** test_misc(): Main misc. test routine. @@ -6710,6 +6928,7 @@ test_misc(void) test_misc37(); /* Test for seg fault failure at file close */ test_misc38(); /* Test for type conversion path table issue */ test_misc39(); /* Ensure H5Pset_est_link_info() handles large values */ + test_misc40(); /* Test object properties propagated to intermediate groups */ } /* test_misc() */ @@ -6767,6 +6986,7 @@ cleanup_misc(void) #endif /* H5_NO_DEPRECATED_SYMBOLS */ H5Fdelete(MISC38_FILE, H5P_DEFAULT); H5Fdelete(MISC39_FILE, H5P_DEFAULT); + H5Fdelete(MISC40_FILE, H5P_DEFAULT); } H5E_END_TRY } /* end cleanup_misc() */