/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* 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 HDF5 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define H5Z_PACKAGE /*suppress error about including H5Zpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5Z_init_interface
#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 */
#ifdef H5_HAVE_SZLIB_H
# include "szlib.h"
#endif
/* 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);
/*-------------------------------------------------------------------------
* Function: H5Z_init_interface
*
* Purpose: Initializes the data filter layer.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Thursday, April 16, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5Z_init_interface (void)
{
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5Z_init_interface)
#ifdef H5_HAVE_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
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
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
if (H5Z_register (H5Z_SZIP)<0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register szip filter")
#endif /* H5_HAVE_FILTER_SZIP */
#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)
}
/*-------------------------------------------------------------------------
* Function: H5Z_term_interface
*
* Purpose: Terminate the H5Z layer.
*
* Return: void
*
* Programmer: Robb Matzke
* Thursday, April 16, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
H5Z_term_interface (void)
{
#ifdef H5Z_DEBUG
size_t i;
int dir, nprint=0;
char comment[16], bandwidth[32];
#endif
if (H5_interface_initialize_g) {
#ifdef H5Z_DEBUG
if (H5DEBUG(Z)) {
for (i=0; i<H5Z_table_used_g; i++) {
for (dir=0; dir<2; dir++) {
if (0==H5Z_stat_table_g[i].stats[dir].total) continue;
if (0==nprint++) {
/* Print column headers */
HDfprintf (H5DEBUG(Z), "H5Z: filter statistics "
"accumulated over life of library:\n");
HDfprintf (H5DEBUG(Z),
" %-16s %10s %10s %8s %8s %8s %10s\n",
"Filter", "Total", "Errors", "User",
"System", "Elapsed", "Bandwidth");
HDfprintf (H5DEBUG(Z),
" %-16s %10s %10s %8s %8s %8s %10s\n",
"------", "-----", "------", "----",
"------", "-------", "---------");
}
/* Truncate the comment to fit in the field */
HDstrncpy(comment, H5Z_table_g[i].name,
sizeof comment);
comment[sizeof(comment)-1] = '\0';
/*
* Format bandwidth to have four significant digits and
* units of `B/s', `kB/s', `MB/s', `GB/s', or `TB/s' or
* the word `Inf' if the elapsed time is zero.
*/
H5_bandwidth(bandwidth,
(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_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 /* 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;
H5_interface_initialize_g = 0;
}
return 0;
}
#ifdef H5_WANT_H5_V1_4_COMPAT
/*-------------------------------------------------------------------------
* Function: H5Zregister
*
* Purpose: This function registers new filter. The COMMENT argument is
* used for debugging and may be the null pointer.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* 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)
{
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);
/* Check args */
if (id<0 || id>H5Z_FILTER_MAX)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number");
if (id<H5Z_FILTER_RESERVED)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters");
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)
H5TRACE1("e","Zc",cls);
/* 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 (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 */
/*-------------------------------------------------------------------------
* Function: H5Z_register
*
* Purpose: Same as the public version except this one allows filters
* to be set for predefined method numbers <H5Z_FILTER_RESERVED
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Thursday, April 16, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Z_register (const H5Z_class_t *cls)
{
size_t i;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5Z_register, FAIL)
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==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++;
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 */
HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class_t));
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5Zunregister
*
* Purpose: This function unregisters a filter.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, November 14, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Zunregister(H5Z_filter_t id)
{
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Zunregister, FAIL)
H5TRACE1("e","Zf",id);
/* Check args */
if (id<0 || id>H5Z_FILTER_MAX)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number")
if (id<H5Z_FILTER_RESERVED)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters")
/* Do it */
if (H5Z_unregister (id)<0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to unregister filter")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Zunregister() */
/*-------------------------------------------------------------------------
* Function: H5Z_unregister
*
* Purpose: Same as the public version except this one allows filters
* to be unset for predefined method numbers <H5Z_FILTER_RESERVED
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, November 14, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Z_unregister (H5Z_filter_t id)
{
size_t i; /* Local index variable */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5Z_unregister,FAIL)
assert (id>=0 && 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;
/* Fail if filter not found */
if (i>=H5Z_table_used_g)
HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter is not registered")
/* 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:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5Z_unregister() */
/*-------------------------------------------------------------------------
* Function: H5Zfilter_avail
*
* Purpose: Check if a filter is available
*
* Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, November 14, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5Zfilter_avail(H5Z_filter_t id)
{
size_t i; /* Local index variable */
htri_t ret_value=FALSE; /* Return value */
FUNC_ENTER_API(H5Zfilter_avail, FAIL)
H5TRACE1("t","Zf",id);
/* Check args */
if(id<0 || id>H5Z_FILTER_MAX)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number")
/* Is the filter already registered? */
for(i=0; i<H5Z_table_used_g; i++)
if(H5Z_table_g[i].id==id) {
ret_value=TRUE;
break;
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Zfilter_avail() */
/*-------------------------------------------------------------------------
* 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_NOAPI_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.nused > 0) {
unsigned chunk_ndims; /* # of chunk dimensions */
size_t chunk_size[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */
hsize_t chunk_dims[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 */
for(u=0; u<chunk_ndims; u++)
chunk_dims[u]=chunk_size[u];
if(NULL == (space = H5S_create_simple(chunk_ndims,chunk_dims,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) {
(void)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.nused; 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) {
herr_t status;
/* Make callback to filter's "can apply" function */
status=(fclass->can_apply)(dcpl_id, type_id, space_id);
/* Check return value */
if(status<=0) {
/* We're leaving, so close dataspace */
if(H5I_dec_ref(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(H5I_dec_ref(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(H5I_dec_ref(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, "unable to apply filter")
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(const 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->nused; idx++)
if(pline->filter[idx].id==filter)
break;
/* Check if the filter was not already in the pipeline */
if(idx>pline->nused)
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.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Tuesday, August 4, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Z_append(H5O_pline_t *pline, H5Z_filter_t filter, unsigned flags,
size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/])
{
size_t idx, i;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5Z_append, FAIL)
assert(pline);
assert(filter>=0 && filter<=H5Z_FILTER_MAX);
assert(0==(flags & ~((unsigned)H5Z_FLAG_DEFMASK)));
assert(0==cd_nelmts || cd_values);
/*
* Check filter limit. We do it here for early warnings although we may
* decide to relax this restriction in the future.
*/
if (pline->nused>=H5Z_MAX_NFILTERS)
HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "too many filters in pipeline")
/* Allocate additional space in the pipeline if it's full */
if (pline->nused>=pline->nalloc) {
H5O_pline_t x;
x.nalloc = MAX(H5Z_MAX_NFILTERS, 2*pline->nalloc);
x.filter = H5MM_realloc(pline->filter, x.nalloc*sizeof(x.filter[0]));
if (NULL==x.filter)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for filter pipeline")
pline->nalloc = x.nalloc;
pline->filter = x.filter;
}
/* Add the new filter to the pipeline */
idx = pline->nused;
pline->filter[idx].id = filter;
pline->filter[idx].flags = flags;
pline->filter[idx].name = NULL; /*we'll pick it up later*/
pline->filter[idx].cd_nelmts = cd_nelmts;
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")
for (i=0; i<cd_nelmts; i++)
pline->filter[idx].cd_values[i] = cd_values[i];
} else {
pline->filter[idx].cd_values = NULL;
}
pline->nused++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* 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_NOAPI_NOINIT_NOFUNC(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)
{
int idx; /* Filter index in global table */
H5Z_class_t *ret_value=NULL; /* Return value */
FUNC_ENTER_NOAPI(H5Z_find, NULL)
/* 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() */
/*-------------------------------------------------------------------------
* Function: H5Z_pipeline
*
* Purpose: Process data through the filter pipeline. The FLAGS argument
* is the filter invocation flags (definition flags come from
* the PLINE->filter[].flags). The filters are processed in
* definition order unless the H5Z_FLAG_REVERSE is set. The
* FILTER_MASK is a bit-mask to indicate which filters to skip
* and on exit will indicate which filters failed. Each
* filter has an index number in the pipeline and that index
* number is the filter's bit in the FILTER_MASK. NBYTES is the
* number of bytes of data to filter and on exit should be the
* number of resulting bytes while BUF_SIZE holds the total
* allocated size of the buffer, which is pointed to BUF.
*
* If the buffer must grow during processing of the pipeline
* then the pipeline function should free the original buffer
* and return a fresh buffer, adjusting BUF_SIZE accordingly.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Tuesday, August 4, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
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;
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(0==(flags & ~((unsigned)H5Z_FLAG_INVMASK)));
assert(filter_mask);
assert(nbytes && *nbytes>0);
assert(buf_size && *buf_size>0);
assert(buf && *buf);
assert(!pline || pline->nused<H5Z_MAX_NFILTERS);
if (pline && (flags & H5Z_FLAG_REVERSE)) { /* Read */
for (i=pline->nused; i>0; --i) {
idx = i-1;
if (*filter_mask & ((unsigned)1<<idx)) {
failed |= (unsigned)1 << idx;
continue;/*filter excluded*/
}
if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) {
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->filter)(tmp_flags, pline->filter[idx].cd_nelmts,
pline->filter[idx].cd_values, *nbytes, buf_size, buf);
#ifdef H5Z_DEBUG
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) {
if((cb_struct.func && (H5Z_CB_FAIL==cb_struct.func(pline->filter[idx].id, *buf, *buf_size, cb_struct.op_data)))
|| !cb_struct.func)
HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "filter returned failure during read")
*nbytes = *buf_size;
failed |= (unsigned)1 << idx;
H5E_clear();
} else {
*nbytes = new_nbytes;
}
}
} else if (pline) { /* Write */
for (idx=0; idx<pline->nused; idx++) {
if (*filter_mask & ((unsigned)1<<idx)) {
failed |= (unsigned)1 << idx;
continue; /*filter excluded*/
}
if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) {
/* Check if filter is optional -- If it isn't, then error */
if ((pline->filter[idx].flags & H5Z_FLAG_OPTIONAL) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "required filter is not registered")
failed |= (unsigned)1 << idx;
H5E_clear();
continue; /*filter excluded*/
}
fclass=&H5Z_table_g[fclass_idx];
#ifdef H5Z_DEBUG
fstats=&H5Z_stat_table_g[fclass_idx];
H5_timer_begin(&timer);
#endif
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(&(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)) {
if((cb_struct.func && (H5Z_CB_FAIL==cb_struct.func(pline->filter[idx].id, *buf, *nbytes, cb_struct.op_data)))
|| !cb_struct.func)
HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "filter returned failure")
*nbytes = *buf_size;
}
failed |= (unsigned)1 << idx;
H5E_clear();
} else {
*nbytes = new_nbytes;
}
}
}
*filter_mask = failed;
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(const 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->nused; idx++)
if(pline->filter[idx].id==filter)
break;
/* Check if the filter was not already in the pipeline */
if(idx>pline->nused)
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(const 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, FAIL)
/* Check args */
assert(pline);
/* Iterate through all the filters in pipeline */
for(i=0; i<pline->nused; 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() */
/*-------------------------------------------------------------------------
* Function: H5Z_delete
*
* Purpose: Delete filter FILTER from pipeline PLINE;
* deletes all filters if FILTER is H5Z_FILTER_NONE
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Pedro Vicente
* Monday, January 26, 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Z_delete(H5O_pline_t *pline, H5Z_filter_t filter)
{
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5Z_delete, FAIL)
/* Check args */
assert(pline);
assert(filter>=0 && filter<=H5Z_FILTER_MAX);
/* if the pipeline has no filters, just return */
if(pline->nused==0)
HGOTO_DONE(SUCCEED)
/* Delete all filters */
if (H5Z_FILTER_ALL==filter) {
if(H5O_reset(H5O_PLINE_ID, pline)<0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFREE, FAIL, "can't release pipeline info")
} /* end if */
/* Delete filter */
else {
size_t idx; /* Index of filter in pipeline */
unsigned found=0; /* Indicate filter was found in pipeline */
/* Locate the filter in the pipeline */
for(idx=0; idx<pline->nused; idx++)
if(pline->filter[idx].id==filter) {
found=1;
break;
}
/* filter was not found in the pipeline */
if (!found)
HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter not in pipeline")
/* Free information for deleted filter */
H5MM_xfree(pline->filter[idx].name);
H5MM_xfree(pline->filter[idx].cd_values);
/* Remove filter from pipeline array */
if((idx+1)<pline->nused)
HDmemcpy(&pline->filter[idx], &pline->filter[idx+1],
sizeof (H5Z_filter_info_t)*(pline->nused-(idx+1)));
/* Decrement number of used filters */
pline->nused--;
/* Reset information for previous last filter in pipeline */
HDmemset(&pline->filter[pline->nused], 0, sizeof (H5Z_filter_info_t));
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5Zget_filter_info
*
* Purpose: Gets information about a pipeline data filter and stores it
* in filter_config_flags.
*
* Return: zero on success / negative on failure
*
* Programmer: James Laird and Nat Furrer
* Monday, June 7, 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t H5Zget_filter_info(H5Z_filter_t filter, unsigned int *filter_config_flags)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Zget_filter_info, FAIL)
if (filter_config_flags != NULL)
{
if (filter == H5Z_FILTER_SZIP)
{
*filter_config_flags = 0;
#ifdef H5_HAVE_FILTER_SZIP
if(SZ_encoder_enabled()>0)
*filter_config_flags |= H5Z_FILTER_CONFIG_ENCODE_ENABLED;
#endif /* H5_HAVE_FILTER_SZIP */
*filter_config_flags |= H5Z_FILTER_CONFIG_DECODE_ENABLED;
}
else
*filter_config_flags = H5Z_FILTER_CONFIG_DECODE_ENABLED | H5Z_FILTER_CONFIG_ENCODE_ENABLED;
/* Make sure the filter exists */
if (H5Z_find(filter) == NULL)
*filter_config_flags = 0;
}
done:
FUNC_LEAVE_API(ret_value)
}
syntax highlighted by Code2HTML, v. 0.9.1