diff options
Diffstat (limited to 'src/H5Z.c')
-rw-r--r-- | src/H5Z.c | 648 |
1 files changed, 584 insertions, 64 deletions
@@ -12,11 +12,17 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "H5private.h" -#include "H5Eprivate.h" -#include "H5MMprivate.h" -#include "H5Oprivate.h" -#include "H5Zprivate.h" +#define H5Z_PACKAGE /*suppress error about including H5Zpkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Dprivate.h" /* Dataset functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Oprivate.h" /* Object headers */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspace functions */ +#include "H5Zpkg.h" /* Data filters */ /* Pablo mask */ #define PABLO_MASK H5Z_mask @@ -26,12 +32,33 @@ static int interface_initialize_g = 0; static herr_t H5Z_init_interface (void); +/* Local typedefs */ +#ifdef H5Z_DEBUG +typedef struct H5Z_stats_t { + struct { + hsize_t total; /*total number of bytes processed */ + hsize_t errors; /*bytes of total attributable to errors */ + H5_timer_t timer; /*execution time including errors */ + } stats[2]; /*0=output, 1=input */ +} H5Z_stats_t; +#endif /* H5Z_DEBUG */ + +/* Enumerated type for dataset creation prelude callbacks */ +typedef enum { + H5Z_PRELUDE_CAN_APPLY, /* Call "can apply" callback */ + H5Z_PRELUDE_SET_LOCAL /* Call "set local" callback */ +} H5Z_prelude_type_t; + /* Local variables */ static size_t H5Z_table_alloc_g = 0; static size_t H5Z_table_used_g = 0; static H5Z_class_t *H5Z_table_g = NULL; +#ifdef H5Z_DEBUG +static H5Z_stats_t *H5Z_stat_table_g = NULL; +#endif /* H5Z_DEBUG */ /* Local functions */ +static int H5Z_find_idx(H5Z_filter_t id); /*------------------------------------------------------------------------- @@ -51,22 +78,31 @@ static H5Z_class_t *H5Z_table_g = NULL; static herr_t H5Z_init_interface (void) { + herr_t ret_value=SUCCEED; /* Return value */ + FUNC_ENTER_NOINIT(H5Z_init_interface); #ifdef H5_HAVE_FILTER_DEFLATE - H5Z_register (H5Z_FILTER_DEFLATE, "deflate", H5Z_filter_deflate); + if (H5Z_register (H5Z_DEFLATE)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register deflate filter"); #endif /* H5_HAVE_FILTER_DEFLATE */ #ifdef H5_HAVE_FILTER_SHUFFLE - H5Z_register (H5Z_FILTER_SHUFFLE, "shuffle", H5Z_filter_shuffle); + if (H5Z_register (H5Z_SHUFFLE)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register shuffle filter"); #endif /* H5_HAVE_FILTER_SHUFFLE */ #ifdef H5_HAVE_FILTER_FLETCHER32 - H5Z_register (H5Z_FILTER_FLETCHER32, "fletcher32", H5Z_filter_fletcher32); + if (H5Z_register (H5Z_FLETCHER32)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register fletcher32 filter"); #endif /* H5_HAVE_FILTER_FLETCHER32 */ #ifdef H5_HAVE_FILTER_SZIP - H5Z_register (H5Z_FILTER_SZIP, "szip", H5Z_filter_szip); + if (H5Z_register (H5Z_SZIP)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register szip filter"); #endif /* H5_HAVE_FILTER_SZIP */ - FUNC_LEAVE_NOAPI(SUCCEED); +#if (defined H5_HAVE_FILTER_DEFLATE | defined H5_HAVE_FILTER_FLETCHER32 | defined H5_HAVE_FILTER_SHUFFLE | defined H5_HAVE_FILTER_SZIP) +done: +#endif /* (defined H5_HAVE_FILTER_DEFLATE | defined H5_HAVE_FILTER_FLETCHER32 | defined H5_HAVE_FILTER_SHUFFLE | defined H5_HAVE_FILTER_SZIP) */ + FUNC_LEAVE_NOAPI(ret_value); } @@ -98,7 +134,7 @@ H5Z_term_interface (void) if (H5DEBUG(Z)) { for (i=0; i<H5Z_table_used_g; i++) { for (dir=0; dir<2; dir++) { - if (0==H5Z_table_g[i].stats[dir].total) continue; + if (0==H5Z_stat_table_g[i].stats[dir].total) continue; if (0==nprint++) { /* Print column headers */ @@ -125,34 +161,35 @@ H5Z_term_interface (void) * the word `Inf' if the elapsed time is zero. */ H5_bandwidth(bandwidth, - (double)(H5Z_table_g[i].stats[dir].total), - H5Z_table_g[i].stats[dir].timer.etime); + (double)(H5Z_stat_table_g[i].stats[dir].total), + H5Z_stat_table_g[i].stats[dir].timer.etime); /* Print the statistics */ HDfprintf (H5DEBUG(Z), " %s%-15s %10Hd %10Hd %8.2f %8.2f %8.2f " "%10s\n", dir?"<":">", comment, - H5Z_table_g[i].stats[dir].total, - H5Z_table_g[i].stats[dir].errors, - H5Z_table_g[i].stats[dir].timer.utime, - H5Z_table_g[i].stats[dir].timer.stime, - H5Z_table_g[i].stats[dir].timer.etime, + H5Z_stat_table_g[i].stats[dir].total, + H5Z_stat_table_g[i].stats[dir].errors, + H5Z_stat_table_g[i].stats[dir].timer.utime, + H5Z_stat_table_g[i].stats[dir].timer.stime, + H5Z_stat_table_g[i].stats[dir].timer.etime, bandwidth); } } } -#endif - /* Free the table */ - for (i=0; i<H5Z_table_used_g; i++) { - H5MM_xfree(H5Z_table_g[i].name); - } +#endif /* H5Z_DEBUG */ + /* Free the table of filters */ H5Z_table_g = H5MM_xfree(H5Z_table_g); +#ifdef H5Z_DEBUG + H5Z_stat_table_g = H5MM_xfree(H5Z_stat_table_g); +#endif /* H5Z_DEBUG */ H5Z_table_used_g = H5Z_table_alloc_g = 0; interface_initialize_g = 0; } return 0; } +#ifdef H5_WANT_H5_V1_4_COMPAT /*------------------------------------------------------------------------- * Function: H5Zregister @@ -166,13 +203,16 @@ H5Z_term_interface (void) * Thursday, April 16, 1998 * * Modifications: + * Changed to pass H5Z_class_t struct to H5Z_register + * Quincey Koziol, April 5, 2003 * *------------------------------------------------------------------------- */ herr_t H5Zregister(H5Z_filter_t id, const char *comment, H5Z_func_t func) { - herr_t ret_value=SUCCEED; /* Return value */ + H5Z_class_t cls; /* Filter class used to bundle parameters */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Zregister, FAIL); H5TRACE3("e","Zfsx",id,comment,func); @@ -185,13 +225,62 @@ H5Zregister(H5Z_filter_t id, const char *comment, H5Z_func_t func) if (!func) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no function specified"); + /* Build class structure */ + cls.id=id; + cls.name=comment; + cls.can_apply=cls.set_local=NULL; + cls.filter=func; + + /* Do it */ + if (H5Z_register (&cls)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter"); + +done: + FUNC_LEAVE_API(ret_value); +} +#else /* H5_WANT_H5_V1_4_COMPAT */ + +/*------------------------------------------------------------------------- + * Function: H5Zregister + * + * Purpose: This function registers new filter. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Thursday, April 16, 1998 + * + * Modifications: + * Changed to pass in H5Z_class_t struct + * Quincey Koziol, April 5, 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Zregister(const H5Z_class_t *cls) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Zregister, FAIL); + + /* Check args */ + if (cls==NULL) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter class"); + if (cls->id<0 || cls->id>H5Z_FILTER_MAX) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number"); + if (cls->id<H5Z_FILTER_RESERVED) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters"); + if (cls->filter==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no filter function specified"); + /* Do it */ - if (H5Z_register (id, comment, func)<0) + if (H5Z_register (cls)<0) HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter"); done: FUNC_LEAVE_API(ret_value); } +#endif /* H5_WANT_H5_V1_4_COMPAT */ /*------------------------------------------------------------------------- @@ -210,42 +299,54 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Z_register (H5Z_filter_t id, const char *comment, H5Z_func_t func) +H5Z_register (const H5Z_class_t *cls) { size_t i; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5Z_register, FAIL); - assert (id>=0 && id<=H5Z_FILTER_MAX); + assert (cls); + assert (cls->id>=0 && cls->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) break; - } + for (i=0; i<H5Z_table_used_g; i++) + if (H5Z_table_g[i].id==cls->id) + break; + + /* Filter not already registered */ if (i>=H5Z_table_used_g) { if (H5Z_table_used_g>=H5Z_table_alloc_g) { size_t n = MAX(H5Z_MAX_NFILTERS, 2*H5Z_table_alloc_g); H5Z_class_t *table = H5MM_realloc(H5Z_table_g, n*sizeof(H5Z_class_t)); +#ifdef H5Z_DEBUG + H5Z_stats_t *stat_table = H5MM_realloc(H5Z_stat_table_g, + n*sizeof(H5Z_stats_t)); +#endif /* H5Z_DEBUG */ if (!table) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend filter table"); H5Z_table_g = table; +#ifdef H5Z_DEBUG + if (!stat_table) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend filter statistics table"); + H5Z_stat_table_g = stat_table; +#endif /* H5Z_DEBUG */ H5Z_table_alloc_g = n; - } + } /* end if */ /* Initialize */ i = H5Z_table_used_g++; - HDmemset(H5Z_table_g+i, 0, sizeof(H5Z_class_t)); - H5Z_table_g[i].id = id; - H5Z_table_g[i].name = H5MM_xstrdup(comment); - H5Z_table_g[i].func = func; - } else { + HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class_t)); +#ifdef H5Z_DEBUG + HDmemset(H5Z_stat_table_g+i, 0, sizeof(H5Z_stats_t)); +#endif /* H5Z_DEBUG */ + } /* end if */ + /* Filter already registered */ + else { /* Replace old contents */ - H5MM_xfree(H5Z_table_g[i].name); - H5Z_table_g[i].name = H5MM_xstrdup(comment); - H5Z_table_g[i].func = func; - } + HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class_t)); + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -310,7 +411,7 @@ H5Z_unregister (H5Z_filter_t id) size_t i; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOINIT(H5Z_unregister); + FUNC_ENTER_NOAPI(H5Z_unregister,FAIL); assert (id>=0 && id<=H5Z_FILTER_MAX); @@ -326,6 +427,9 @@ H5Z_unregister (H5Z_filter_t id) /* 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_class_t)*((H5Z_table_used_g-1)-i)); +#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)); +#endif /* H5Z_DEBUG */ H5Z_table_used_g--; done: @@ -373,6 +477,295 @@ done: /*------------------------------------------------------------------------- + * Function: H5Z_prelude_callback + * + * Purpose: Makes a dataset creation "prelude" callback for the "can_apply" + * or "set_local" routines. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, April 4, 2003 + * + * Notes: + * The chunk dimensions are used to create a dataspace, instead + * of passing in the dataset's dataspace, since the chunk + * dimensions are what the I/O filter will actually see + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_type) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5Z_prelude_callback); + + assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id)); + assert (H5I_DATATYPE==H5I_get_type(type_id)); + + /* Check if the property list is non-default */ + if(dcpl_id!=H5P_DATASET_CREATE_DEFAULT) { + H5P_genplist_t *dc_plist; /* Dataset creation property list object */ + H5D_layout_t dcpl_layout; /* Dataset's layout information */ + + /* Get dataset creation property list object */ + if (NULL == (dc_plist = H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list"); + + /* Get layout information */ + if(H5P_get(dc_plist, H5D_CRT_LAYOUT_NAME, &dcpl_layout) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve layout"); + + /* Check if the dataset is chunked */ + if(H5D_CHUNKED == dcpl_layout) { + H5O_pline_t dcpl_pline; /* Dataset's I/O pipeline information */ + + /* Get I/O pipeline information */ + if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &dcpl_pline) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve pipeline filter"); + + /* Check if the chunks have filters */ + if(dcpl_pline.nfilters > 0) { + int chunk_ndims; /* # of chunk dimensions */ + hsize_t chunk_size[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */ + H5S_t *space; /* Dataspace describing chunk */ + hid_t space_id; /* ID for dataspace describing chunk */ + size_t u; /* Local index variable */ + + /* Get chunk information */ + if(H5P_get(dc_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve chunk dimensions"); + if(H5P_get(dc_plist, H5D_CRT_CHUNK_SIZE_NAME, chunk_size) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve chunk size"); + + /* Create a data space for a chunk & set the extent */ + if(NULL == (space = H5S_create_simple(chunk_ndims,chunk_size,NULL))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); + + /* Get ID for dataspace to pass to filter routines */ + if ((space_id=H5I_register (H5I_DATASPACE, space))<0) { + H5S_close(space); + HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + } /* end if */ + + /* Iterate over filters */ + for (u=0; u<dcpl_pline.nfilters; u++) { + H5Z_class_t *fclass; /* Individual filter information */ + + /* Get filter information */ + if (NULL==(fclass=H5Z_find(dcpl_pline.filter[u].id))) { + /* Ignore errors from optional filters */ + if (dcpl_pline.filter[u].flags & H5Z_FLAG_OPTIONAL) + H5E_clear(); + else + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "required filter was not located"); + } /* end if */ + else { + /* Make correct callback */ + switch(prelude_type) { + case H5Z_PRELUDE_CAN_APPLY: + /* Check if there is a "can apply" callback */ + if(fclass->can_apply) { + /* Make callback to filter's "can apply" function */ + herr_t status=(fclass->can_apply)(dcpl_id, type_id, space_id); + + /* Check return value */ + if(status<=0) { + /* We're leaving, so close dataspace */ + if(H5Sclose(space_id)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace"); + + /* Indicate filter can't apply to this combination of parameters */ + if(status==0) { + HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "filter parameters not appropriate"); + } /* end if */ + /* Indicate error during filter callback */ + else { + HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "error during user callback"); + } /* end if */ + } /* end if */ + } /* end if */ + break; + + case H5Z_PRELUDE_SET_LOCAL: + /* Check if there is a "set local" callback */ + if(fclass->set_local) { + /* Make callback to filter's "set local" function */ + if((fclass->set_local)(dcpl_id, type_id, space_id)<0) { + /* We're leaving, so close dataspace */ + if(H5Sclose(space_id)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace"); + + /* Indicate error during filter callback */ + HGOTO_ERROR(H5E_PLINE, H5E_SETLOCAL, FAIL, "error during user callback"); + } /* end if */ + } /* end if */ + break; + + default: + assert("invalid prelude type" && 0); + } /* end switch */ + } /* end else */ + } /* end for */ + + /* Close dataspace */ + if(H5Sclose(space_id)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace"); + } /* end if */ + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_prelude_callback() */ + + +/*------------------------------------------------------------------------- + * Function: H5Z_can_apply + * + * Purpose: Checks if all the filters defined in the dataset creation + * property list can be applied to a particular combination of + * datatype and dataspace for a dataset. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, April 3, 2003 + * + * Notes: + * The chunk dimensions are used to create a dataspace, instead + * of passing in the dataset's dataspace, since the chunk + * dimensions are what the I/O filter will actually see + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Z_can_apply (hid_t dcpl_id, hid_t type_id) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5Z_can_apply,FAIL); + + assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id)); + assert (H5I_DATATYPE==H5I_get_type(type_id)); + + /* Make "can apply" callbacks for filters in pipeline */ + if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_CAN_APPLY)<0) + HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "filter parameters not appropriate"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_can_apply() */ + + +/*------------------------------------------------------------------------- + * Function: H5Z_set_local + * + * Purpose: Makes callbacks to modify dataset creation list property + * settings for filters on a new dataset, based on the datatype + * and dataspace of that dataset (chunk). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, April 4, 2003 + * + * Notes: + * The chunk dimensions are used to create a dataspace, instead + * of passing in the dataset's dataspace, since the chunk + * dimensions are what the I/O filter will actually see + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Z_set_local (hid_t dcpl_id, hid_t type_id) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5Z_set_local,FAIL); + + assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id)); + assert (H5I_DATATYPE==H5I_get_type(type_id)); + + /* Make "set local" callbacks for filters in pipeline */ + if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_SET_LOCAL)<0) + HGOTO_ERROR(H5E_PLINE, H5E_SETLOCAL, FAIL, "local filter parameters not set"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_set_local() */ + + +/*------------------------------------------------------------------------- + * Function: H5Z_modify + * + * Purpose: Modify filter parameters for specified pipeline. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, April 5, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Z_modify(H5O_pline_t *pline, H5Z_filter_t filter, unsigned flags, + size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/]) +{ + size_t idx; /* Index of filter in pipeline */ + size_t i; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5Z_modify, FAIL); + + assert(pline); + assert(filter>=0 && filter<=H5Z_FILTER_MAX); + assert(0==(flags & ~((unsigned)H5Z_FLAG_DEFMASK))); + assert(0==cd_nelmts || cd_values); + + /* Locate the filter in the pipeline */ + for(idx=0; idx<pline->nfilters; idx++) + if(pline->filter[idx].id==filter) + break; + + /* Check if the filter was not already in the pipeline */ + if(idx>pline->nfilters) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter not in pipeline"); + + /* Change parameters for filter */ + pline->filter[idx].flags = flags; + pline->filter[idx].cd_nelmts = cd_nelmts; + + /* Free any existing parameters */ + if(pline->filter[idx].cd_values!=NULL) + H5MM_xfree(pline->filter[idx].cd_values); + + /* Set parameters */ + if (cd_nelmts>0) { + pline->filter[idx].cd_values = H5MM_malloc(cd_nelmts*sizeof(unsigned)); + if (NULL==pline->filter[idx].cd_values) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for filter parameters"); + for (i=0; i<cd_nelmts; i++) + pline->filter[idx].cd_values[i] = cd_values[i]; + } /* end if */ + else + pline->filter[idx].cd_values = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_modify() */ + + +/*------------------------------------------------------------------------- * Function: H5Z_append * * Purpose: Append another filter to the specified pipeline. @@ -441,38 +834,74 @@ done: /*------------------------------------------------------------------------- + * Function: H5Z_find_idx + * + * Purpose: Given a filter ID return the offset in the global array + * that holds all the registered filters. + * + * Return: Success: Non-negative index of entry in global filter table. + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, April 5, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5Z_find_idx(H5Z_filter_t id) +{ + size_t i; /* Local index variable */ + int ret_value=FAIL; /* Return value */ + + FUNC_ENTER_NOINIT(H5Z_find_idx); + + for (i=0; i<H5Z_table_used_g; i++) + if (H5Z_table_g[i].id == id) + HGOTO_DONE((int)i); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_find_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5Z_find * * Purpose: Given a filter ID return a pointer to a global struct that * defines the filter. * * Return: Success: Ptr to entry in global filter table. - * * Failure: NULL * * Programmer: Robb Matzke * Wednesday, August 5, 1998 * * Modifications: + * Use H5Z_find_idx now + * Quincey Koziol, April 5, 2003 * *------------------------------------------------------------------------- */ H5Z_class_t * H5Z_find(H5Z_filter_t id) { - size_t i; - H5Z_class_t *ret_value=NULL; /* Return value */ + int idx; /* Filter index in global table */ + H5Z_class_t *ret_value=NULL; /* Return value */ FUNC_ENTER_NOAPI(H5Z_find, NULL); - for (i=0; i<H5Z_table_used_g; i++) { - if (H5Z_table_g[i].id == id) - HGOTO_DONE(H5Z_table_g+i); - } + /* Get the index in the global table */ + if((idx=H5Z_find_idx(id))<0) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, NULL, "required filter is not registered"); + + /* Set return value */ + ret_value=H5Z_table_g+idx; done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* H5Z_find() */ /*------------------------------------------------------------------------- @@ -504,23 +933,24 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Z_pipeline(H5F_t UNUSED *f, const H5O_pline_t *pline, unsigned flags, +H5Z_pipeline(const H5O_pline_t *pline, unsigned flags, unsigned *filter_mask/*in,out*/, H5Z_EDC_t edc_read, H5Z_cb_t cb_struct, size_t *nbytes/*in,out*/, size_t *buf_size/*in,out*/, void **buf/*in,out*/) { size_t i, idx, new_nbytes; - H5Z_class_t *fclass=NULL; - unsigned failed = 0; - unsigned tmp_flags; + int fclass_idx; /* Index of filter class in global table */ + H5Z_class_t *fclass=NULL; /* Filter class pointer */ #ifdef H5Z_DEBUG + H5Z_stats_t *fstats=NULL; /* Filter stats pointer */ H5_timer_t timer; #endif + unsigned failed = 0; + unsigned tmp_flags; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5Z_pipeline, FAIL); - assert(f); assert(0==(flags & ~((unsigned)H5Z_FLAG_INVMASK))); assert(filter_mask); assert(nbytes && *nbytes>0); @@ -536,22 +966,24 @@ H5Z_pipeline(H5F_t UNUSED *f, const H5O_pline_t *pline, unsigned flags, failed |= (unsigned)1 << idx; continue;/*filter excluded*/ } - if (NULL==(fclass=H5Z_find(pline->filter[idx].id))) { + if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) { failed |= (unsigned)1 << idx; HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter is not registered"); } + fclass=&H5Z_table_g[fclass_idx]; #ifdef H5Z_DEBUG + fstats=&H5Z_stat_table_g[fclass_idx]; H5_timer_begin(&timer); #endif tmp_flags=flags|(pline->filter[idx].flags); tmp_flags|=(edc_read== H5Z_DISABLE_EDC) ? H5Z_FLAG_SKIP_EDC : 0; - new_nbytes = (fclass->func)(tmp_flags, pline->filter[idx].cd_nelmts, + new_nbytes = (fclass->filter)(tmp_flags, pline->filter[idx].cd_nelmts, pline->filter[idx].cd_values, *nbytes, buf_size, buf); #ifdef H5Z_DEBUG - H5_timer_end(&(fclass->stats[1].timer), &timer); - fclass->stats[1].total += MAX(*nbytes, new_nbytes); - if (0==new_nbytes) fclass->stats[1].errors += *nbytes; + H5_timer_end(&(fstats->stats[1].timer), &timer); + fstats->stats[1].total += MAX(*nbytes, new_nbytes); + if (0==new_nbytes) fstats->stats[1].errors += *nbytes; #endif if(0==new_nbytes) { @@ -572,7 +1004,7 @@ H5Z_pipeline(H5F_t UNUSED *f, const H5O_pline_t *pline, unsigned flags, failed |= (unsigned)1 << idx; continue; /*filter excluded*/ } - if (NULL==(fclass=H5Z_find(pline->filter[idx].id))) { + if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) { failed |= (unsigned)1 << idx; if (pline->filter[idx].flags & H5Z_FLAG_OPTIONAL) { H5E_clear(); @@ -581,15 +1013,17 @@ H5Z_pipeline(H5F_t UNUSED *f, const H5O_pline_t *pline, unsigned flags, HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "required filter is not registered"); } } + fclass=&H5Z_table_g[fclass_idx]; #ifdef H5Z_DEBUG + fstats=&H5Z_stat_table_g[fclass_idx]; H5_timer_begin(&timer); #endif - new_nbytes = (fclass->func)(flags|(pline->filter[idx].flags), pline->filter[idx].cd_nelmts, + new_nbytes = (fclass->filter)(flags|(pline->filter[idx].flags), pline->filter[idx].cd_nelmts, pline->filter[idx].cd_values, *nbytes, buf_size, buf); #ifdef H5Z_DEBUG - H5_timer_end(&(fclass->stats[0].timer), &timer); - fclass->stats[0].total += MAX(*nbytes, new_nbytes); - if (0==new_nbytes) fclass->stats[0].errors += *nbytes; + H5_timer_end(&(fstats->stats[0].timer), &timer); + fstats->stats[0].total += MAX(*nbytes, new_nbytes); + if (0==new_nbytes) fstats->stats[0].errors += *nbytes; #endif if(0==new_nbytes) { if (0==(pline->filter[idx].flags & H5Z_FLAG_OPTIONAL)) { @@ -616,3 +1050,89 @@ done: FUNC_LEAVE_NOAPI(ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5Z_filter_info + * + * Purpose: Get pointer to filter info for pipeline + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, April 5, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5Z_filter_info_t * +H5Z_filter_info(H5O_pline_t *pline, H5Z_filter_t filter) +{ + size_t idx; /* Index of filter in pipeline */ + H5Z_filter_info_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5Z_filter_info, NULL); + + assert(pline); + assert(filter>=0 && filter<=H5Z_FILTER_MAX); + + /* Locate the filter in the pipeline */ + for(idx=0; idx<pline->nfilters; idx++) + if(pline->filter[idx].id==filter) + break; + + /* Check if the filter was not already in the pipeline */ + if(idx>pline->nfilters) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, NULL, "filter not in pipeline"); + + /* Set return value */ + ret_value=&pline->filter[idx]; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_filter_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5Z_all_filters_avail + * + * Purpose: Verify that all the filters in a pipeline are currently + * available (i.e. registered) + * + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, April 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5Z_all_filters_avail(H5O_pline_t *pline) +{ + size_t i,j; /* Local index variable */ + htri_t ret_value=TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5Z_all_filters_avail, UFAIL); + + /* Check args */ + assert(pline); + + /* Iterate through all the filters in pipeline */ + for(i=0; i<pline->nfilters; i++) { + + /* Look for each filter in the list of registered filters */ + for(j=0; j<H5Z_table_used_g; j++) + if(H5Z_table_g[j].id==pline->filter[i].id) + break; + + /* Check if we didn't find the filter */ + if(j==H5Z_table_used_g) + HGOTO_DONE(FALSE); + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5Z_all_filters_avail() */ + |