summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2013-04-29 19:23:04 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2013-04-29 19:23:04 (GMT)
commitbada3f7a86cb30b24fad3a24f88114861527ed58 (patch)
tree3f351f78649e966c2521c606082ad63e860e81c1
parent029e143471397de6ddc204be0c21f0c04ee5f2e2 (diff)
downloadhdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.zip
hdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.tar.gz
hdf5-bada3f7a86cb30b24fad3a24f88114861527ed58.tar.bz2
[svn-r23656] Issue 8380 H5Zunregister caused seg fault: I added some protection measures:
1. If any opened object uses the filter, let it fail. 2. Flush all opened files to push any cached data to files. Tested with h5committest.
-rw-r--r--MANIFEST1
-rw-r--r--src/H5D.c47
-rw-r--r--src/H5Dprivate.h1
-rw-r--r--src/H5G.c46
-rw-r--r--src/H5Gprivate.h1
-rw-r--r--src/H5I.c42
-rw-r--r--src/H5Iprivate.h1
-rw-r--r--src/H5Pocpl.c37
-rw-r--r--src/H5Pprivate.h1
-rw-r--r--src/H5Z.c163
-rw-r--r--src/H5Zprivate.h1
-rw-r--r--test/Makefile.am4
-rw-r--r--test/Makefile.in20
-rw-r--r--test/unregister.c258
14 files changed, 595 insertions, 28 deletions
diff --git a/MANIFEST b/MANIFEST
index 8fd716a..944072a 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1091,6 +1091,7 @@
./test/tvlstr.c
./test/tvltypes.c
./test/unlink.c
+./test/unregister.c
./test/vfd.c
./test/test_filters_le.h5
./test/test_filters_be.h5
diff --git a/src/H5D.c b/src/H5D.c
index d204712..d81d4c7 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -572,19 +572,56 @@ done:
hid_t
H5Dget_create_plist(hid_t dset_id)
{
- H5D_t *dset; /* Dataset structure */
+ H5D_t *dataset; /* Dataset structure */
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 */
+ hid_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ 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_NOAPI(FAIL)
+
+ /* Check args */
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 +707,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 1e2b91d..7adc231 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -162,6 +162,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/H5G.c b/src/H5G.c
index a0e7767..bd4ad9b 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -499,7 +499,7 @@ H5Gget_create_plist(hid_t group_id)
htri_t ginfo_exists;
htri_t linfo_exists;
htri_t pline_exists;
- H5G_t *grp = NULL;
+ H5G_t *group = NULL;
H5P_genplist_t *gcpl_plist;
H5P_genplist_t *new_plist;
hid_t new_gcpl_id = FAIL;
@@ -509,9 +509,47 @@ H5Gget_create_plist(hid_t group_id)
H5TRACE1("i", "i", group_id);
/* Check args */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
+ 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;
+ H5P_genplist_t *gcpl_plist;
+ H5P_genplist_t *new_plist;
+ hid_t new_gcpl_id = FAIL;
+ hid_t ret_value = FAIL;
+
+ 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)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default group creation property list")
@@ -573,8 +611,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/H5I.c b/src/H5I.c
index 581356e..6a8c269 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -2002,21 +2002,55 @@ H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
+ if((ret_value = H5I_search(type, func, key)) == NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Isearch() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5I_search
+ *
+ * Purpose: Private function for H5Isearch
+ *
+ * Return: Success: The first object in the type for which FUNC
+ * returns non-zero. NULL if FUNC returned zero
+ * for every object in the type.
+ *
+ * Failure: NULL
+ *
+ * Programmer: James Laird
+ * Nathaniel Furrer
+ * Friday, April 23, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5I_search(H5I_type_t _type, H5I_search_func_t _func, void *_key)
+{
+ H5I_search_ud_t udata; /* Context for iteration */
+ void *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
/* Set up udata struct */
- udata.app_cb = func;
- udata.app_key = key;
+ udata.app_cb = _func;
+ udata.app_key = _key;
udata.ret_obj = NULL;
/* Note that H5I_iterate returns an error code. We ignore it
* here, as we can't do anything with it without revising the API.
*/
- H5I_iterate(type, H5I_search_cb, &udata, TRUE);
+ if(H5I_iterate(_type, H5I_search_cb, &udata, TRUE) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
/* Set return value */
ret_value = udata.ret_obj;
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5Isearch() */
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index ff1463d..28b6327 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -78,6 +78,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
+H5_DLL void *H5I_search(H5I_type_t _type, H5I_search_func_t _func, void *_key);
H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref);
H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c
index 880b46a..f80e4e7 100644
--- a/src/H5Pocpl.c
+++ b/src/H5Pocpl.c
@@ -1177,6 +1177,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
+ * 26 April 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 6560064..083619b 100644
--- a/src/H5Pprivate.h
+++ b/src/H5Pprivate.h
@@ -108,6 +108,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);
diff --git a/src/H5Z.c b/src/H5Z.c
index 9f8b59d..5d68c25 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -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 */
@@ -51,6 +52,9 @@ typedef enum {
H5Z_PRELUDE_SET_LOCAL /* Call "set local" callback */
} H5Z_prelude_type_t;
+/* Maximal number of the list of opened objects (2^16) */
+#define NUM_OBJS 65536
+
/* Local variables */
static size_t H5Z_table_alloc_g = 0;
static size_t H5Z_table_used_g = 0;
@@ -403,33 +407,133 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Z_unregister (H5Z_filter_t id)
+H5Z_unregister (H5Z_filter_t filter_id)
{
- size_t i; /* Local index variable */
+ hid_t *file_list = NULL;
+ hid_t *obj_id_list = NULL;
+ size_t num_obj_id = 0;
+ size_t num_file_id = 0;
+ H5F_t *f = NULL; /* File to query */
+ H5I_type_t id_type;
+ hid_t ocpl_id;
+ H5P_genplist_t *plist; /* Property list */
+ size_t filter_index; /* Local index variable for filter */
+ int i;
+ htri_t filter_in_pline = FALSE;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
- assert (id>=0 && id<=H5Z_FILTER_MAX);
+ assert (filter_id>=0 && filter_id<=H5Z_FILTER_MAX);
/* Is the filter already registered? */
- for (i=0; i<H5Z_table_used_g; i++)
- if (H5Z_table_g[i].id==id)
+ for (filter_index=0; filter_index<H5Z_table_used_g; filter_index++)
+ if (H5Z_table_g[filter_index].id==filter_id)
break;
/* Fail if filter not found */
- if (i>=H5Z_table_used_g)
+ if (filter_index>=H5Z_table_used_g)
HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter is not registered")
+ /* Count the number of opened datasets and groups among all opened files */
+ if(H5F_get_obj_count(NULL, H5F_OBJ_DATASET | H5F_OBJ_GROUP, FALSE, &num_obj_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object number")
+
+ if(num_obj_id) {
+ if(NULL == (obj_id_list = (hid_t *)H5MM_malloc(num_obj_id*sizeof(hid_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "failed to allocate space")
+
+ /* Find all opened objects that may use the filter (datasets and groups). Passing NULL as a pointer to
+ * file structure indicates searching among all opened files */
+ if(H5F_get_obj_ids(NULL, H5F_OBJ_DATASET | H5F_OBJ_GROUP, num_obj_id, obj_id_list, FALSE, &num_obj_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object IDs")
+ }
+
+ /* Check if any opened object (dataset or group) uses the filter. If so, fail with a message */
+ for(i=0; i<num_obj_id; i++) {
+ if((id_type = H5I_get_type(obj_id_list[i])) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "bad object id");
+
+ switch(id_type) {
+ case H5I_GROUP:
+ {
+ H5G_t *group = NULL;
+
+ if(NULL == (group = (H5G_t *)H5I_object_verify(obj_id_list[i], H5I_GROUP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
+
+ if((ocpl_id = H5G_get_create_plist(group)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get group creation property list")
+
+ }
+ break;
+
+ case H5I_DATASET:
+ {
+ H5D_t *dataset = NULL;
+
+ if(NULL == (dataset = (H5D_t *)H5I_object_verify(obj_id_list[i], H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+
+ if((ocpl_id = H5D_get_create_plist(dataset)) < 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, filter_id)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't check filter in pipeline")
+
+ if(filter_in_pline)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't unregister filter because some object is still using it")
+ }
+
+ /* Count the number of opened files */
+ if(H5F_get_obj_count(NULL, H5F_OBJ_FILE, FALSE, &num_file_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file number")
+
+ /* Get the list of IDs for all opened files */
+ if(num_file_id) {
+ if(NULL == (file_list = (hid_t *)H5MM_malloc(num_file_id*sizeof(hid_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "failed to allocate space")
+
+ if(H5F_get_obj_ids(NULL, H5F_OBJ_FILE, num_file_id, file_list, FALSE, &num_file_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file IDs")
+ }
+
+ /* Flush all opened files in case any file uses the filter */
+ for(i=0; i<num_file_id; i++) {
+ if(NULL == (f = (H5F_t *)H5I_object_verify(file_list[i], H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+
+ /* 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(f)) {
+ if(H5F_flush_mounts(f, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy")
+ } /* end if */
+ }
+
/* 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));
+ HDmemmove(&H5Z_table_g[filter_index],&H5Z_table_g[filter_index+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-filter_index));
#ifdef H5Z_DEBUG
- HDmemmove(&H5Z_stat_table_g[i],&H5Z_stat_table_g[i+1],sizeof(H5Z_stats_t)*((H5Z_table_used_g-1)-i));
+ HDmemmove(&H5Z_stat_table_g[filter_index],&H5Z_stat_table_g[filter_index+1],sizeof(H5Z_stats_t)*((H5Z_table_used_g-1)-filter_index));
#endif /* H5Z_DEBUG */
H5Z_table_used_g--;
done:
+ if(file_list) H5MM_free(file_list);
+ if(obj_id_list) H5MM_free(obj_id_list);
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5Z_unregister() */
@@ -1275,6 +1379,49 @@ 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
+ * 26 April 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);
diff --git a/test/Makefile.am b/test/Makefile.am
index ac5d169..5e476d3 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -46,7 +46,7 @@ TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image
+ freespace mf farray earray btree2 fheap file_image unregister
# List programs to be built when testing here. error_test and err_compat are
# built at the same time as the other tests, but executed by testerror.sh.
@@ -150,7 +150,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
earray.h5 efc[0-5].h5 log_vfd_out.log \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
- file_image_core_test.h5.copy
+ file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5
# Sources for testhdf5 executable
testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
diff --git a/test/Makefile.in b/test/Makefile.in
index 65c0fca..e9e2faa 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -165,7 +165,8 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \
dtransform$(EXEEXT) reserved$(EXEEXT) cross_read$(EXEEXT) \
freespace$(EXEEXT) mf$(EXEEXT) farray$(EXEEXT) earray$(EXEEXT) \
- btree2$(EXEEXT) fheap$(EXEEXT) file_image$(EXEEXT)
+ btree2$(EXEEXT) fheap$(EXEEXT) file_image$(EXEEXT) \
+ unregister$(EXEEXT)
@HAVE_SHARED_CONDITIONAL_TRUE@am__EXEEXT_2 = plugin$(EXEEXT)
am__EXEEXT_3 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \
@@ -484,6 +485,10 @@ unlink_SOURCES = unlink.c
unlink_OBJECTS = unlink.$(OBJEXT)
unlink_LDADD = $(LDADD)
unlink_DEPENDENCIES = libh5test.la $(LIBHDF5)
+unregister_SOURCES = unregister.c
+unregister_OBJECTS = unregister.$(OBJEXT)
+unregister_LDADD = $(LDADD)
+unregister_DEPENDENCIES = libh5test.la $(LIBHDF5)
vfd_SOURCES = vfd.c
vfd_OBJECTS = vfd.$(OBJEXT)
vfd_LDADD = $(LDADD)
@@ -539,7 +544,7 @@ SOURCES = $(libdynlib1_la_SOURCES) $(libdynlib2_la_SOURCES) \
mount.c mtime.c ntypes.c objcopy.c ohdr.c plugin.c pool.c \
reserved.c set_extent.c space_overflow.c stab.c \
tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) unlink.c vfd.c
+ $(ttsafe_SOURCES) unlink.c unregister.c vfd.c
DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
$(am__libdynlib2_la_SOURCES_DIST) \
$(am__libdynlib3_la_SOURCES_DIST) $(libh5test_la_SOURCES) \
@@ -558,7 +563,7 @@ DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
mount.c mtime.c ntypes.c objcopy.c ohdr.c plugin.c pool.c \
reserved.c set_extent.c space_overflow.c stab.c \
tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) unlink.c vfd.c
+ $(ttsafe_SOURCES) unlink.c unregister.c vfd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -879,7 +884,8 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \
objcopy_ext.dat trefer1.h5 trefer2.h5 app_ref.h5 farray.h5 \
earray.h5 efc[0-5].h5 log_vfd_out.log new_multi_file_v16-r.h5 \
new_multi_file_v16-s.h5 split_get_file_image_test-m.h5 \
- split_get_file_image_test-r.h5 file_image_core_test.h5.copy
+ split_get_file_image_test-r.h5 file_image_core_test.h5.copy \
+ unregister_filter_1.h5 unregister_filter_2.h5
INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src
# Test script for error_test and err_compat
@@ -902,7 +908,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe enc_dec_plist enc_dec_plist_with_endianess\
getname vfd ntypes dangle dtransform reserved cross_read \
- freespace mf farray earray btree2 fheap file_image
+ freespace mf farray earray btree2 fheap file_image unregister
# These programs generate test files for the tests. They don't need to be
@@ -1303,6 +1309,9 @@ ttsafe$(EXEEXT): $(ttsafe_OBJECTS) $(ttsafe_DEPENDENCIES) $(EXTRA_ttsafe_DEPENDE
unlink$(EXEEXT): $(unlink_OBJECTS) $(unlink_DEPENDENCIES) $(EXTRA_unlink_DEPENDENCIES)
@rm -f unlink$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(unlink_OBJECTS) $(unlink_LDADD) $(LIBS)
+unregister$(EXEEXT): $(unregister_OBJECTS) $(unregister_DEPENDENCIES) $(EXTRA_unregister_DEPENDENCIES)
+ @rm -f unregister$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(unregister_OBJECTS) $(unregister_LDADD) $(LIBS)
vfd$(EXEEXT): $(vfd_OBJECTS) $(vfd_DEPENDENCIES) $(EXTRA_vfd_DEPENDENCIES)
@rm -f vfd$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(vfd_OBJECTS) $(vfd_LDADD) $(LIBS)
@@ -1421,6 +1430,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tvlstr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tvltypes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unlink.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unregister.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfd.Po@am__quote@
.c.o:
diff --git a/test/unregister.c b/test/unregister.c
new file mode 100644
index 0000000..88f4d1b
--- /dev/null
+++ b/test/unregister.c
@@ -0,0 +1,258 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic document set and is *
+ * linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have access *
+ * to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/*
+ * Programmer: Raymond Lu
+ * 24 April 2013
+ *
+ * Purpose: Tests H5Zunregister function
+ */
+#include "h5test.h"
+
+const char *FILENAME[] = {
+ "unregister_filter_1",
+ "unregister_filter_2",
+ NULL
+};
+
+#define GROUP_NAME "group"
+#define DSET_NAME "dataset"
+#define FILENAME_BUF_SIZE 1024
+#define DSET_DIM1 100
+#define DSET_DIM2 200
+#define FILTER_CHUNK_DIM1 2
+#define FILTER_CHUNK_DIM2 25
+#define GROUP_ITERATION 1000
+
+#define H5Z_FILTER_DUMMY 312
+
+static size_t filter_dummy(unsigned int flags, size_t cd_nelmts,
+ const unsigned int *cd_values, size_t nbytes, size_t *buf_size, void **buf);
+
+/* Dummy filter for test_unregister_filters only */
+const H5Z_class2_t H5Z_DUMMY[1] = {{
+ H5Z_CLASS_T_VERS, /* H5Z_class_t version */
+ H5Z_FILTER_DUMMY, /* Filter id number */
+ 1, 1, /* Encoding and decoding enabled */
+ "dummy", /* Filter name for debugging */
+ NULL, /* The "can apply" callback */
+ NULL, /* The "set local" callback */
+ filter_dummy, /* The actual filter function */
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: filter_dummy
+ *
+ * Purpose: A dummy compression method that doesn't do anything. This
+ * filter is only for test_unregister_filters. Please don't
+ * use it for other tests because it may mess up this test.
+ *
+ * Return: Success: Data chunk size
+ *
+ * Failure: 0
+ *
+ * Programmer: Raymond Lu
+ * April 24, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+filter_dummy(unsigned int UNUSED flags, size_t UNUSED cd_nelmts,
+ const unsigned int UNUSED *cd_values, size_t nbytes,
+ size_t UNUSED *buf_size, void UNUSED **buf)
+{
+ return nbytes;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: test_unregister_filters
+ *
+ * Purpose: Tests unregistering filter before closing the file
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * 11 April 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+test_unregister_filters(hid_t my_fapl)
+{
+ hid_t file1, file2;
+ hid_t dc;
+ hid_t gcpl, gid, group;
+ hid_t dataset, space;
+ int i, j, n;
+ char gname[256];
+ char filename[FILENAME_BUF_SIZE];
+ const hsize_t chunk_size[2] = {FILTER_CHUNK_DIM1, FILTER_CHUNK_DIM2}; /* Chunk dimensions */
+ hsize_t dims[2];
+ int points[DSET_DIM1][DSET_DIM2];
+ herr_t ret;
+
+ TESTING("Unregistering filter");
+
+ /* Create first file */
+ h5_fixname(FILENAME[0], my_fapl, filename, sizeof filename);
+ if((file1 = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) goto error;
+
+ /* Create second file */
+ h5_fixname(FILENAME[1], my_fapl, filename, sizeof filename);
+ if((file2 = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) goto error;
+
+ /* Register DUMMY filter */
+ if(H5Zregister(H5Z_DUMMY) < 0) goto error;
+
+ if(H5Zfilter_avail(H5Z_FILTER_DUMMY)!=TRUE) goto error;
+
+ if((gcpl = H5Pcreate(H5P_GROUP_CREATE)) < 0) goto error;
+
+ /* Use DUMMY filter for creating groups */
+ if(H5Pset_filter (gcpl, H5Z_FILTER_DUMMY, H5Z_FLAG_MANDATORY, (size_t)0, NULL) < 0) goto error;
+
+ /* Create a group using this filter */
+ if((gid = H5Gcreate2(file1, GROUP_NAME, H5P_DEFAULT, gcpl, H5P_DEFAULT)) < 0) goto error;
+
+ /* Create multiple groups under the main group */
+ for (i=0; i < GROUP_ITERATION; i++) {
+ sprintf(gname, "group_%d", i);
+ if((group = H5Gcreate2(gid, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error;
+ if(H5Gclose(group) < 0) goto error;
+ }
+
+ if(H5Fflush(file1, H5F_SCOPE_GLOBAL) < 0) goto error;
+
+ /* Unregister the filter before closing the group. It should fail */
+ H5E_BEGIN_TRY {
+ ret = H5Zunregister(H5Z_FILTER_DUMMY);
+ } H5E_END_TRY;
+ if(ret>=0) {
+ H5_FAILED();
+ printf(" Line %d: Should not be able to unregister filter\n", __LINE__);
+ goto error;
+ } /* end if */
+
+
+ /* Close the group */
+ if(H5Gclose(gid) < 0) goto error;
+
+ /* Clean up objects used for this test */
+ if(H5Pclose (gcpl) < 0) goto error;
+
+ if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error;
+ if(H5Pset_chunk (dc, 2, chunk_size) < 0) goto error;
+
+ if(H5Pset_filter(dc, H5Z_FILTER_DUMMY, 0, (size_t)0, NULL) < 0) goto error;
+
+ /* Initialize the dataset */
+ for(i = n = 0; i < DSET_DIM1; i++)
+ for(j = 0; j < DSET_DIM2; j++)
+ points[i][j] = n++;
+
+ /* Create the data space */
+ dims[0] = DSET_DIM1;
+ dims[1] = DSET_DIM2;
+ if((space = H5Screate_simple(2, dims, NULL)) < 0) goto error;
+
+ /* Create a dataset in the first file */
+ if((dataset = H5Dcreate2(file1, DSET_NAME, H5T_NATIVE_INT, space,
+ H5P_DEFAULT, dc, H5P_DEFAULT)) < 0) goto error;
+
+ /* Write the data to the dataset */
+ if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, points) < 0)
+ goto error;
+
+ /* Unregister the filter before closing the dataset. It should fail */
+ /*if(H5Zunregister(H5Z_FILTER_DUMMY) < 0) goto error;*/
+ H5E_BEGIN_TRY {
+ ret = H5Zunregister(H5Z_FILTER_DUMMY);
+ } H5E_END_TRY;
+ if(ret>=0) {
+ H5_FAILED();
+ printf(" Line %d: Should not be able to unregister filter\n", __LINE__);
+ goto error;
+ } /* end if */
+
+ if(H5Dclose(dataset) < 0) goto error;
+
+ /* Create a dataset in the second file */
+ if((dataset = H5Dcreate2(file2, DSET_NAME, H5T_NATIVE_INT, space,
+ H5P_DEFAULT, dc, H5P_DEFAULT)) < 0) goto error;
+
+ /* Write the data to the dataset */
+ if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, points) < 0)
+ goto error;
+
+ if(H5Dclose(dataset) < 0) goto error;
+
+ /* Unregister the filter after closing all objects but before closing files.
+ * It should flush all files. */
+ if(H5Zunregister(H5Z_FILTER_DUMMY) < 0) goto error;
+
+ /* Clean up objects used for this test */
+ if(H5Pclose (dc) < 0) goto error;
+ if(H5Fclose(file1) < 0) goto error;
+ if(H5Fclose(file2) < 0) goto error;
+
+ PASSED();
+ return 0;
+
+error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Tests unregistering filter with H5Zunregister
+ *
+ * Return: Success: exit(0)
+ *
+ * Failure: exit(1)
+ *
+ * Programmer: Raymond Lu
+ * 11 April 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ hid_t fapl;
+ int nerrors = 0;
+
+ /* Testing setup */
+ h5_reset();
+ fapl = h5_fileaccess();
+
+ /* Test unregistering filter in its own file */
+ nerrors += (test_unregister_filters(fapl) < 0 ? 1 : 0);
+
+ if(nerrors)
+ goto error;
+ printf("All dataset tests passed.\n");
+ h5_cleanup(FILENAME, fapl);
+
+ return 0;
+
+error:
+ nerrors = MAX(1, nerrors);
+ printf("***** %d DATASET TEST%s FAILED! *****\n",
+ nerrors, 1 == nerrors ? "" : "S");
+ return 1;
+}
+