diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2013-05-14 19:56:51 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2013-05-14 19:56:51 (GMT) |
commit | 71af5b7480cb0f0aa689640972f8e96fef1e60f0 (patch) | |
tree | ab8e74253d276931a20d40a0df8a2de6692026fe /src | |
parent | 811ac68ac24972a1392fc9f6d20ae96286b2db7a (diff) | |
download | hdf5-71af5b7480cb0f0aa689640972f8e96fef1e60f0.zip hdf5-71af5b7480cb0f0aa689640972f8e96fef1e60f0.tar.gz hdf5-71af5b7480cb0f0aa689640972f8e96fef1e60f0.tar.bz2 |
[svn-r23702] Issue 8380 - H5Zunregister caused seg fault. This is a porting of code from the trunk. It fixes the problem by first iterating
through all opened datasets and groups to see if any of them uses the filter. If it finds one, the function fails with a message.
Then the function flushes all opened files.
Tested with h5committest.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5D.c | 47 | ||||
-rw-r--r-- | src/H5Dprivate.h | 1 | ||||
-rw-r--r-- | src/H5Fpkg.h | 1 | ||||
-rw-r--r-- | src/H5Fprivate.h | 1 | ||||
-rw-r--r-- | src/H5G.c | 50 | ||||
-rw-r--r-- | src/H5Gprivate.h | 1 | ||||
-rw-r--r-- | src/H5Pocpl.c | 37 | ||||
-rw-r--r-- | src/H5Pprivate.h | 1 | ||||
-rw-r--r-- | src/H5Z.c | 179 | ||||
-rw-r--r-- | src/H5Zprivate.h | 1 |
10 files changed, 302 insertions, 17 deletions
@@ -572,19 +572,52 @@ done: hid_t H5Dget_create_plist(hid_t dset_id) { - H5D_t *dset; /* Dataset structure */ + H5D_t *dataset; /* Dataset structure */ + hid_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("i", "i", dset_id); + + /* Check args */ + if(NULL == (dataset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + if((ret_value = H5D_get_create_plist(dataset)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dget_create_plist() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_get_create_plist + * + * Purpose: Private function for H5Dget_create_plist + * + * Return: Success: ID for a copy of the dataset creation + * property list. The template should be + * released by calling H5P_close(). + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, February 3, 1998 + * + *------------------------------------------------------------------------- + */ +hid_t +H5D_get_create_plist(H5D_t *dset) +{ H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */ H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */ H5O_fill_t copied_fill; /* Fill value to tweak */ hid_t new_dcpl_id = FAIL; hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) - H5TRACE1("i", "i", dset_id); + FUNC_ENTER_NOAPI(FAIL) /* Check args */ - if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") @@ -670,8 +703,8 @@ done: if(H5I_dec_app_ref(new_dcpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object") - FUNC_LEAVE_API(ret_value) -} /* end H5Dget_create_plist() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_get_create_plist() */ /*------------------------------------------------------------------------- diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 61bcf47..07f512b 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -164,6 +164,7 @@ H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset); H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset); H5_DLL H5T_t *H5D_typeof(const H5D_t *dset); H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id); +H5_DLL hid_t H5D_get_create_plist(H5D_t *dset); /* Functions that operate on vlen data */ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index ece1600..47e9136 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -299,7 +299,6 @@ H5_DLL herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing); H5_DLL herr_t H5F_close_mounts(H5F_t *f); H5_DLL int H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void *key); H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs); -H5_DLL herr_t H5F_flush_mounts(H5F_t *f, hid_t dxpl_id); /* Superblock related routines */ H5_DLL herr_t H5F_super_init(H5F_t *f, hid_t dxpl_id); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 4a984a1..c32f462 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -501,6 +501,7 @@ H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); H5_DLL hid_t H5F_get_file_id(const H5F_t *f); H5_DLL H5F_t *H5F_get_parent(const H5F_t *f); H5_DLL unsigned H5F_get_nmounts(const H5F_t *f); +H5_DLL herr_t H5F_flush_mounts(H5F_t *f, hid_t dxpl_id); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr); @@ -495,22 +495,54 @@ done: hid_t H5Gget_create_plist(hid_t group_id) { + H5G_t *group = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_API(FAIL) + H5TRACE1("i", "i", group_id); + + /* Check args */ + if(NULL == (group = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + if((ret_value = H5G_get_create_plist(group)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_create_plist() */ + + + +/*------------------------------------------------------------------------- + * Function: H5G_get_create_plist + * + * Purpose: Private function for H5Gget_create_plist + * + * Return: Success: ID for a copy of the group creation + * property list. The property list ID should be + * released by calling H5Pclose(). + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, October 25, 2005 + * + *------------------------------------------------------------------------- + */ +hid_t +H5G_get_create_plist(H5G_t *grp) +{ H5O_linfo_t linfo; /* Link info message */ htri_t ginfo_exists; htri_t linfo_exists; htri_t pline_exists; - H5G_t *grp = NULL; H5P_genplist_t *gcpl_plist; H5P_genplist_t *new_plist; hid_t new_gcpl_id = FAIL; hid_t ret_value = FAIL; - FUNC_ENTER_API(FAIL) - H5TRACE1("i", "i", group_id); - - /* Check args */ - if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + FUNC_ENTER_NOAPI(FAIL) /* Copy the default group creation property list */ if(NULL == (gcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_GROUP_CREATE_g))) @@ -573,8 +605,8 @@ done: HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't free") } /* end if */ - FUNC_LEAVE_API(ret_value) -} /* end H5Gget_create_plist() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_get_create_plist() */ /*------------------------------------------------------------------------- diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index f765b52..50f8bda 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -243,6 +243,7 @@ H5_DLL herr_t H5G_obj_remove_by_idx(const struct H5O_loc_t *grp_oloc, H5RS_str_t H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id); 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, hid_t dxpl_id); +H5_DLL hid_t H5G_get_create_plist(H5G_t *grp); /* * These functions operate on symbol table nodes. diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index 2199b9c..0405197 100644 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -1158,6 +1158,43 @@ done: /*------------------------------------------------------------------------- + * Function: H5P_filter_in_pline + * + * Purpose: Check whether the filter is in the pipeline of the object + * creation property list. + * + * Return: TRUE: found + * FALSE: not found + * FAIL: error + * + * Programmer: Raymond Lu + * 14 May 2013 + * + *------------------------------------------------------------------------- + */ +htri_t +H5P_filter_in_pline(H5P_genplist_t *plist, H5Z_filter_t id) +{ + H5O_pline_t pline; /* Filter pipeline */ + H5Z_filter_info_t *filter; /* Pointer to filter information */ + htri_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get pipeline info */ + if(H5P_get(plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline") + + /* Check if the file is in the pipeline */ + if((ret_value = H5Z_filter_in_pline(&pline, id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTCOMPARE, FAIL, "can't find filter") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_get_filter_by_id() */ + + +/*------------------------------------------------------------------------- * Function: H5Premove_filter * * Purpose: Deletes a filter from the dataset creation property list; diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index c750070..72157dc 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -107,6 +107,7 @@ H5_DLL herr_t H5P_modify_filter(H5P_genplist_t *plist, H5Z_filter_t filter, H5_DLL herr_t H5P_get_filter_by_id(H5P_genplist_t *plist, H5Z_filter_t id, unsigned int *flags, size_t *cd_nelmts, unsigned cd_values[], size_t namelen, char name[], unsigned *filter_config); +H5_DLL htri_t H5P_filter_in_pline(H5P_genplist_t *plist, H5Z_filter_t id); /* *SPECIAL* Don't make more of these! -QAK */ H5_DLL htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id); @@ -22,6 +22,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ @@ -45,6 +46,11 @@ typedef struct H5Z_stats_t { } H5Z_stats_t; #endif /* H5Z_DEBUG */ +typedef struct H5Z_object_t { + H5Z_filter_t filter_id; /* ID of the filter we're looking for */ + htri_t found; /* Whether we find an object using the filter */ +} H5Z_object_t; + /* Enumerated type for dataset creation prelude callbacks */ typedef enum { H5Z_PRELUDE_CAN_APPLY, /* Call "can apply" callback */ @@ -61,6 +67,8 @@ static H5Z_stats_t *H5Z_stat_table_g = NULL; /* Local functions */ static int H5Z_find_idx(H5Z_filter_t id); +static int H5Z_get_object_cb(void *obj_ptr, hid_t obj_id, void *key); +static int H5Z_get_file_cb(void *obj_ptr, hid_t obj_id, void *key); /*------------------------------------------------------------------------- @@ -406,6 +414,7 @@ herr_t H5Z_unregister (H5Z_filter_t id) { size_t i; /* Local index variable */ + H5Z_object_t object; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -421,6 +430,28 @@ H5Z_unregister (H5Z_filter_t id) if (i>=H5Z_table_used_g) HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter is not registered") + /* Initialize the structure object for iteration */ + object.filter_id = id; + object.found = FALSE; + + /* Iterate through all opened datasets, returns a failure if any of them uses the filter */ + if(H5I_iterate(H5I_DATASET, H5Z_get_object_cb, &object, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + + if(object.found) + HGOTO_ERROR(H5E_PLINE, H5E_CANTRELEASE, FAIL, "can't unregister filter because a dataset is still using it") + + /* Iterate through all opened groups, returns a failure if any of them uses the filter */ + if(H5I_iterate(H5I_GROUP, H5Z_get_object_cb, &object, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + + if(object.found) + HGOTO_ERROR(H5E_PLINE, H5E_CANTRELEASE, FAIL, "can't unregister filter because a group is still using it") + + /* Iterate through all opened files and flush them */ + if(H5I_iterate(H5I_FILE, H5Z_get_file_cb, NULL, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + /* Remove filter from table */ /* Don't worry about shrinking table size (for now) */ HDmemmove(&H5Z_table_g[i],&H5Z_table_g[i+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-i)); @@ -435,6 +466,112 @@ done: /*------------------------------------------------------------------------- + * Function: H5Z_get_object_cb + * + * Purpose: The callback function for H5Z_unregister. It iterates + * through all opened objects. If the object is a dataset + * or a group and it uses the filter to be unregistered, the + * function returns TRUE. + * + * Return: TRUE if the object uses the filter. + * FALSE otherwise. + * + * Programmer: Raymond Lu + * 13 May 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5Z_get_object_cb(void *obj_ptr, hid_t obj_id, void *key) +{ + H5I_type_t id_type; + hid_t ocpl_id; + H5P_genplist_t *plist; /* Property list */ + H5Z_object_t *object = (H5Z_object_t *)key; + htri_t filter_in_pline = FALSE; + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(obj_ptr); + + if((id_type = H5I_get_type(obj_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "bad object id"); + + switch(id_type) { + case H5I_GROUP: + if((ocpl_id = H5G_get_create_plist((H5G_t *)obj_ptr)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get group creation property list") + + break; + + case H5I_DATASET: + if((ocpl_id = H5D_get_create_plist((H5D_t *)obj_ptr)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get dataset creation property list") + + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object") + } /* end switch */ + + /* Get the plist structure of object creation */ + if(NULL == (plist = H5P_object_verify(ocpl_id, H5P_OBJECT_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Check if the object creation property list uses the filter */ + if((filter_in_pline = H5P_filter_in_pline(plist, object->filter_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't check filter in pipeline") + + /* H5I_iterate expects TRUE to stop the loop over objects. Stop the loop and let + * H5Z_unregister return failure */ + if(filter_in_pline) { + object->found = TRUE; + ret_value = TRUE; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_object_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5Z_get_file_cb + * + * Purpose: The callback function for H5Z_unregister. It iterates + * through all opened files and flush them. + * + * Return: FALSE if finishes flushing and moves on + * FAIL if there is an error + * + * Programmer: Raymond Lu + * 13 May 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5Z_get_file_cb(void *obj_ptr, hid_t UNUSED obj_id, void UNUSED *key) +{ + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(obj_ptr); + + /* Call the flush routine for mounted file hierarchies. Do a global flush + * if the file is opened for write */ + if(H5F_ACC_RDWR & H5F_INTENT((H5F_t *)obj_ptr)) { + if(H5F_flush_mounts((H5F_t *)obj_ptr, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_file_cb() */ + + + +/*------------------------------------------------------------------------- * Function: H5Zfilter_avail * * Purpose: Check if a filter is available @@ -1275,6 +1412,48 @@ done: /*------------------------------------------------------------------------- + * Function: H5Z_filter_in_pline + * + * Purpose: Check wheter a filter is in the filter pipeline using the + * filter ID. This function is very similar to H5Z_filter_info + * + * Return: TRUE - found filter + * FALSE - not found + * FAIL - error + * + * Programmer: Raymond Lu + * 14 May 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5Z_filter_in_pline(const H5O_pline_t *pline, H5Z_filter_t filter) +{ + size_t idx; /* Index of filter in pipeline */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + assert(pline); + assert(filter>=0 && filter<=H5Z_FILTER_MAX); + + /* Locate the filter in the pipeline */ + for(idx=0; idx<pline->nused; idx++) + if(pline->filter[idx].id==filter) + break; + + /* Check if the filter was not already in the pipeline */ + if(idx>=pline->nused) + ret_value = FALSE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_filter_in_pline() */ + + +/*------------------------------------------------------------------------- * Function: H5Z_all_filters_avail * * Purpose: Verify that all the filters in a pipeline are currently diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h index f53b50c..6c0a46f 100644 --- a/src/H5Zprivate.h +++ b/src/H5Zprivate.h @@ -91,6 +91,7 @@ H5_DLL herr_t H5Z_can_apply_direct(const struct H5O_pline_t *pline); H5_DLL herr_t H5Z_set_local_direct(const struct H5O_pline_t *pline); H5_DLL H5Z_filter_info_t *H5Z_filter_info(const struct H5O_pline_t *pline, H5Z_filter_t filter); +H5_DLL htri_t H5Z_filter_in_pline(const struct H5O_pline_t *pline, H5Z_filter_t filter); H5_DLL htri_t H5Z_all_filters_avail(const struct H5O_pline_t *pline); H5_DLL htri_t H5Z_filter_avail(H5Z_filter_t id); H5_DLL herr_t H5Z_delete(struct H5O_pline_t *pline, H5Z_filter_t filter); |