diff options
Diffstat (limited to 'src/H5Z.c')
| -rw-r--r-- | src/H5Z.c | 1711 |
1 files changed, 1010 insertions, 701 deletions
@@ -1,235 +1,225 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * 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 */ +#include "H5Zmodule.h" /* This source code file is part of the H5Z module */ + +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ +#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 */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5PLprivate.h" /* Plugins */ +#include "H5Sprivate.h" /* Dataspace functions */ +#include "H5Zpkg.h" /* Data filters */ #ifdef H5_HAVE_SZLIB_H -# include "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 */ + hsize_t total; /* total number of bytes processed */ + hsize_t errors; /* bytes of total attributable to errors */ + H5_timevals_t times; /* execution time including errors */ + } stats[2]; /* 0 = output, 1 = input */ } H5Z_stats_t; #endif /* H5Z_DEBUG */ +typedef struct H5Z_object_t { + H5Z_filter_t filter_id; /* ID of the filter we're looking for */ + htri_t found; /* Whether we find an object using the filter */ +#ifdef H5_HAVE_PARALLEL + hbool_t + sanity_checked; /* Whether the sanity check for collectively calling H5Zunregister has been done */ +#endif /* H5_HAVE_PARALLEL */ +} H5Z_object_t; + /* 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_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_class2_t *H5Z_table_g = NULL; +static size_t H5Z_table_alloc_g = 0; +static size_t H5Z_table_used_g = 0; +static H5Z_class2_t *H5Z_table_g = NULL; #ifdef H5Z_DEBUG -static H5Z_stats_t *H5Z_stat_table_g = NULL; +static H5Z_stats_t *H5Z_stat_table_g = NULL; #endif /* H5Z_DEBUG */ /* Local functions */ -static int H5Z_find_idx(H5Z_filter_t id); +static int H5Z__find_idx(H5Z_filter_t id); +static int H5Z__check_unregister_dset_cb(void *obj_ptr, hid_t obj_id, void *key); +static int H5Z__check_unregister_group_cb(void *obj_ptr, hid_t obj_id, void *key); +static int H5Z__flush_file_cb(void *obj_ptr, hid_t obj_id, void *key); - /*------------------------------------------------------------------------- - * Function: H5Z_init_interface - * - * Purpose: Initializes the data filter layer. + * Function: H5Z_init * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, April 16, 1998 - * - * Modifications: + * Purpose: Initialize the interface from some other layer. * + * Return: Success: non-negative + * Failure: negative *------------------------------------------------------------------------- */ -static herr_t -H5Z_init_interface (void) +herr_t +H5Z_init(void) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_NOAPI(FAIL) + if (H5_TERM_GLOBAL) + HGOTO_DONE(SUCCEED) + + /* Internal filters */ + if (H5Z_register(H5Z_SHUFFLE) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register shuffle filter") + if (H5Z_register(H5Z_FLETCHER32) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register fletcher32 filter") + if (H5Z_register(H5Z_NBIT) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register nbit filter") + if (H5Z_register(H5Z_SCALEOFFSET) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register scaleoffset filter") + + /* External filters */ #ifdef H5_HAVE_FILTER_DEFLATE - if (H5Z_register (H5Z_DEFLATE)<0) - HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register deflate filter") + 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 H5Z_SZIP->encoder_present = SZ_encoder_enabled(); - if (H5Z_register (H5Z_SZIP)<0) - HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register szip filter") + if (H5Z_register(H5Z_SZIP) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register szip filter") #endif /* H5_HAVE_FILTER_SZIP */ -#ifdef H5_HAVE_FILTER_NBIT - if (H5Z_register (H5Z_NBIT)<0) - HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register nbit filter") -#endif /* H5_HAVE_FILTER_NBIT */ -#ifdef H5_HAVE_FILTER_SCALEOFFSET - if (H5Z_register (H5Z_SCALEOFFSET)<0) - HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register scaleoffset filter") -#endif /* H5_HAVE_FILTER_SCALEOFFSET */ - -#if (defined H5_HAVE_FILTER_DEFLATE | defined H5_HAVE_FILTER_FLETCHER32 | defined H5_HAVE_FILTER_SHUFFLE | defined H5_HAVE_FILTER_SZIP | defined H5_HAVE_FILTER_NBIT | defined H5_HAVE_FILTER_SCALEOFFSET) + done: -#endif /* (defined H5_HAVE_FILTER_DEFLATE | defined H5_HAVE_FILTER_FLETCHER32 | defined H5_HAVE_FILTER_SHUFFLE | defined H5_HAVE_FILTER_SZIP | defined H5_HAVE_FILTER_NBIT | defined H5_HAVE_FILTER_SCALEOFFSET) */ FUNC_LEAVE_NOAPI(ret_value) } - /*------------------------------------------------------------------------- - * Function: H5Z_term_interface + * Function: H5Z_term_package * - * Purpose: Terminate the H5Z layer. - * - * Return: void - * - * Programmer: Robb Matzke - * Thursday, April 16, 1998 - * - * Modifications: + * Purpose: Terminate the H5Z layer. * + * Return: void *------------------------------------------------------------------------- */ int -H5Z_term_interface(void) +H5Z_term_package(void) { -#ifdef H5Z_DEBUG - size_t i; - int dir, nprint=0; - char comment[16], bandwidth[32]; -#endif + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR - 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 = (H5Z_class2_t *)H5MM_xfree(H5Z_table_g); + char comment[16], bandwidth[32]; + int dir, nprint = 0; + size_t i; + + if (H5DEBUG(Z)) { + for (i = 0; i < H5Z_table_used_g; i++) { + for (dir = 0; dir < 2; dir++) { + struct { + char *user; + char *system; + char *elapsed; + } timestrs = {H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.user), + H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.system), + H5_timer_get_time_string(H5Z_stat_table_g[i].stats[dir].times.elapsed)}; + if (0 == H5Z_stat_table_g[i].stats[dir].total) + goto next; + + 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", "------", "-----", + "------", "----", "------", "-------", "---------"); + } /* end if */ + + /* 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, sizeof(bandwidth), (double)(H5Z_stat_table_g[i].stats[dir].total), + H5Z_stat_table_g[i].stats[dir].times.elapsed); + + /* Print the statistics */ + HDfprintf(H5DEBUG(Z), " %s%-15s %10" PRIdHSIZE " %10" PRIdHSIZE " %8s %8s %8s %10s\n", + (dir ? "<" : ">"), comment, H5Z_stat_table_g[i].stats[dir].total, + H5Z_stat_table_g[i].stats[dir].errors, timestrs.user, timestrs.system, + timestrs.elapsed, bandwidth); +next: + HDfree(timestrs.user); + HDfree(timestrs.system); + HDfree(timestrs.elapsed); + } /* end for */ + } /* end for */ + } /* end if */ +#endif /* H5Z_DEBUG */ + + /* Free the table of filters */ + if (H5Z_table_g) { + H5Z_table_g = (H5Z_class2_t *)H5MM_xfree(H5Z_table_g); + #ifdef H5Z_DEBUG - H5Z_stat_table_g = (H5Z_stats_t *)H5MM_xfree(H5Z_stat_table_g); + H5Z_stat_table_g = (H5Z_stats_t *)H5MM_xfree(H5Z_stat_table_g); #endif /* H5Z_DEBUG */ - H5Z_table_used_g = H5Z_table_alloc_g = 0; - H5_interface_initialize_g = 0; + H5Z_table_used_g = H5Z_table_alloc_g = 0; + + n++; } /* end if */ - return(0); -} /* end H5Z_term_interface() */ + FUNC_LEAVE_NOAPI(n) +} /* end H5Z_term_package() */ - /*------------------------------------------------------------------------- - * Function: H5Zregister - * - * Purpose: This function registers new filter. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, April 16, 1998 + * Function: H5Zregister * - * Modifications: - * Changed to pass in H5Z_class_t struct - * Quincey Koziol, April 5, 2003 + * Purpose: This function registers new filter. * + * Return: Non-negative on success/Negative on failure *------------------------------------------------------------------------- */ herr_t H5Zregister(const void *cls) { - const H5Z_class2_t *cls_real = (const H5Z_class2_t *) cls; /* "Real" class pointer */ - H5Z_class2_t cls_new; /* Translated class struct */ - herr_t ret_value=SUCCEED; /* Return value */ + const H5Z_class2_t *cls_real = (const H5Z_class2_t *)cls; /* "Real" class pointer */ + herr_t ret_value = SUCCEED; /* Return value */ +#ifndef H5_NO_DEPRECATED_SYMBOLS + H5Z_class2_t cls_new; /* Translated class struct */ +#endif FUNC_ENTER_API(FAIL) H5TRACE1("e", "*x", cls); /* Check args */ - if (cls_real==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter class") + if (cls_real == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter class") /* Check H5Z_class_t version number; this is where a function to convert * from an outdated version should be called. @@ -241,66 +231,60 @@ H5Zregister(const void *cls) * at least 256, there should be no overlap and the version of the struct * can be determined by the value of the first field. */ - if(cls_real->version != H5Z_CLASS_T_VERS) { + if (cls_real->version != H5Z_CLASS_T_VERS) { #ifndef H5_NO_DEPRECATED_SYMBOLS /* Assume it is an old "H5Z_class1_t" instead */ - const H5Z_class1_t *cls_old = (const H5Z_class1_t *) cls; + const H5Z_class1_t *cls_old = (const H5Z_class1_t *)cls; /* Translate to new H5Z_class2_t */ - cls_new.version = H5Z_CLASS_T_VERS; - cls_new.id = cls_old->id; + cls_new.version = H5Z_CLASS_T_VERS; + cls_new.id = cls_old->id; cls_new.encoder_present = 1; cls_new.decoder_present = 1; - cls_new.name = cls_old->name; - cls_new.can_apply = cls_old->can_apply; - cls_new.set_local = cls_old->set_local; - cls_new.filter = cls_old->filter; + cls_new.name = cls_old->name; + cls_new.can_apply = cls_old->can_apply; + cls_new.set_local = cls_old->set_local; + cls_new.filter = cls_old->filter; /* Set cls_real to point to the translated structure */ cls_real = &cls_new; -#else /* H5_NO_DEPRECATED_SYMBOLS */ +#else /* H5_NO_DEPRECATED_SYMBOLS */ /* Deprecated symbols not allowed, throw an error */ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5Z_class_t version number"); #endif /* H5_NO_DEPRECATED_SYMBOLS */ - } /* end if */ + } /* end if */ - if (cls_real->id<0 || cls_real->id>H5Z_FILTER_MAX) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number") - if (cls_real->id<H5Z_FILTER_RESERVED) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters") - if (cls_real->filter==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no filter function specified") + if (cls_real->id < 0 || cls_real->id > H5Z_FILTER_MAX) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number") + if (cls_real->id < H5Z_FILTER_RESERVED) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters") + if (cls_real->filter == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no filter function specified") /* Do it */ - if (H5Z_register (cls_real)<0) - HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter") + if (H5Z_register(cls_real) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter") done: FUNC_LEAVE_API(ret_value) } - /*------------------------------------------------------------------------- - * Function: H5Z_register - * - * Purpose: Same as the public version except this one allows filters - * to be set for predefined method numbers <H5Z_FILTER_RESERVED + * Function: H5Z_register * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, April 16, 1998 - * - * Modifications: + * 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 *------------------------------------------------------------------------- */ herr_t -H5Z_register (const H5Z_class2_t *cls) +H5Z_register(const H5Z_class2_t *cls) { - size_t i; - herr_t ret_value = SUCCEED; /* Return value */ + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -308,240 +292,467 @@ H5Z_register (const H5Z_class2_t *cls) HDassert(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) + 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_class2_t *table = (H5Z_class2_t *)H5MM_realloc(H5Z_table_g, n * sizeof(H5Z_class2_t)); + 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_class2_t *table = (H5Z_class2_t *)H5MM_realloc(H5Z_table_g, n * sizeof(H5Z_class2_t)); #ifdef H5Z_DEBUG - H5Z_stats_t *stat_table = (H5Z_stats_t *)H5MM_realloc(H5Z_stat_table_g, n * sizeof(H5Z_stats_t)); + H5Z_stats_t *stat_table = (H5Z_stats_t *)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; + 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; + 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 */ + H5Z_table_alloc_g = n; + } /* end if */ - /* Initialize */ - i = H5Z_table_used_g++; - HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t)); + /* Initialize */ + i = H5Z_table_used_g++; + H5MM_memcpy(H5Z_table_g + i, cls, sizeof(H5Z_class2_t)); #ifdef H5Z_DEBUG - HDmemset(H5Z_stat_table_g+i, 0, sizeof(H5Z_stats_t)); + HDmemset(H5Z_stat_table_g + i, 0, sizeof(H5Z_stats_t)); #endif /* H5Z_DEBUG */ - } /* end if */ + } /* end if */ /* Filter already registered */ else { - /* Replace old contents */ - HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t)); + /* Replace old contents */ + H5MM_memcpy(H5Z_table_g + i, cls, sizeof(H5Z_class2_t)); } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) } - /*------------------------------------------------------------------------- - * Function: H5Zunregister + * Function: H5Zunregister * - * Purpose: This function unregisters a filter. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Thursday, November 14, 2002 - * - * Modifications: + * Purpose: This function unregisters a filter. * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ herr_t H5Zunregister(H5Z_filter_t id) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(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") + 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") + 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 + * Function: H5Z__unregister * - * Purpose: Same as the public version except this one allows filters - * to be unset for predefined method numbers <H5Z_FILTER_RESERVED + * 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: + * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ herr_t -H5Z_unregister (H5Z_filter_t id) +H5Z__unregister(H5Z_filter_t filter_id) { - size_t i; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t filter_index; /* Local index variable for filter */ + H5Z_object_t object; /* Object to pass to callbacks */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_PACKAGE - assert (id>=0 && id<=H5Z_FILTER_MAX); + HDassert(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") + /* Initialize the structure object for iteration */ + object.filter_id = filter_id; + object.found = FALSE; +#ifdef H5_HAVE_PARALLEL + object.sanity_checked = FALSE; +#endif /* H5_HAVE_PARALLEL */ + + /* Iterate through all opened datasets, returns a failure if any of them uses the filter */ + if (H5I_iterate(H5I_DATASET, H5Z__check_unregister_dset_cb, &object, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + + if (object.found) + HGOTO_ERROR(H5E_PLINE, H5E_CANTRELEASE, FAIL, + "can't unregister filter because a dataset is still using it") + + /* Iterate through all opened groups, returns a failure if any of them uses the filter */ + if (H5I_iterate(H5I_GROUP, H5Z__check_unregister_group_cb, &object, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + + if (object.found) + HGOTO_ERROR(H5E_PLINE, H5E_CANTRELEASE, FAIL, + "can't unregister filter because a group is still using it") + + /* Iterate through all opened files and flush them */ + if (H5I_iterate(H5I_FILE, H5Z__flush_file_cb, &object, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed") + /* Remove filter from table */ /* Don't worry about shrinking table size (for now) */ - HDmemmove(&H5Z_table_g[i],&H5Z_table_g[i+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-i)); + 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: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5Z_unregister() */ +} /* end H5Z__unregister() */ + +/*------------------------------------------------------------------------- + * Function: H5Z__check_unregister + * + * Purpose: Check if an object uses the filter to be unregistered. + * + * Return: TRUE if the object uses the filter + * FALSE if not + * NEGATIVE on error + * + *------------------------------------------------------------------------- + */ +static htri_t +H5Z__check_unregister(hid_t ocpl_id, H5Z_filter_t filter_id) +{ + H5P_genplist_t *plist; /* Property list */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Get the plist structure of object creation */ + if (NULL == (plist = H5P_object_verify(ocpl_id, H5P_OBJECT_CREATE))) + HGOTO_ERROR(H5E_PLINE, H5E_BADID, FAIL, "can't find object for ID") + + /* Check if the object creation property list uses the filter */ + if ((ret_value = H5P_filter_in_pline(plist, filter_id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't check filter in pipeline") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z__check_unregister() */ + +/*------------------------------------------------------------------------- + * Function: H5Z__check_unregister_group_cb + * + * Purpose: The callback function for H5Z__unregister. It iterates + * through all opened objects. If the object is a dataset + * or a group and it uses the filter to be unregistered, the + * function returns TRUE. + * + * Return: TRUE if the object uses the filter + * FALSE if not + * NEGATIVE on error + * + *------------------------------------------------------------------------- + */ +static int +H5Z__check_unregister_group_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key) +{ + hid_t ocpl_id = -1; + H5Z_object_t *object = (H5Z_object_t *)key; + htri_t filter_in_pline = FALSE; + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_PACKAGE + + HDassert(obj_ptr); + + /* Get the group creation property */ + if ((ocpl_id = H5G_get_create_plist((H5G_t *)obj_ptr)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get group creation property list") + + /* Check if the filter is in the group creation property list */ + if ((filter_in_pline = H5Z__check_unregister(ocpl_id, object->filter_id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't check filter in pipeline") + + /* H5I_iterate expects TRUE to stop the loop over objects. Stop the loop and + * let H5Z__unregister return failure. + */ + if (filter_in_pline) { + object->found = TRUE; + ret_value = TRUE; + } + +done: + if (ocpl_id > 0) + if (H5I_dec_app_ref(ocpl_id) < 0) + HDONE_ERROR(H5E_PLINE, H5E_CANTDEC, FAIL, "can't release plist") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z__check_unregister_group_cb() */ - /*------------------------------------------------------------------------- - * Function: H5Zfilter_avail + * Function: H5Z__check_unregister_dset_cb * - * Purpose: Check if a filter is available + * Purpose: The callback function for H5Z__unregister. It iterates + * through all opened objects. If the object is a dataset + * or a group and it uses the filter to be unregistered, the + * function returns TRUE. * - * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * Return: TRUE if the object uses the filter + * FALSE if not + * NEGATIVE on error * - * Programmer: Quincey Koziol - * Thursday, November 14, 2002 + *------------------------------------------------------------------------- + */ +static int +H5Z__check_unregister_dset_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key) +{ + hid_t ocpl_id = -1; + H5Z_object_t *object = (H5Z_object_t *)key; + htri_t filter_in_pline = FALSE; + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_PACKAGE + + HDassert(obj_ptr); + + /* Get the dataset creation property */ + if ((ocpl_id = H5D_get_create_plist((H5D_t *)obj_ptr)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get dataset creation property list") + + /* Check if the filter is in the dataset creation property list */ + if ((filter_in_pline = H5Z__check_unregister(ocpl_id, object->filter_id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't check filter in pipeline") + + /* H5I_iterate expects TRUE to stop the loop over objects. Stop the loop and + * let H5Z__unregister return failure. + */ + if (filter_in_pline) { + object->found = TRUE; + ret_value = TRUE; + } + +done: + if (ocpl_id > 0) + if (H5I_dec_app_ref(ocpl_id) < 0) + HDONE_ERROR(H5E_PLINE, H5E_CANTDEC, FAIL, "can't release plist") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z__check_unregister_dset_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5Z__flush_file_cb * - * Modifications: + * Purpose: The callback function for H5Z__unregister. It iterates + * through all opened files and flush them. * + * Return: NON-NEGATIVE if finishes flushing and moves on + * NEGATIVE if there is an error + *------------------------------------------------------------------------- + */ +static int +H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void H5_ATTR_PARALLEL_USED *key) +{ + H5F_t *f = (H5F_t *)obj_ptr; /* File object for operations */ +#ifdef H5_HAVE_PARALLEL + H5Z_object_t *object = (H5Z_object_t *)key; +#endif /* H5_HAVE_PARALLEL */ + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity checks */ + HDassert(obj_ptr); + HDassert(key); + + /* Do a global flush if the file is opened for write */ + if (H5F_ACC_RDWR & H5F_INTENT(f)) { + +#ifdef H5_HAVE_PARALLEL + /* Check if MPIO driver is used */ + if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) { + /* Sanity check for collectively calling H5Zunregister, if requested */ + /* (Sanity check assumes that a barrier on one file's comm + * is sufficient (i.e. that there aren't different comms for + * different files). -QAK, 2018/02/14) + */ + if (H5_coll_api_sanity_check_g && !object->sanity_checked) { + MPI_Comm mpi_comm; /* File's communicator */ + + /* Retrieve the file communicator */ + if (MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(f))) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get MPI communicator") + + /* Issue the barrier */ + if (mpi_comm != MPI_COMM_NULL) + MPI_Barrier(mpi_comm); + + /* Set the "sanity checked" flag */ + object->sanity_checked = TRUE; + } /* end if */ + } /* end if */ +#endif /* H5_HAVE_PARALLEL */ + + /* Call the flush routine for mounted file hierarchies */ + if (H5F_flush_mounts((H5F_t *)obj_ptr) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z__flush_file_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5Zfilter_avail + * + * Purpose: Check if a filter is available + * + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure *------------------------------------------------------------------------- */ htri_t H5Zfilter_avail(H5Z_filter_t id) { - size_t i; /* Local index variable */ - htri_t ret_value=FALSE; /* Return value */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_API(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") + 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 */ + if ((ret_value = H5Z_filter_avail(id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "unable to check the availability of the filter") done: FUNC_LEAVE_API(ret_value) } /* end H5Zfilter_avail() */ - /*------------------------------------------------------------------------- - * Function: H5Z_prelude_callback + * Function: H5Z_filter_avail * - * Purpose: Makes a dataset creation "prelude" callback for the "can_apply" - * or "set_local" routines. + * Purpose: Private function to check if a filter is available * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + *------------------------------------------------------------------------- + */ +htri_t +H5Z_filter_avail(H5Z_filter_t id) +{ + H5PL_key_t key; /* Key for finding a plugin */ + const H5Z_class2_t *filter_info; /* Filter information */ + size_t i; /* Local index variable */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Is the filter already registered? */ + for (i = 0; i < H5Z_table_used_g; i++) + if (H5Z_table_g[i].id == id) + HGOTO_DONE(TRUE) + + key.id = (int)id; + if (NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, &key))) { + if (H5Z_register(filter_info) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register loaded filter") + HGOTO_DONE(TRUE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_filter_avail() */ + +/*------------------------------------------------------------------------- + * Function: H5Z__prelude_callback * - * Programmer: Quincey Koziol - * Friday, April 4, 2003 + * Purpose: Makes a dataset creation "prelude" callback for the "can_apply" + * or "set_local" routines. * - * 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 + * Return: Non-negative on success/Negative on failure * + * 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 *------------------------------------------------------------------------- */ static herr_t -H5Z_prelude_callback(const H5O_pline_t *pline, hid_t dcpl_id, hid_t type_id, - hid_t space_id, H5Z_prelude_type_t prelude_type) +H5Z__prelude_callback(const H5O_pline_t *pline, hid_t dcpl_id, hid_t type_id, hid_t space_id, + H5Z_prelude_type_t prelude_type) { - H5Z_class2_t *fclass; /* Individual filter information */ - size_t u; /* Local index variable */ - htri_t ret_value = TRUE; /* Return value */ + H5Z_class2_t *fclass; /* Individual filter information */ + size_t u; /* Local index variable */ + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE HDassert(pline->nused > 0); /* Iterate over filters */ - for(u = 0; u < pline->nused; u++) { + for (u = 0; u < pline->nused; u++) { /* Get filter information */ - if(NULL == (fclass = H5Z_find(pline->filter[u].id))) { + if (NULL == (fclass = H5Z_find(pline->filter[u].id))) { /* Ignore errors from optional filters */ - if(pline->filter[u].flags & H5Z_FLAG_OPTIONAL) + if (pline->filter[u].flags & H5Z_FLAG_OPTIONAL) H5E_clear_stack(NULL); else HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "required filter was not located") } /* end if */ else { /* Make correct callback */ - switch(prelude_type) { + switch (prelude_type) { case H5Z_PRELUDE_CAN_APPLY: /* Check if filter is configured to be able to encode */ - if(!fclass->encoder_present) - HGOTO_ERROR(H5E_PLINE, H5E_NOENCODER, FAIL, "Filter present but encoding is disabled."); - + if (!fclass->encoder_present) + HGOTO_ERROR(H5E_PLINE, H5E_NOENCODER, FAIL, + "Filter present but encoding is disabled."); /* Check if there is a "can apply" callback */ - if(fclass->can_apply) { + if (fclass->can_apply) { /* Make callback to filter's "can apply" function */ htri_t status = (fclass->can_apply)(dcpl_id, type_id, space_id); /* Indicate error during filter callback */ - if(status < 0) + if (status < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "error during user callback") - /* Indicate filter can't apply to this combination of parameters. + /* Indicate filter can't apply to this combination of parameters. * If the filter is NOT optional, returns failure. */ - if(status == FALSE && !(pline->filter[u].flags & H5Z_FLAG_OPTIONAL)) + if (status == FALSE && !(pline->filter[u].flags & H5Z_FLAG_OPTIONAL)) HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "filter parameters not appropriate") } /* end if */ break; case H5Z_PRELUDE_SET_LOCAL: /* Check if there is a "set local" callback */ - if(fclass->set_local) { + if (fclass->set_local) { /* Make callback to filter's "set local" function */ - if((fclass->set_local)(dcpl_id, type_id, space_id) < 0) + if ((fclass->set_local)(dcpl_id, type_id, space_id) < 0) /* Indicate error during filter callback */ HGOTO_ERROR(H5E_PLINE, H5E_SETLOCAL, FAIL, "error during user callback") } /* end if */ @@ -550,257 +761,297 @@ H5Z_prelude_callback(const H5O_pline_t *pline, hid_t dcpl_id, hid_t type_id, default: HDassert("invalid prelude type" && 0); } /* end switch */ - } /* end else */ - } /* end for */ + } /* end else */ + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5Z_prelude_callback() */ +} /* end H5Z__prelude_callback() */ - /*------------------------------------------------------------------------- - * Function: H5Z_prepare_prelude_callback_dcpl - * - * Purpose: Prepares to make a dataset creation "prelude" callback - * for the "can_apply" or "set_local" routines. + * Function: H5Z__prepare_prelude_callback_dcpl * - * Return: Non-negative on success/Negative on failure + * Purpose: Prepares to make a dataset creation "prelude" callback + * for the "can_apply" or "set_local" routines. * - * 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 + * Return: Non-negative on success/Negative on failure * + * 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 *------------------------------------------------------------------------- */ static herr_t -H5Z_prepare_prelude_callback_dcpl(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_type) +H5Z__prepare_prelude_callback_dcpl(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_type) { - hid_t space_id = -1; /* ID for dataspace describing chunk */ - herr_t ret_value = SUCCEED; /* Return value */ + hid_t space_id = -1; /* ID for dataspace describing chunk */ + H5O_layout_t *dcpl_layout = NULL; /* Dataset's layout information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id)); HDassert(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 */ - H5O_layout_t dcpl_layout; /* Dataset's layout information */ + if (dcpl_id != H5P_DATASET_CREATE_DEFAULT) { + H5P_genplist_t *dc_plist; /* Dataset creation property list object */ + + /* Get memory for the layout */ + if (NULL == (dcpl_layout = (H5O_layout_t *)H5MM_calloc(sizeof(H5O_layout_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate dcpl layout buffer") /* Get dataset creation property list object */ - if(NULL == (dc_plist = (H5P_genplist_t *)H5I_object(dcpl_id))) + if (NULL == (dc_plist = (H5P_genplist_t *)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) + /* Peek at the layout information */ + if (H5P_peek(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.type) { - H5O_pline_t dcpl_pline; /* Object's I/O pipeline information */ + if (H5D_CHUNKED == dcpl_layout->type) { + H5O_pline_t dcpl_pline; /* Object's I/O pipeline information */ /* Get I/O pipeline information */ - if(H5P_get(dc_plist, H5O_CRT_PIPELINE_NAME, &dcpl_pline) < 0) + if (H5P_peek(dc_plist, H5O_CRT_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) { - hsize_t chunk_dims[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */ - H5S_t *space; /* Dataspace describing chunk */ - size_t u; /* Local index variable */ - - /* Create a data space for a chunk & set the extent */ - for(u = 0; u < dcpl_layout.u.chunk.ndims; u++) - chunk_dims[u] = dcpl_layout.u.chunk.dim[u]; - if(NULL == (space = H5S_create_simple(dcpl_layout.u.chunk.ndims, chunk_dims, NULL))) + if (dcpl_pline.nused > 0) { + hsize_t chunk_dims[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */ + H5S_t *space; /* Dataspace describing chunk */ + size_t u; /* Local index variable */ + + /* Create a dataspace for a chunk & set the extent */ + for (u = 0; u < dcpl_layout->u.chunk.ndims; u++) + chunk_dims[u] = dcpl_layout->u.chunk.dim[u]; + if (NULL == (space = H5S_create_simple(dcpl_layout->u.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, FALSE)) < 0) { + if ((space_id = H5I_register(H5I_DATASPACE, space, FALSE)) < 0) { (void)H5S_close(space); - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") - } /* end if */ + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + } /* Make the callbacks */ - if(H5Z_prelude_callback(&dcpl_pline, dcpl_id, type_id, space_id, prelude_type) < 0) + if (H5Z__prelude_callback(&dcpl_pline, dcpl_id, type_id, space_id, prelude_type) < 0) HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "unable to apply filter") - } /* end if */ - } /* end if */ - } /* end if */ + } + } + } done: - if(space_id > 0 && H5I_dec_ref(space_id) < 0) + if (space_id > 0 && H5I_dec_ref(space_id) < 0) HDONE_ERROR(H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace") + if (dcpl_layout) + dcpl_layout = (H5O_layout_t *)H5MM_xfree(dcpl_layout); + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5Z_prepare_prelude_callback_dcpl() */ +} /* end H5Z__prepare_prelude_callback_dcpl() */ - /*------------------------------------------------------------------------- - * 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 + * Function: H5Z_can_apply * - * Programmer: Quincey Koziol - * Thursday, April 3, 2003 + * 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. * - * 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 + * Return: Non-negative on success + * Negative on failure * + * 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 *------------------------------------------------------------------------- */ herr_t H5Z_can_apply(hid_t dcpl_id, hid_t type_id) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Make "can apply" callbacks for filters in pipeline */ - if(H5Z_prepare_prelude_callback_dcpl(dcpl_id, type_id, H5Z_PRELUDE_CAN_APPLY) < 0) + if (H5Z__prepare_prelude_callback_dcpl(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). + * Function: H5Z_set_local * - * Return: Non-negative on success/Negative on failure + * 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). * - * 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 + * Return: Non-negative on success + * Negative on failure * + * 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 *------------------------------------------------------------------------- */ herr_t H5Z_set_local(hid_t dcpl_id, hid_t type_id) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Make "set local" callbacks for filters in pipeline */ - if(H5Z_prepare_prelude_callback_dcpl(dcpl_id, type_id, H5Z_PRELUDE_SET_LOCAL) < 0) + if (H5Z__prepare_prelude_callback_dcpl(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_can_apply_direct - * - * Purpose: Checks if all the filters defined in the pipeline can be - * applied to an opaque byte stream (currently only a group). - * The pipeline is assumed to have at least one filter. - * - * Return: Non-negative on success/Negative on failure + * Function: H5Z_can_apply_direct * - * Programmer: Neil Fortner - * Tuesday, September 22, 2009 + * Purpose: Checks if all the filters defined in the pipeline can be + * applied to an opaque byte stream (currently only a group). + * The pipeline is assumed to have at least one filter. * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ herr_t H5Z_can_apply_direct(const H5O_pline_t *pline) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) HDassert(pline->nused > 0); /* Make "can apply" callbacks for filters in pipeline */ - if(H5Z_prelude_callback(pline, -1, -1, -1, H5Z_PRELUDE_CAN_APPLY) < 0) + if (H5Z__prelude_callback(pline, (hid_t)-1, (hid_t)-1, (hid_t)-1, 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_direct() */ - /*------------------------------------------------------------------------- - * Function: H5Z_set_local_direct - * - * Purpose: Makes callbacks to modify local settings for filters on a - * new opaque object. The pipeline is assumed to have at - * least one filter. - * - * Return: Non-negative on success/Negative on failure + * Function: H5Z_set_local_direct * - * Programmer: Neil Fortner - * Tuesday, September 22, 2009 + * Purpose: Makes callbacks to modify local settings for filters on a + * new opaque object. The pipeline is assumed to have at + * least one filter. * - * Notes: - * This callback will almost certainly not do anything - * useful, other than to make certain that the filter will - * accept opque data. + * Return: Non-negative on success + * Negative on failure * + * Notes: This callback will almost certainly not do anything + * useful, other than to make certain that the filter will + * accept opaque data. *------------------------------------------------------------------------- */ herr_t H5Z_set_local_direct(const H5O_pline_t *pline) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) HDassert(pline->nused > 0); /* Make "set local" callbacks for filters in pipeline */ - if(H5Z_prelude_callback(pline, -1, -1, -1, H5Z_PRELUDE_SET_LOCAL) < 0) + if (H5Z__prelude_callback(pline, (hid_t)-1, (hid_t)-1, (hid_t)-1, 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_direct() */ - /*------------------------------------------------------------------------- - * Function: H5Z_modify + * Function: H5Z_ignore_filters * - * Purpose: Modify filter parameters for specified pipeline. + * Purpose: Determine whether filters can be ignored. * - * Return: Non-negative on success/Negative on failure + * Description: + * When the filters are optional (i.e., H5Z_FLAG_OPTIONAL is provided,) + * if any of the following conditions is met, the filters will be ignored: + * - dataspace is either H5S_NULL or H5S_SCALAR + * - datatype is variable-length (string or non-string) + * However, if any of these conditions exists and a filter is not + * optional, the function will produce an error. * - * Programmer: Quincey Koziol - * Friday, April 5, 2003 + * Return: Non-negative(TRUE/FALSE) on success + * Negative on failure * - * Modifications: + *------------------------------------------------------------------------- + */ +htri_t +H5Z_ignore_filters(hid_t dcpl_id, const H5T_t *type, const H5S_t *space) +{ + H5P_genplist_t *dc_plist; /* Dataset creation property list object */ + H5O_pline_t pline; /* Object's I/O pipeline information */ + H5S_class_t space_class; /* To check class of space */ + H5T_class_t type_class; /* To check if type is VL */ + hbool_t bad_for_filters = FALSE; /* Suitable to have filters */ + htri_t ret_value = FALSE; /* TRUE for ignoring filters */ + + FUNC_ENTER_NOAPI(FAIL) + + if (NULL == (dc_plist = (H5P_genplist_t *)H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list") + + /* Get pipeline information */ + if (H5P_peek(dc_plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't retrieve pipeline filter") + + /* Get datatype and dataspace classes for quick access */ + space_class = H5S_GET_EXTENT_TYPE(space); + type_class = H5T_get_class(type, FALSE); + + /* These conditions are not suitable for filters */ + bad_for_filters = (H5S_NULL == space_class || H5S_SCALAR == space_class || H5T_VLEN == type_class || + (H5T_STRING == type_class && TRUE == H5T_is_variable_str(type))); + + /* When these conditions occur, if there are required filters in pline, + then report a failure, otherwise, set flag that they can be ignored */ + if (bad_for_filters) { + size_t ii; + if (pline.nused > 0) { + for (ii = 0; ii < pline.nused; ii++) { + if (!(pline.filter[ii].flags & H5Z_FLAG_OPTIONAL)) + HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "not suitable for filters") + } + + /* All filters are optional, we can ignore them */ + ret_value = TRUE; + } + } /* bad for filters */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_ignore_filters() */ + +/*------------------------------------------------------------------------- + * Function: H5Z_modify + * + * Purpose: Modify filter parameters for specified pipeline. * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ 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*/]) +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 */ - herr_t ret_value = SUCCEED; /* Return value */ + size_t idx; /* Index of filter in pipeline */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -810,67 +1061,61 @@ H5Z_modify(const H5O_pline_t *pline, H5Z_filter_t filter, unsigned flags, HDassert(0 == cd_nelmts || cd_values); /* Locate the filter in the pipeline */ - for(idx = 0; idx < pline->nused; idx++) - if(pline->filter[idx].id == filter) + 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") + 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].flags = flags; pline->filter[idx].cd_nelmts = cd_nelmts; /* Free any existing parameters */ - if(pline->filter[idx].cd_values != NULL && pline->filter[idx].cd_values != pline->filter[idx]._cd_values) - H5MM_xfree(pline->filter[idx].cd_values); + if (pline->filter[idx].cd_values != NULL && pline->filter[idx].cd_values != pline->filter[idx]._cd_values) + H5MM_xfree(pline->filter[idx].cd_values); /* Set parameters */ - if(cd_nelmts > 0) { - size_t i; /* Local index variable */ + if (cd_nelmts > 0) { + size_t i; /* Local index variable */ /* Allocate memory or point at internal buffer */ - if(cd_nelmts > H5Z_COMMON_CD_VALUES) { + if (cd_nelmts > H5Z_COMMON_CD_VALUES) { pline->filter[idx].cd_values = (unsigned *)H5MM_malloc(cd_nelmts * sizeof(unsigned)); - if(NULL == pline->filter[idx].cd_values) + if (NULL == pline->filter[idx].cd_values) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for filter parameters") } /* end if */ else pline->filter[idx].cd_values = pline->filter[idx]._cd_values; /* Copy client data values */ - for(i = 0; i < cd_nelmts; i++) - pline->filter[idx].cd_values[i] = cd_values[i]; + 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; + 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 + * Function: H5Z_append * - * Programmer: Robb Matzke - * Tuesday, August 4, 1998 - * - * Modifications: + * Purpose: Append another filter to the specified pipeline. * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ 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*/]) +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; - herr_t ret_value = SUCCEED; /* Return value */ + size_t idx; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -883,17 +1128,17 @@ H5Z_append(H5O_pline_t *pline, H5Z_filter_t filter, unsigned flags, * 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") + if (pline->nused >= H5Z_MAX_NFILTERS) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "too many filters in pipeline") /* Check for freshly allocated filter pipeline */ - if(pline->version == 0) + if (pline->version == 0) pline->version = H5O_PLINE_VERSION_1; /* Allocate additional space in the pipeline if it's full */ - if(pline->nused >= pline->nalloc) { - H5O_pline_t x; - size_t n; + if (pline->nused >= pline->nalloc) { + H5O_pline_t x; + size_t n; /* Each filter's data may be stored internally or may be * a separate block of memory. @@ -902,51 +1147,51 @@ H5Z_append(H5O_pline_t *pline, H5Z_filter_t filter, unsigned flags, * filter struct is reallocated. Set these pointers to ~NULL * so that we can reset them after reallocating the filters array. */ - for(n = 0; n < pline->nalloc; ++n) - if(pline->filter[n].cd_values == pline->filter[n]._cd_values) - pline->filter[n].cd_values = (unsigned *)((void *) ~((size_t)NULL)); + for (n = 0; n < pline->nalloc; ++n) + if (pline->filter[n].cd_values == pline->filter[n]._cd_values) + pline->filter[n].cd_values = (unsigned *)((void *)~((size_t)NULL)); - x.nalloc = MAX(H5Z_MAX_NFILTERS, 2 * pline->nalloc); - x.filter = (H5Z_filter_info_t *)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") + x.nalloc = MAX(H5Z_MAX_NFILTERS, 2 * pline->nalloc); + x.filter = (H5Z_filter_info_t *)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") /* Fix pointers in previous filters that need to point to their own * internal data. */ - for(n = 0; n < pline->nalloc; ++n) - if(x.filter[n].cd_values == (void *) ~((size_t) NULL)) + for (n = 0; n < pline->nalloc; ++n) + if (x.filter[n].cd_values == (void *)~((size_t)NULL)) x.filter[n].cd_values = x.filter[n]._cd_values; /* Point to newly allocated buffer */ - pline->nalloc = x.nalloc; - pline->filter = x.filter; + pline->nalloc = x.nalloc; + pline->filter = x.filter; } /* end if */ /* 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*/ + 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) { - size_t i; /* Local index variable */ + if (cd_nelmts > 0) { + size_t i; /* Local index variable */ /* Allocate memory or point at internal buffer */ - if(cd_nelmts > H5Z_COMMON_CD_VALUES) { + if (cd_nelmts > H5Z_COMMON_CD_VALUES) { pline->filter[idx].cd_values = (unsigned *)H5MM_malloc(cd_nelmts * sizeof(unsigned)); - if(NULL == pline->filter[idx].cd_values) + if (NULL == pline->filter[idx].cd_values) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for filter") } /* end if */ else pline->filter[idx].cd_values = pline->filter[idx]._cd_values; /* Copy client data values */ - for(i = 0; i < cd_nelmts; i++) - pline->filter[idx].cd_values[i] = cd_values[i]; + 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; + pline->filter[idx].cd_values = NULL; pline->nused++; @@ -954,220 +1199,250 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_append() */ - /*------------------------------------------------------------------------- - * 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 + * Function: H5Z__find_idx * - * Programmer: Quincey Koziol - * Friday, April 5, 2003 - * - * Modifications: + * 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 *------------------------------------------------------------------------- */ static int -H5Z_find_idx(H5Z_filter_t id) +H5Z__find_idx(H5Z_filter_t id) { - size_t i; /* Local index variable */ - int ret_value=FAIL; /* Return value */ + size_t i; /* Local index variable */ + int ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_PACKAGE_NOERR - for (i=0; i<H5Z_table_used_g; i++) - if (H5Z_table_g[i].id == id) - HGOTO_DONE((int)i) + 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() */ +} /* 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 + * Function: H5Z_find * - * Programmer: Robb Matzke - * Wednesday, August 5, 1998 - * - * Modifications: - * Use H5Z_find_idx now - * Quincey Koziol, April 5, 2003 + * 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 *------------------------------------------------------------------------- */ H5Z_class2_t * H5Z_find(H5Z_filter_t id) { - int idx; /* Filter index in global table */ - H5Z_class2_t *ret_value=NULL; /* Return value */ + int idx; /* Filter index in global table */ + H5Z_class2_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(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") + if ((idx = H5Z__find_idx(id)) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, NULL, "required filter %d is not registered", id) /* Set return value */ - ret_value=H5Z_table_g+idx; + 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: - * + * 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 *------------------------------------------------------------------------- */ 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*/) +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_class2_t *fclass=NULL; /* Filter class pointer */ + size_t idx; + size_t new_nbytes; + int fclass_idx; /* Index of filter class in global table */ + H5Z_class2_t *fclass = NULL; /* Filter class pointer */ #ifdef H5Z_DEBUG - H5Z_stats_t *fstats=NULL; /* Filter stats pointer */ - H5_timer_t timer; + H5Z_stats_t *fstats = NULL; /* Filter stats pointer */ + H5_timer_t timer; /* Timer for filter operations */ + H5_timevals_t times; /* Elapsed time for each operation */ #endif - unsigned failed = 0; - unsigned tmp_flags; - herr_t ret_value=SUCCEED; /* Return value */ + unsigned failed = 0; + unsigned tmp_flags; + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(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); + HDassert(0 == (flags & ~((unsigned)H5Z_FLAG_INVMASK))); + HDassert(filter_mask); + HDassert(nbytes && *nbytes > 0); + HDassert(buf_size && *buf_size > 0); + HDassert(buf && *buf); + HDassert(!pline || pline->nused < H5Z_MAX_NFILTERS); +#ifdef H5Z_DEBUG + H5_timer_init(&timer); +#endif 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) { - /* Print out the filter name to give more info. But the name is optional for - * the filter */ - if(pline->filter[idx].name) - HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter '%s' is not registered", - pline->filter[idx].name) + for (i = pline->nused; i > 0; --i) { + idx = i - 1; + if (*filter_mask & ((unsigned)1 << idx)) { + failed |= (unsigned)1 << idx; + continue; /* filter excluded */ + } + + /* If the filter isn't registered and the application doesn't + * indicate no plugin through HDF5_PRELOAD_PLUG (using the symbol "::"), + * try to load it dynamically and register it. Otherwise, return failure + */ + if ((fclass_idx = H5Z__find_idx(pline->filter[idx].id)) < 0) { + H5PL_key_t key; + const H5Z_class2_t *filter_info; + hbool_t issue_error = FALSE; + + /* Try loading the filter */ + key.id = (int)(pline->filter[idx].id); + if (NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, &key))) { + /* Register the filter we loaded */ + if (H5Z_register(filter_info) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter") + + /* Search in the table of registered filters again to find the dynamic filter just loaded + * and registered */ + if ((fclass_idx = H5Z__find_idx(pline->filter[idx].id)) < 0) + issue_error = TRUE; + } else - HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter (name unavailable) is not registered") + issue_error = TRUE; + + /* Check for error */ + if (issue_error) { + /* Print out the filter name to give more info. But the name is optional for + * the filter */ + if (pline->filter[idx].name) + HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter '%s' is not registered", + pline->filter[idx].name) + else + HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, + "required filter (name unavailable) is not registered") + } + } /* end if */ + + fclass = &H5Z_table_g[fclass_idx]; - } - fclass=&H5Z_table_g[fclass_idx]; #ifdef H5Z_DEBUG - fstats=&H5Z_stat_table_g[fclass_idx]; - H5_timer_begin(&timer); + fstats = &H5Z_stat_table_g[fclass_idx]; + H5_timer_start(&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); + + 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; + H5_timer_stop(&timer); + H5_timer_get_times(timer, ×); + fstats->stats[1].times.elapsed += times.elapsed; + fstats->stats[1].times.system += times.system; + fstats->stats[1].times.user += times.user; + + 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") + 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_stack(NULL); - } else { + } + 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 */ } - } - } 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) { + 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; + 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_stack(NULL); - continue; /*filter excluded*/ - } - fclass=&H5Z_table_g[fclass_idx]; + continue; /* filter excluded */ + } /* end if */ + + fclass = &H5Z_table_g[fclass_idx]; + #ifdef H5Z_DEBUG - fstats=&H5Z_stat_table_g[fclass_idx]; - H5_timer_begin(&timer); + fstats = &H5Z_stat_table_g[fclass_idx]; + H5_timer_start(&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); + + 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; + H5_timer_stop(&timer); + H5_timer_get_times(timer, ×); + fstats->stats[0].times.elapsed += times.elapsed; + fstats->stats[0].times.system += times.system; + fstats->stats[0].times.user += times.user; + + 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) + + 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_stack(NULL); - } else { - *nbytes = new_nbytes; } - } + else + *nbytes = new_nbytes; + } /* end for */ } *filter_mask = failed; @@ -1176,85 +1451,106 @@ 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 + * Function: H5Z_filter_info * - * Modifications: + * Purpose: Get pointer to filter info for pipeline * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ 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 */ + size_t idx; /* Index of filter in pipeline */ + H5Z_filter_info_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) - assert(pline); - assert(filter>=0 && filter<=H5Z_FILTER_MAX); + HDassert(pline); + HDassert(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) + 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") + if (idx >= pline->nused) + HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, NULL, "filter not in pipeline") /* Set return value */ - ret_value=&pline->filter[idx]; + ret_value = &pline->filter[idx]; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_filter_info() */ - /*------------------------------------------------------------------------- - * Function: H5Z_all_filters_avail + * Function: H5Z_filter_in_pline * - * Purpose: Verify that all the filters in a pipeline are currently - * available (i.e. registered) + * Purpose: Check whether a filter is in the filter pipeline using the + * filter ID. This function is very similar to H5Z_filter_info * - * Return: Non-negative (TRUE/FALSE) on success/Negative on failure - * - * Programmer: Quincey Koziol - * Tuesday, April 8, 2003 + * Return: TRUE - found filter + * FALSE - not found + * FAIL - error + *------------------------------------------------------------------------- + */ +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_NOERR + + HDassert(pline); + HDassert(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; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_filter_in_pline() */ + +/*------------------------------------------------------------------------- + * Function: H5Z_all_filters_avail * - * Modifications: + * 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 *------------------------------------------------------------------------- */ 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 */ + size_t i, j; /* Local index variable */ + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOERR /* Check args */ - assert(pline); + HDassert(pline); /* Iterate through all the filters in pipeline */ - for(i=0; i<pline->nused; i++) { - + 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) + 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) + if (j == H5Z_table_used_g) HGOTO_DONE(FALSE) } /* end for */ @@ -1262,21 +1558,14 @@ 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: + * Purpose: Delete filter FILTER from pipeline PLINE; + * deletes all filters if FILTER is H5Z_FILTER_NONE * + * Return: Non-negative on success + * Negative on failure *------------------------------------------------------------------------- */ herr_t @@ -1291,51 +1580,51 @@ H5Z_delete(H5O_pline_t *pline, H5Z_filter_t filter) HDassert(filter >= 0 && filter <= H5Z_FILTER_MAX); /* if the pipeline has no filters, just return */ - if(pline->nused==0) + if (pline->nused == 0) HGOTO_DONE(SUCCEED) /* Delete all filters */ - if(H5Z_FILTER_ALL == filter) { - if(H5O_msg_reset(H5O_PLINE_ID, pline) < 0) + if (H5Z_FILTER_ALL == filter) { + if (H5O_msg_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 */ - hbool_t found = FALSE; /* Indicate filter was found in pipeline */ + size_t idx; /* Index of filter in pipeline */ + hbool_t found = FALSE; /* 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) { + for (idx = 0; idx < pline->nused; idx++) + if (pline->filter[idx].id == filter) { found = TRUE; break; - } /* end if */ + } /* filter was not found in the pipeline */ - if(!found) + if (!found) HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "filter not in pipeline") /* Free information for deleted filter */ - if(pline->filter[idx].name && pline->filter[idx].name != pline->filter[idx]._name) + if (pline->filter[idx].name && pline->filter[idx].name != pline->filter[idx]._name) HDassert((HDstrlen(pline->filter[idx].name) + 1) > H5Z_COMMON_NAME_LEN); - if(pline->filter[idx].name != pline->filter[idx]._name) + if (pline->filter[idx].name != pline->filter[idx]._name) pline->filter[idx].name = (char *)H5MM_xfree(pline->filter[idx].name); - if(pline->filter[idx].cd_values && pline->filter[idx].cd_values != pline->filter[idx]._cd_values) + if (pline->filter[idx].cd_values && pline->filter[idx].cd_values != pline->filter[idx]._cd_values) HDassert(pline->filter[idx].cd_nelmts > H5Z_COMMON_CD_VALUES); - if(pline->filter[idx].cd_values != pline->filter[idx]._cd_values) + if (pline->filter[idx].cd_values != pline->filter[idx]._cd_values) pline->filter[idx].cd_values = (unsigned *)H5MM_xfree(pline->filter[idx].cd_values); /* Remove filter from pipeline array */ - if((idx + 1) < pline->nused) { + if ((idx + 1) < pline->nused) { /* Copy filters down & fix up any client data value arrays using internal storage */ - for(; (idx + 1) < pline->nused; idx++) { + for (; (idx + 1) < pline->nused; idx++) { pline->filter[idx] = pline->filter[idx + 1]; - if(pline->filter[idx].name && (HDstrlen(pline->filter[idx].name) + 1) <= H5Z_COMMON_NAME_LEN) + if (pline->filter[idx].name && (HDstrlen(pline->filter[idx].name) + 1) <= H5Z_COMMON_NAME_LEN) pline->filter[idx].name = pline->filter[idx]._name; - if(pline->filter[idx].cd_nelmts <= H5Z_COMMON_CD_VALUES) + if (pline->filter[idx].cd_nelmts <= H5Z_COMMON_CD_VALUES) pline->filter[idx].cd_values = pline->filter[idx]._cd_values; - } /* end for */ - } /* end if */ + } + } /* Decrement number of used filters */ pline->nused--; @@ -1348,44 +1637,64 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5Z_delete() */ - /*------------------------------------------------------------------------- * Function: H5Zget_filter_info * - * Purpose: Gets information about a pipeline data filter and stores it - * in filter_config_flags. + * Purpose: Gets information about a pipeline data filter and stores it + * in filter_config_flags. * - * Return: zero on success / negative on failure + * Return: zero on success + * negative on failure + *------------------------------------------------------------------------- + */ +herr_t +H5Zget_filter_info(H5Z_filter_t filter, unsigned *filter_config_flags /*out*/) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "Zfx", filter, filter_config_flags); + + /* Get the filter info */ + if (H5Z_get_filter_info(filter, filter_config_flags) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "Filter info not retrieved") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Zget_filter_info() */ + +/*------------------------------------------------------------------------- + * Function: H5Z_get_filter_info * - * Programmer: James Laird and Nat Furrer - * Monday, June 7, 2004 + * Purpose: Gets information about a pipeline data filter and stores it + * in filter_config_flags. * + * Return: zero on success + * negative on failure *------------------------------------------------------------------------- */ herr_t -H5Zget_filter_info(H5Z_filter_t filter, unsigned int *filter_config_flags) +H5Z_get_filter_info(H5Z_filter_t filter, unsigned int *filter_config_flags) { H5Z_class2_t *fclass; - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; - FUNC_ENTER_API(FAIL) - H5TRACE2("e", "Zf*Iu", filter, filter_config_flags); + FUNC_ENTER_NOAPI(FAIL) /* Look up the filter class info */ - if(NULL == (fclass = H5Z_find(filter))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Filter not defined") + if (NULL == (fclass = H5Z_find(filter))) + HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, FAIL, "Filter not defined") /* Set the filter config flags for the application */ - if(filter_config_flags != NULL) { + if (filter_config_flags != NULL) { *filter_config_flags = 0; - if(fclass->encoder_present) + if (fclass->encoder_present) *filter_config_flags |= H5Z_FILTER_CONFIG_ENCODE_ENABLED; - if(fclass->decoder_present) + if (fclass->decoder_present) *filter_config_flags |= H5Z_FILTER_CONFIG_DECODE_ENABLED; } /* end if */ done: - FUNC_LEAVE_API(ret_value) -} /* end H5Zget_filter_info() */ - + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_get_filter_info() */ |
