diff options
-rw-r--r-- | MANIFEST | 10 | ||||
-rw-r--r-- | Makefile.in | 11 | ||||
-rwxr-xr-x | configure | 59 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | src/H5.c | 1 | ||||
-rw-r--r-- | src/H5Edefin.h | 3 | ||||
-rw-r--r-- | src/H5Einit.h | 7 | ||||
-rw-r--r-- | src/H5Epubgen.h | 4 | ||||
-rw-r--r-- | src/H5Eterm.h | 3 | ||||
-rw-r--r-- | src/H5PL.c | 401 | ||||
-rw-r--r-- | src/H5PLpkg.h | 59 | ||||
-rw-r--r-- | src/H5PLprivate.h | 59 | ||||
-rw-r--r-- | src/H5PLpublic.h | 45 | ||||
-rw-r--r-- | src/H5Pocpl.c | 91 | ||||
-rw-r--r-- | src/H5Pprivate.h | 2 | ||||
-rw-r--r-- | src/H5Z.c | 62 | ||||
-rw-r--r-- | src/H5Zprivate.h | 1 | ||||
-rw-r--r-- | src/H5Zpublic.h | 6 | ||||
-rw-r--r-- | src/H5config.h.in | 3 | ||||
-rw-r--r-- | src/H5err.txt | 2 | ||||
-rw-r--r-- | src/H5private.h | 1 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/Makefile.in | 7 | ||||
-rw-r--r-- | src/hdf5.h | 1 | ||||
-rw-r--r-- | test/Makefile.am | 10 | ||||
-rw-r--r-- | test/Makefile.in | 46 | ||||
-rw-r--r-- | test/plugin.c | 810 | ||||
-rw-r--r-- | test/plugin_lib/Makefile.in | 26 | ||||
-rw-r--r-- | test/plugin_lib/dynlib1.c | 73 | ||||
-rw-r--r-- | test/plugin_lib/dynlib1.h | 9 | ||||
-rw-r--r-- | test/test_plugin.sh.in | 57 |
31 files changed, 1834 insertions, 44 deletions
@@ -846,6 +846,10 @@ ./src/H5Ppublic.h ./src/H5Pstrcpl.c ./src/H5Ptest.c +./src/H5PL.c +./src/H5PLpkg.c +./src/H5PLprivate.c +./src/H5PLpublic.c ./src/H5R.c ./src/H5Rdeprec.c ./src/H5Rpkg.h @@ -1027,6 +1031,7 @@ ./test/ntypes.c ./test/ohdr.c ./test/objcopy.c +./test/plugin.c ./test/reserved.c ./test/pool.c ./test/set_extent.c @@ -1049,6 +1054,7 @@ ./test/testhdf5.c ./test/testhdf5.h ./test/testlibinfo.sh.in +./test/test_plugin.sh.in ./test/testmeta.c ./test/tfile.c ./test/tgenprop.c @@ -1087,6 +1093,10 @@ ./test/gen_filters.c ./test/chunk_info.c +./test/plugin_lib/dynlib1.c +./test/plugin_lib/dynlib1.h +./test/plugin_lib/Makefile.in + ./test/testfiles/err_compat_1 ./test/testfiles/err_compat_2 ./test/testfiles/error_test_1 diff --git a/Makefile.in b/Makefile.in index 1472be5..7144e95 100644 --- a/Makefile.in +++ b/Makefile.in @@ -88,9 +88,10 @@ DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ $(top_srcdir)/bin/ltmain.sh $(top_srcdir)/bin/missing \ $(top_srcdir)/bin/mkinstalldirs \ $(top_srcdir)/config/commence.am $(top_srcdir)/configure \ - COPYING bin/COPYING bin/README bin/compile bin/config.guess \ - bin/config.sub bin/depcomp bin/install-sh bin/ltmain.sh \ - bin/missing bin/mkinstalldirs + $(top_srcdir)/test/plugin_lib/Makefile.in COPYING bin/COPYING \ + bin/README bin/compile bin/config.guess bin/config.sub \ + bin/depcomp bin/install-sh bin/ltmain.sh bin/missing \ + bin/mkinstalldirs subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -100,7 +101,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = test/plugin_lib/Makefile CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -519,6 +520,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): +test/plugin_lib/Makefile: $(top_builddir)/config.status $(top_srcdir)/test/plugin_lib/Makefile.in + cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo @@ -22247,7 +22247,7 @@ $as_echo "user-defined" >&6; } esac ## ---------------------------------------------------------------------- -## Check for system libraries. +## Check for system libraries. "dl" stands for dynamically loaded library ## { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ceil in -lm" >&5 $as_echo_n "checking for ceil in -lm... " >&6; } @@ -22302,6 +22302,59 @@ _ACEOF fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +#ifdef FC_DUMMY_MAIN +#ifndef FC_DUMMY_MAIN_EQ_F77 +# ifdef __cplusplus + extern "C" +# endif + int FC_DUMMY_MAIN() { return 1; } +#endif +#endif +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + if test "`uname`" = "SunOS" -o "`uname -sr`" = "HP-UX B.11.00"; then ## ...for Solaris @@ -31133,7 +31186,7 @@ if test -n "$TESTPARALLEL"; then fi fi -ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/H5srcdir_str.h test/testlibinfo.sh test/testlinks_env.sh testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumppbits.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5import/h5importtestutil.sh tools/h5diff/Makefile tools/h5diff/testh5diff.sh tools/h5diff/testph5diff.sh tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/h5copy/testh5copy.sh tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5mkgrp.sh tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/tools/Makefile hl/tools/gif2h5/Makefile hl/tools/gif2h5/h52giftest.sh hl/examples/Makefile hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile hl/fortran/examples/run-hlfortran-ex.sh" +ac_config_files="$ac_config_files src/libhdf5.settings Makefile src/Makefile test/Makefile test/testcheck_version.sh test/testerror.sh test/H5srcdir_str.h test/testlibinfo.sh test/testlinks_env.sh test/test_plugin.sh test/plugin_lib/Makefile testpar/Makefile testpar/testph5.sh perform/Makefile tools/Makefile tools/h5dump/Makefile tools/h5dump/testh5dump.sh tools/h5dump/testh5dumppbits.sh tools/h5dump/testh5dumpxml.sh tools/h5ls/testh5ls.sh tools/h5import/Makefile tools/h5import/h5importtestutil.sh tools/h5diff/Makefile tools/h5diff/testh5diff.sh tools/h5diff/testph5diff.sh tools/h5jam/Makefile tools/h5jam/testh5jam.sh tools/h5repack/Makefile tools/h5repack/h5repack.sh tools/h5ls/Makefile tools/h5copy/Makefile tools/h5copy/testh5copy.sh tools/lib/Makefile tools/misc/Makefile tools/misc/h5cc tools/misc/testh5mkgrp.sh tools/misc/testh5repart.sh tools/h5stat/testh5stat.sh tools/h5stat/Makefile examples/Makefile examples/run-c-ex.sh examples/testh5cc.sh c++/Makefile c++/src/Makefile c++/src/h5c++ c++/test/Makefile c++/test/H5srcdir_str.h c++/examples/Makefile c++/examples/run-c++-ex.sh c++/examples/testh5c++.sh fortran/Makefile fortran/src/h5fc fortran/src/Makefile fortran/test/Makefile fortran/testpar/Makefile fortran/examples/Makefile fortran/examples/run-fortran-ex.sh fortran/examples/testh5fc.sh hl/Makefile hl/src/Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/tools/Makefile hl/tools/gif2h5/Makefile hl/tools/gif2h5/h52giftest.sh hl/examples/Makefile hl/examples/run-hlc-ex.sh hl/c++/Makefile hl/c++/src/Makefile hl/c++/test/Makefile hl/c++/examples/Makefile hl/c++/examples/run-hlc++-ex.sh hl/fortran/Makefile hl/fortran/src/Makefile hl/fortran/test/Makefile hl/fortran/examples/Makefile hl/fortran/examples/run-hlfortran-ex.sh" cat >confcache <<\_ACEOF @@ -32394,6 +32447,8 @@ do "test/H5srcdir_str.h") CONFIG_FILES="$CONFIG_FILES test/H5srcdir_str.h" ;; "test/testlibinfo.sh") CONFIG_FILES="$CONFIG_FILES test/testlibinfo.sh" ;; "test/testlinks_env.sh") CONFIG_FILES="$CONFIG_FILES test/testlinks_env.sh" ;; + "test/test_plugin.sh") CONFIG_FILES="$CONFIG_FILES test/test_plugin.sh" ;; + "test/plugin_lib/Makefile") CONFIG_FILES="$CONFIG_FILES test/plugin_lib/Makefile" ;; "testpar/Makefile") CONFIG_FILES="$CONFIG_FILES testpar/Makefile" ;; "testpar/testph5.sh") CONFIG_FILES="$CONFIG_FILES testpar/testph5.sh" ;; "perform/Makefile") CONFIG_FILES="$CONFIG_FILES perform/Makefile" ;; diff --git a/configure.ac b/configure.ac index c6959f9..6b6d3a3 100644 --- a/configure.ac +++ b/configure.ac @@ -1242,9 +1242,10 @@ case "X-$enable_production" in esac ## ---------------------------------------------------------------------- -## Check for system libraries. +## Check for system libraries. "dl" stands for dynamically loaded library ## AC_CHECK_LIB([m], [ceil]) +AC_CHECK_LIB([dl], [dlopen]) if test "`uname`" = "SunOS" -o "`uname -sr`" = "HP-UX B.11.00"; then ## ...for Solaris @@ -4425,6 +4426,8 @@ AC_CONFIG_FILES([src/libhdf5.settings test/H5srcdir_str.h test/testlibinfo.sh test/testlinks_env.sh + test/test_plugin.sh + test/plugin_lib/Makefile testpar/Makefile testpar/testph5.sh perform/Makefile @@ -271,6 +271,7 @@ H5_term_library(void) pending += DOWN(Z); pending += DOWN(FD); pending += DOWN(P); + pending += DOWN(PL); /* Don't shut down the error code until other APIs which use it are shut down */ if(pending == 0) pending += DOWN(E); diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 2ae79e5..8557f13 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -25,6 +25,7 @@ hid_t H5E_FUNC_g = FAIL; /* Function entry/exit */ hid_t H5E_FILE_g = FAIL; /* File accessibilty */ hid_t H5E_SOHM_g = FAIL; /* Shared Object Header Messages */ hid_t H5E_SYM_g = FAIL; /* Symbol table */ +hid_t H5E_PLUGIN_g = FAIL; /* Plugin for dynamically loaded library */ hid_t H5E_VFL_g = FAIL; /* Virtual File Layer */ hid_t H5E_INTERNAL_g = FAIL; /* Internal error (too specific to document in detail) */ hid_t H5E_BTREE_g = FAIL; /* B-Tree node */ @@ -131,6 +132,8 @@ hid_t H5E_PATH_g = FAIL; /* Problem with path to object */ /* No error */ hid_t H5E_NONE_MINOR_g = FAIL; /* No error */ +/* Plugin errors */ + /* File accessibilty errors */ hid_t H5E_FILEEXISTS_g = FAIL; /* File already exists */ hid_t H5E_FILEOPEN_g = FAIL; /* File already open */ diff --git a/src/H5Einit.h b/src/H5Einit.h index a2eb02f..edd9bf5 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -44,6 +44,11 @@ if((msg = H5E_create_msg(cls, H5E_MAJOR, "Symbol table"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_SYM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_PLUGIN_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MAJOR, "Plugin for dynamically loaded library"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_PLUGIN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_VFL_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MAJOR, "Virtual File Layer"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") @@ -477,6 +482,8 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "No error"))==NULL) if((H5E_NONE_MINOR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +/* Plugin errors */ + /* File accessibilty errors */ assert(H5E_FILEEXISTS_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MINOR, "File already exists"))==NULL) diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index ddfb1d3..3df7d7e 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -28,6 +28,7 @@ #define H5E_FILE (H5OPEN H5E_FILE_g) #define H5E_SOHM (H5OPEN H5E_SOHM_g) #define H5E_SYM (H5OPEN H5E_SYM_g) +#define H5E_PLUGIN (H5OPEN H5E_PLUGIN_g) #define H5E_VFL (H5OPEN H5E_VFL_g) #define H5E_INTERNAL (H5OPEN H5E_INTERNAL_g) #define H5E_BTREE (H5OPEN H5E_BTREE_g) @@ -60,6 +61,7 @@ H5_DLLVAR hid_t H5E_FUNC_g; /* Function entry/exit */ H5_DLLVAR hid_t H5E_FILE_g; /* File accessibilty */ H5_DLLVAR hid_t H5E_SOHM_g; /* Shared Object Header Messages */ H5_DLLVAR hid_t H5E_SYM_g; /* Symbol table */ +H5_DLLVAR hid_t H5E_PLUGIN_g; /* Plugin for dynamically loaded library */ H5_DLLVAR hid_t H5E_VFL_g; /* Virtual File Layer */ H5_DLLVAR hid_t H5E_INTERNAL_g; /* Internal error (too specific to document in detail) */ H5_DLLVAR hid_t H5E_BTREE_g; /* B-Tree node */ @@ -221,6 +223,8 @@ H5_DLLVAR hid_t H5E_PATH_g; /* Problem with path to object */ #define H5E_NONE_MINOR (H5OPEN H5E_NONE_MINOR_g) H5_DLLVAR hid_t H5E_NONE_MINOR_g; /* No error */ +/* Plugin errors */ + /* File accessibilty errors */ #define H5E_FILEEXISTS (H5OPEN H5E_FILEEXISTS_g) #define H5E_FILEOPEN (H5OPEN H5E_FILEOPEN_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 6c621bc..f782db5 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -26,6 +26,7 @@ H5E_FUNC_g= H5E_FILE_g= H5E_SOHM_g= H5E_SYM_g= +H5E_PLUGIN_g= H5E_VFL_g= H5E_INTERNAL_g= H5E_BTREE_g= @@ -133,6 +134,8 @@ H5E_PATH_g= /* No error */ H5E_NONE_MINOR_g= +/* Plugin errors */ + /* File accessibilty errors */ H5E_FILEEXISTS_g= H5E_FILEOPEN_g= diff --git a/src/H5PL.c b/src/H5PL.c new file mode 100644 index 0000000..4bf059c --- /dev/null +++ b/src/H5PL.c @@ -0,0 +1,401 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 H5PL_PACKAGE /*suppress error about including H5PLpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5PL_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 "H5Zprivate.h" /* Filter pipeline */ +#include "H5PLpkg.h" /* Plugin */ + +#define H5PL_DEFAULT_PATH "/usr:/usr/lib:/usr/local" +#define H5PL_PATH_SEPERATOR ":" + + +/*-------------------------------------------------------------------------- +NAME + H5PL_init_interface -- Initialize interface-specific information +USAGE + herr_t H5PL_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5PL_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5PL_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL_term_interface + * + * Purpose: Terminate the H5I interface: release all memory, reset all + * global variables to initial values. This only happens if all + * types have been destroyed from other interfaces. + * + * Return: Success: Positive if any action was taken that might + * affect some other interface; zero otherwise. + * + * Failure: Negative. + * + * Programmer: Raymond Lu + * 20 February 2013 + * + *------------------------------------------------------------------------- + */ +int +H5PL_term_interface(void) +{ + void *handle = NULL; + size_t i = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + /* Free the table of dynamic libraries */ + for(i=0; i<H5PL_table_used_g; i++) { + handle = (H5PL_table_g[i]).handle; +/*fprintf(stderr, "%s: handle=%p\n", FUNC, handle);*/ + H5PL_close(handle); + } + + H5PL_table_g = (H5PL_table_t *)H5MM_xfree(H5PL_table_g); + H5PL_table_used_g = H5PL_table_alloc_g = 0; + + for(i = 0; i < num_paths; i++) { + if(path_table[i]) + path_table[i] = H5MM_xfree(path_table[i]); + } + num_paths = 0; + path_found = FALSE; + + H5_interface_initialize_g = 0; + i = 1; + } /* end if */ + + FUNC_LEAVE_NOAPI(i) +} /* end H5PL_term_interface() */ + + + +/*------------------------------------------------------------------------- + * Function: H5PL_load + * + * Purpose: + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5PL_load(H5PL_type_t type, int id) +{ + char *dl_path = NULL; + char *origin_dl_path = NULL; + char *pathname = NULL; + size_t len = 0; + char *dir = NULL; + DIR *dirp = NULL; + int i; + void *handle = NULL; + htri_t found_in_table = FALSE; + htri_t found_in_path = FALSE; + H5Z_class2_t* (*PL_get_plugin_info)(void) = NULL; + H5Z_class2_t *plugin_info = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) + + /* Search in the table of already loaded plugin libraries */ + if((found_in_table = H5PL_search_table(type, id, &plugin_info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in table failed") + + /* Finish the function if found */ + if(found_in_table && plugin_info) { + ret_value = (void *)plugin_info; + HGOTO_DONE(ret_value) + } + + if(FALSE == path_found) { + origin_dl_path = HDgetenv("HDF5_PLUGIN_PATH"); + if(origin_dl_path == NULL) { + len = HDstrlen(H5PL_DEFAULT_PATH) + 1; + dl_path = (char *)H5MM_malloc(len*sizeof(char)); + HDstrncpy(dl_path, H5PL_DEFAULT_PATH, len-1); + dl_path[len-1] = '\0'; + } else { + len = HDstrlen(origin_dl_path) + 1; + dl_path = (char *)H5MM_malloc(len*sizeof(char)); + HDstrncpy(dl_path, origin_dl_path, len); + } + + dir = HDstrtok(dl_path, H5PL_PATH_SEPERATOR); + while(dir) { + path_table[num_paths] = (char *)HDmalloc(HDstrlen(dir) + 1); + path_table[num_paths][0] = '\0'; + HDstrcat(path_table[num_paths], dir); + num_paths++; + dir = HDstrtok(NULL, H5PL_PATH_SEPERATOR); + } + + path_found = TRUE; + } + +#ifndef TMP + for(i=0; i<num_paths; i++) { + /*fprintf(stderr, "path[%d]=%s\n", i, path_table[i]);*/ + if((found_in_path = H5PL_find(type, id, path_table[i], &plugin_info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in paths failed") + + /* Finish the function if found */ + if(found_in_path && plugin_info) { + ret_value = (void *)plugin_info; + HGOTO_DONE(ret_value) + } + } +#endif + +done: + if(dl_path) + dl_path = (char *)H5MM_xfree(dl_path); + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5PL_find + * + * Purpose: Given a path, this function opens the directory and iterates + * through all files to find the right plugin library. It + * loads the dynamic plugin library and keeps it on the list + * of loaded libraries. + * + * Return: TRUE on success, + * FALSE on not found, + * negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5PL_find(H5PL_type_t plugin_type, int type_id, char *dir, void **info) +{ + char *dl_path = NULL; + char *pathname = NULL; + DIR *dirp = NULL; + int i; + void *handle = NULL; + htri_t found_in_table = FALSE; + hbool_t free_path = FALSE; + H5Z_class2_t* (*H5PL_get_plugin_info)(void) = NULL; + H5Z_class2_t *plugin_info = NULL; + htri_t ret_value = FALSE; + + FUNC_ENTER_NOAPI(FAIL) + + + if(dirp = HDopendir(dir)) { + struct dirent *dp = NULL; + struct stat my_stat; + while ((dp = HDreaddir(dirp)) != NULL) { + if(!HDstrncmp(dp->d_name, "lib", 3) && HDstrstr(dp->d_name, ".so")) { + pathname = (char *)H5MM_malloc(strlen(dir) + strlen(dp->d_name) + 2); + HDstrncpy(pathname, dir, strlen(dir)+1); + HDstrcat(pathname, "/"); + HDstrcat(pathname, dp->d_name); + + /*fprintf(stderr, "dp->d_name=%s, pathname=%s. ", dp->d_name, pathname); + fprintf(stderr, "\n");*/ + + if(HDstat(pathname, &my_stat) == -1) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file: %s", strerror(errno)) + + if(!S_ISDIR(my_stat.st_mode)) { /* if directory, skip it */ + if(NULL == (handle = dlopen(pathname, RTLD_NOW|RTLD_LAZY))) { + /*fprintf(stderr, "not open dl library: %s", dlerror());*/ + if(!HDstrcmp(dp->d_name, "libbogus2.so")) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't open dl library: %s", dlerror()) + else + continue; + } + + dlerror(); /*clear error*/ + if(NULL == (H5PL_get_plugin_info = dlsym(handle, "H5PL_get_plugin_info"))) { + if(H5PL_close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + } + + if(H5PL_get_plugin_info) { + if(NULL == (plugin_info = (*H5PL_get_plugin_info)())) { + if(H5PL_close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info") + } + + if(plugin_info->id == type_id) { + (H5PL_table_g[H5PL_table_used_g]).handle = handle; + (H5PL_table_g[H5PL_table_used_g]).pl_type = plugin_type; + (H5PL_table_g[H5PL_table_used_g]).pl_id = plugin_info->id; +/*fprintf(stderr, "%s: H5PL_table_used_g=%d, id=%d, id 2=%d\n", FUNC, H5PL_table_used_g, (H5PL_table_g[H5PL_table_used_g]).pl_id, plugin_info->id);*/ + H5PL_table_used_g++; + + *info = (void *)plugin_info; + ret_value = TRUE; + + HGOTO_DONE(ret_value) + } else if(H5PL_close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + } + } + + if(pathname) + pathname = (char *)H5MM_xfree(pathname); + } + } + + if(HDclosedir(dirp) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", strerror(errno)) + dirp = NULL; + } + + +done: + if(pathname) + pathname = (char *)H5MM_xfree(pathname); + if(dirp) + HDclosedir(dirp); + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5PL_search_table + * + * Purpose: + * + * Return: TRUE on success, + * FALSE on not found, + * negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5PL_search_table(H5PL_type_t plugin_type, int type_id, void **info) +{ + htri_t found = FALSE; + H5Z_class2_t* (*H5PL_get_plugin_info)(void) = NULL; + H5Z_class2_t *plugin_info = NULL; + int i; + htri_t ret_value = FALSE; + + FUNC_ENTER_NOAPI(FAIL) + +/*if(0 < H5PL_table_used_g) +fprintf(stderr, "%s: H5PL_table_used_g=%d, id=%d\n", FUNC, H5PL_table_used_g, (H5PL_table_g[H5PL_table_used_g-1]).pl_id);*/ + + /* Search in the table of already opened dynamic libraries */ + if(0 < H5PL_table_used_g) { + for(i=0; i<H5PL_table_used_g; i++) { + if((plugin_type == (H5PL_table_g[i]).pl_type) && (type_id == (H5PL_table_g[i]).pl_id)) { + if(NULL == (H5PL_get_plugin_info = dlsym((H5PL_table_g[i]).handle, "H5PL_get_plugin_info"))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function: %s", dlerror()) + + if(NULL == (plugin_info = (*H5PL_get_plugin_info)())) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info") + + /*fprintf(stderr, "%s: handle=%p, H5PL_get_plugin_info=%p, plugin_info=%p, id=%d\n", FUNC, (H5PL_table_g[i]).handle, H5PL_get_plugin_info, plugin_info, plugin_info->id);*/ + + *info = (void *)plugin_info; + ret_value = TRUE; + } + } + } + + /* Expand the table if it is small */ + if(H5PL_table_used_g >= H5PL_table_alloc_g) { + size_t n = MAX(H5Z_MAX_NFILTERS, 2*H5PL_table_alloc_g); + H5PL_table_t *table = (H5PL_table_t *)H5MM_realloc(H5PL_table_g, n * sizeof(H5PL_table_t)); + + if(!table) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend dynamic library table") + + H5PL_table_g = table; + H5PL_table_alloc_g = n; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5PL_close + * + * Purpose: + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5PL_close(void *handle) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) +/*fprintf(stderr, "%s: closing. handle=%p\n", FUNC, handle);*/ + dlclose(handle); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + diff --git a/src/H5PLpkg.h b/src/H5PLpkg.h new file mode 100644 index 0000000..adbe38a --- /dev/null +++ b/src/H5PLpkg.h @@ -0,0 +1,59 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef H5PL_PACKAGE +#error "Do not include this file outside the H5PL package!" +#endif + +#ifndef _H5PLpkg_H +#define _H5PLpkg_H + +/* Include private header file */ +#include "H5PLprivate.h" + +#define MAX_PATH_NUM 16 + +/****************************/ +/* Local typedefs */ +/****************************/ + +typedef struct H5PL_table_t { + H5PL_type_t pl_type; /* plugin type */ + int pl_id; /* ID for the plugin */ + void *handle; /* plugin handle */ +} H5PL_table_t; + +/****************************/ +/* Local variables */ +/****************************/ + +static size_t H5PL_table_alloc_g = 0; +static size_t H5PL_table_used_g = 0; +static H5PL_table_t *H5PL_table_g = NULL; + +static char *path_table[MAX_PATH_NUM]; +static size_t num_paths = 0; +static htri_t path_found = FALSE; + +/******************************/ +/* Package Private Prototypes */ +/******************************/ + +/* Function prototypes for H5PL package scope */ +htri_t H5PL_find(H5PL_type_t plugin_type, int type_id, char *dir, void **info); +htri_t H5PL_search_table(H5PL_type_t plugin_type, int type_id, void **info); + +#endif /* _H5PLpkg_H */ + diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h new file mode 100644 index 0000000..0a79249 --- /dev/null +++ b/src/H5PLprivate.h @@ -0,0 +1,59 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Raymond Lu <songyulu@hdfgroup.org> + * 13 February 2013 + */ + +#ifndef _H5PLprivate_H +#define _H5PLprivate_H + +/* Include package's public header */ +#include "H5PLpublic.h" + +/* Private headers needed by this file */ +#include "H5private.h" /* Generic Functions */ + +#ifdef H5_HAVE_DLFCN_H + #include <dlfcn.h> +#endif + +#include <dirent.h> +/*#include <sys/dirent.h>*/ + +/**************************/ +/* Library Private Macros */ +/**************************/ + + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + + +/*****************************/ +/* Library-private Variables */ +/*****************************/ + + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ + +/* Internal API routines */ +H5_DLL void* H5PL_load(H5PL_type_t plugin_type, int type_id); +H5_DLL herr_t H5PL_close(void *handle); + +#endif diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h new file mode 100644 index 0000000..1f21f88 --- /dev/null +++ b/src/H5PLpublic.h @@ -0,0 +1,45 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Raymond Lu <songyulu@hdfgroup.org> + * 13 February 2013 + */ +#ifndef _H5PLpublic_H +#define _H5PLpublic_H + +/* Public headers needed by this file */ +#include "H5public.h" + +/****************************/ +/* Library Public Typedefs */ +/****************************/ + +typedef enum H5PL_type_t { + H5PL_TYPE_ERROR = -1, /*error */ + H5PL_TYPE_FILTER = 0, /*filter */ + H5PL_TYPE_VFD = 1, /*virtual file driver */ + H5PL_TYPE_NONE = 2 /*this must be last! */ +} H5PL_type_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index d8ddfee..032162a 100644 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -38,6 +38,8 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ +#include "H5PLprivate.h" /* Dynamic plugin */ +#include "H5Zprivate.h" /* Filter pipeline */ #include "H5Opkg.h" /* Object headers */ #include "H5Ppkg.h" /* Property lists */ @@ -746,9 +748,9 @@ herr_t H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags, size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/]) { - H5P_genplist_t *plist; /* Property list */ - H5O_pline_t pline; /* Filter pipeline */ - herr_t ret_value=SUCCEED; /* return value */ + H5P_genplist_t *plist; /* Property list */ + H5O_pline_t pline; /* Filter pipeline */ + herr_t ret_value=SUCCEED; /* return value */ FUNC_ENTER_API(FAIL) H5TRACE5("e", "iZfIuz*[a3]Iu", plist_id, filter, flags, cd_nelmts, cd_values); @@ -765,6 +767,84 @@ H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags, if(NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_CREATE))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + /* Call the private function */ + if(H5P_set_filter(plist, filter, flags, cd_nelmts, cd_values) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "failed to call private function") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_filter() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_set_filter + * + * Purpose: Adds the specified FILTER and corresponding properties to the + * end of the data or link output filter pipeline + * depending on whether PLIST is a dataset creation or group + * creation property list. The FLAGS argument specifies certain + * general properties of the filter and is documented below. + * The CD_VALUES is an array of CD_NELMTS integers which are + * auxiliary data for the filter. The integer vlues will be + * stored in the dataset object header as part of the filter + * information. + * + * The FLAGS argument is a bit vector of the following fields: + * + * H5Z_FLAG_OPTIONAL(0x0001) + * If this bit is set then the filter is optional. If the + * filter fails during an H5Dwrite() operation then the filter + * is just excluded from the pipeline for the chunk for which it + * failed; the filter will not participate in the pipeline + * during an H5Dread() of the chunk. If this bit is clear and + * the filter fails then the entire I/O operation fails. + * If this bit is set but encoding is disabled for a filter, + * attempting to write will generate an error. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + * Raymond Lu + * Tuesday, October 2, 2001 + * Changed the way to check parameter and set property for + * generic property list. + * + * Neil Fortner + * Wednesday, May 20, 2009 + * Overloaded to accept gcpl's as well as dcpl's and moved to + * H5Pocpl.c + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_set_filter(H5P_genplist_t *plist, H5Z_filter_t filter, unsigned int flags, + size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/]) +{ + H5O_pline_t pline; /* Filter pipeline */ + H5Z_class2_t *filter_info = NULL; + htri_t filter_avail = FALSE; /* Filter availability */ + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI(FAIL) + + if((filter_avail = H5Z_filter_avail(filter)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't check filter availability") + + if(!filter_avail) { + if((filter_info = (H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, (int)filter)) == NULL) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "failed to load dynamically loaded plugin") +/*if(filter_info) +fprintf(stderr, "%s: filter_info=%p, filter_info->id=%d\n", FUNC, filter_info, filter_info->id);*/ + if (H5Z_register (filter_info)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter") + + } + +#ifndef TMP /* Get the pipeline property to append to */ if(H5P_get(plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline") @@ -776,10 +856,11 @@ H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags, /* Put the I/O pipeline information back into the property list */ if(H5P_set(plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set pipeline") +#endif done: - FUNC_LEAVE_API(ret_value) -} /* end H5Pset_filter() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_set_filter() */ /*------------------------------------------------------------------------- diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 6560064..2006ced 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -108,6 +108,8 @@ H5_DLL herr_t H5P_modify_filter(H5P_genplist_t *plist, H5Z_filter_t filter, H5_DLL herr_t H5P_get_filter_by_id(H5P_genplist_t *plist, H5Z_filter_t id, unsigned int *flags, size_t *cd_nelmts, unsigned cd_values[], size_t namelen, char name[], unsigned *filter_config); +H5_DLL herr_t H5P_set_filter(H5P_genplist_t *plist, H5Z_filter_t filter, + unsigned int flags, size_t cd_nelmts, const unsigned int cd_values[/*cd_nelmts*/]); /* *SPECIAL* Don't make more of these! -QAK */ H5_DLL htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id); @@ -26,6 +26,7 @@ #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 */ @@ -303,6 +304,8 @@ H5Z_register (const H5Z_class2_t *cls) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) +/*if(cls) +fprintf(stderr, "cls=%p, cls->id=%d\n", cls, cls->id);*/ HDassert(cls); HDassert(cls->id >= 0 && cls->id <= H5Z_FILTER_MAX); @@ -450,7 +453,6 @@ done: htri_t H5Zfilter_avail(H5Z_filter_t id) { - size_t i; /* Local index variable */ htri_t ret_value=FALSE; /* Return value */ FUNC_ENTER_API(FAIL) @@ -459,6 +461,36 @@ H5Zfilter_avail(H5Z_filter_t id) /* Check args */ if(id<0 || id>H5Z_FILTER_MAX) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number") + + 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_filter_avail + * + * Purpose: Private function to check if a filter is available + * + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5Z_filter_avail(H5Z_filter_t id) +{ + 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++) @@ -468,8 +500,8 @@ H5Zfilter_avail(H5Z_filter_t id) } /* end if */ done: - FUNC_LEAVE_API(ret_value) -} /* end H5Zfilter_avail() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Z_filter_avail() */ /*------------------------------------------------------------------------- @@ -1088,16 +1120,36 @@ H5Z_pipeline(const H5O_pline_t *pline, unsigned flags, failed |= (unsigned)1 << idx; continue;/*filter excluded*/ } + + /* If the filter isn't registered, try to load it dynamically and register it. Otherwise, return failure */ + if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) { + H5Z_class2_t *filter_info = NULL; + + if((filter_info = (H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, (int)(pline->filter[idx].id))) != NULL) { + if (H5Z_register(filter_info)<0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter") + } else { + /* 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") + } + } + + /* 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) { /* 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) + pline->filter[idx].name) else HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter (name unavailable) is not registered") - } + fclass=&H5Z_table_g[fclass_idx]; #ifdef H5Z_DEBUG fstats=&H5Z_stat_table_g[fclass_idx]; diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h index c1528b3..f53b50c 100644 --- a/src/H5Zprivate.h +++ b/src/H5Zprivate.h @@ -92,6 +92,7 @@ H5_DLL herr_t H5Z_set_local_direct(const struct H5O_pline_t *pline); H5_DLL H5Z_filter_info_t *H5Z_filter_info(const struct H5O_pline_t *pline, H5Z_filter_t filter); H5_DLL htri_t H5Z_all_filters_avail(const struct H5O_pline_t *pline); +H5_DLL htri_t H5Z_filter_avail(H5Z_filter_t id); H5_DLL herr_t H5Z_delete(struct H5O_pline_t *pline, H5Z_filter_t filter); /* Data Transform Functions */ diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h index 5d9b5ed..b5ac475 100644 --- a/src/H5Zpublic.h +++ b/src/H5Zpublic.h @@ -42,6 +42,12 @@ typedef int H5Z_filter_t; #define H5Z_FILTER_NBIT 5 /*nbit compression */ #define H5Z_FILTER_SCALEOFFSET 6 /*scale+offset compression */ #define H5Z_FILTER_RESERVED 256 /*filter ids below this value are reserved for library use */ + +#define H5Z_FILTER_DYNLIB1 257 +#define H5Z_FILTER_DYNLIB2 258 + +#define H5Z_FILTER_BZIP2 300 + #define H5Z_FILTER_MAX 65535 /*maximum filter id */ /* General macros */ diff --git a/src/H5config.h.in b/src/H5config.h.in index 0308b38..c1cee13 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -187,6 +187,9 @@ /* Define to 1 if you have the <io.h> header file. */ #undef HAVE_IO_H +/* Define to 1 if you have the `dl' library (-ldl). */ +#undef HAVE_LIBDL + /* Define to 1 if you have the `dmalloc' library (-ldmalloc). */ #undef HAVE_LIBDMALLOC diff --git a/src/H5err.txt b/src/H5err.txt index ab3277f..282afd8 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -76,6 +76,7 @@ MAJOR, H5E_FSPACE, Free Space Manager MAJOR, H5E_SOHM, Shared Object Header Messages MAJOR, H5E_EARRAY, Extensible Array MAJOR, H5E_FARRAY, Fixed Array +MAJOR, H5E_PLUGIN, Plugin for dynamically loaded library MAJOR, H5E_NONE_MAJOR, No error # Sections (for grouping minor errors) @@ -98,6 +99,7 @@ SECTION, HEAP, Heap errors SECTION, FSPACE, Free space errors SECTION, PIPELINE, I/O pipeline errors SECTION, SYSTEM, System level errors +SECTION, PLUGIN, Plugin errors SECTION, NONE, No error # Minor errors diff --git a/src/H5private.h b/src/H5private.h index bff4e59..3bc8722 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -2350,6 +2350,7 @@ H5_DLL int H5G_term_interface(void); H5_DLL int H5I_term_interface(void); H5_DLL int H5L_term_interface(void); H5_DLL int H5P_term_interface(void); +H5_DLL int H5PL_term_interface(void); H5_DLL int H5R_term_interface(void); H5_DLL int H5S_term_interface(void); H5_DLL int H5T_term_interface(void); diff --git a/src/Makefile.am b/src/Makefile.am index 2669bdd..262bdc7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,7 +88,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \ H5Pdeprec.c H5Pdxpl.c H5Pencdec.c \ H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ - H5Pgcpl.c H5Pint.c \ + H5Pgcpl.c H5Pint.c H5PL.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \ H5R.c H5Rdeprec.c \ H5RC.c \ @@ -117,7 +117,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h \ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ - H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ + H5MMpublic.h H5Opublic.h H5PLpublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ H5Tpublic.h H5Zpublic.h # install libhdf5.settings in lib directory diff --git a/src/Makefile.in b/src/Makefile.in index d9dca2d..f7fe1d8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -158,7 +158,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Orefcount.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo \ H5Oshmesg.lo H5Otest.lo H5Ounknown.lo H5P.lo H5Pacpl.lo \ H5Pdapl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo H5Pencdec.lo \ - H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo \ + H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo H5PL.lo \ H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo \ H5Ptest.lo H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo \ H5Sall.lo H5Sdbg.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \ @@ -585,7 +585,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \ H5Pdeprec.c H5Pdxpl.c H5Pencdec.c \ H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ - H5Pgcpl.c H5Pint.c \ + H5Pgcpl.c H5Pint.c H5PL.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \ H5R.c H5Rdeprec.c \ H5RC.c \ @@ -614,7 +614,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h \ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ - H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ + H5MMpublic.h H5Opublic.h H5PLpublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ H5Tpublic.h H5Zpublic.h @@ -935,6 +935,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Otest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ounknown.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5P.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5PL.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pacpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdapl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdcpl.Plo@am__quote@ @@ -34,6 +34,7 @@ #include "H5MMpublic.h" /* Memory management */ #include "H5Opublic.h" /* Object headers */ #include "H5Ppublic.h" /* Property lists */ +#include "H5PLpublic.h" /* Plugin */ #include "H5Rpublic.h" /* References */ #include "H5Spublic.h" /* Dataspaces */ #include "H5Tpublic.h" /* Datatypes */ diff --git a/test/Makefile.am b/test/Makefile.am index fd40ad6..37975f2 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -24,9 +24,9 @@ include $(top_srcdir)/config/commence.am INCLUDES=-I$(top_srcdir)/src -I$(top_builddir)/src # Test script for error_test and err_compat -TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh +TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh check_SCRIPTS = $(TEST_SCRIPT) -SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) +SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) plugin$(EXEEXT) # These are our main targets. They should be listed in the order to be @@ -50,7 +50,7 @@ TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ # 'make check' doesn't run them directly, so they are not included in TEST_PROG. # Also build testmeta, which is used for timings test. It builds quickly, # and this lets automake keep all its test programs in one place. -check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_env +check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_env plugin # These programs generate test files for the tests. They don't need to be @@ -128,7 +128,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse earray.h5 efc[0-5].h5 log_vfd_out.log \ new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \ split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \ - file_image_core_test.h5.copy + file_image_core_test.h5.copy plugin.h5 # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ @@ -137,6 +137,6 @@ testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ tvlstr.c tvltypes.c # Temporary files. -DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh +DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh include $(top_srcdir)/config/conclude.am diff --git a/test/Makefile.in b/test/Makefile.in index 6f39794..458ede6 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -69,15 +69,15 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/H5srcdir_str.h.in $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/testcheck_version.sh.in \ - $(srcdir)/testerror.sh.in $(srcdir)/testlibinfo.sh.in \ - $(srcdir)/testlinks_env.sh.in $(top_srcdir)/bin/depcomp \ - $(top_srcdir)/bin/mkinstalldirs \ + $(srcdir)/Makefile.in $(srcdir)/test_plugin.sh.in \ + $(srcdir)/testcheck_version.sh.in $(srcdir)/testerror.sh.in \ + $(srcdir)/testlibinfo.sh.in $(srcdir)/testlinks_env.sh.in \ + $(top_srcdir)/bin/depcomp $(top_srcdir)/bin/mkinstalldirs \ $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am COPYING check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \ err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \ - links_env$(EXEEXT) + links_env$(EXEEXT) plugin$(EXEEXT) @BUILD_ALL_CONDITIONAL_TRUE@noinst_PROGRAMS = $(am__EXEEXT_2) TESTS = $(am__EXEEXT_1) $(TEST_SCRIPT) subdir = test @@ -88,7 +88,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/H5config.h CONFIG_CLEAN_FILES = testcheck_version.sh testerror.sh H5srcdir_str.h \ - testlibinfo.sh testlinks_env.sh + testlibinfo.sh testlinks_env.sh test_plugin.sh CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libh5test_la_LIBADD = @@ -377,6 +377,10 @@ ohdr_SOURCES = ohdr.c ohdr_OBJECTS = ohdr.$(OBJEXT) ohdr_LDADD = $(LDADD) ohdr_DEPENDENCIES = libh5test.la $(LIBHDF5) +plugin_SOURCES = plugin.c +plugin_OBJECTS = plugin.$(OBJEXT) +plugin_LDADD = $(LDADD) +plugin_DEPENDENCIES = libh5test.la $(LIBHDF5) pool_SOURCES = pool.c pool_OBJECTS = pool.$(OBJEXT) pool_LDADD = $(LDADD) @@ -477,10 +481,10 @@ SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \ gen_new_super.c gen_noencoder.c gen_nullspace.c gen_plist.c \ gen_sizes_lheap.c gen_specmetaread.c gen_udlinks.c getname.c \ gheap.c hyperslab.c istore.c lheap.c links.c links_env.c mf.c \ - mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ - set_extent.c space_overflow.c stab.c tcheck_version.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.c + mount.c mtime.c ntypes.c objcopy.c ohdr.c plugin.c pool.c \ + reserved.c set_extent.c space_overflow.c stab.c \ + tcheck_version.c $(testhdf5_SOURCES) testmeta.c \ + $(ttsafe_SOURCES) unlink.c vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \ bittests.c btree2.c cache.c cache_api.c cache_tagging.c \ cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \ @@ -494,9 +498,10 @@ DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \ gen_noencoder.c gen_nullspace.c gen_plist.c gen_sizes_lheap.c \ gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \ istore.c lheap.c links.c links_env.c mf.c mount.c mtime.c \ - ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c \ - space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \ - testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c + ntypes.c objcopy.c ohdr.c plugin.c pool.c reserved.c \ + set_extent.c space_overflow.c stab.c tcheck_version.c \ + $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ + vfd.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -817,13 +822,14 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \ objcopy_ext.dat trefer1.h5 trefer2.h5 app_ref.h5 farray.h5 \ earray.h5 efc[0-5].h5 log_vfd_out.log new_multi_file_v16-r.h5 \ new_multi_file_v16-s.h5 split_get_file_image_test-m.h5 \ - split_get_file_image_test-r.h5 file_image_core_test.h5.copy + split_get_file_image_test-r.h5 file_image_core_test.h5.copy \ + plugin.h5 INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src # Test script for error_test and err_compat -TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh +TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh check_SCRIPTS = $(TEST_SCRIPT) -SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) +SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) plugin$(EXEEXT) # These are our main targets. They should be listed in the order to be # executed, generally most specific tests to least specific tests. @@ -876,7 +882,7 @@ testhdf5_SOURCES = testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ # Temporary files. -DISTCLEANFILES = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh +DISTCLEANFILES = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh # Automake needs to be taught how to build lib, progs, and tests targets. # These will be filled in automatically for the most part (e.g., @@ -942,6 +948,8 @@ testlibinfo.sh: $(top_builddir)/config.status $(srcdir)/testlibinfo.sh.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ testlinks_env.sh: $(top_builddir)/config.status $(srcdir)/testlinks_env.sh.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +test_plugin.sh: $(top_builddir)/config.status $(srcdir)/test_plugin.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @@ -1162,6 +1170,9 @@ objcopy$(EXEEXT): $(objcopy_OBJECTS) $(objcopy_DEPENDENCIES) $(EXTRA_objcopy_DEP ohdr$(EXEEXT): $(ohdr_OBJECTS) $(ohdr_DEPENDENCIES) $(EXTRA_ohdr_DEPENDENCIES) @rm -f ohdr$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ohdr_OBJECTS) $(ohdr_LDADD) $(LIBS) +plugin$(EXEEXT): $(plugin_OBJECTS) $(plugin_DEPENDENCIES) $(EXTRA_plugin_DEPENDENCIES) + @rm -f plugin$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(plugin_OBJECTS) $(plugin_LDADD) $(LIBS) pool$(EXEEXT): $(pool_OBJECTS) $(pool_DEPENDENCIES) $(EXTRA_pool_DEPENDENCIES) @rm -f pool$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pool_OBJECTS) $(pool_LDADD) $(LIBS) @@ -1267,6 +1278,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objcopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ohdr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reserved.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_extent.Po@am__quote@ diff --git a/test/plugin.c b/test/plugin.c new file mode 100644 index 0000000..4385916 --- /dev/null +++ b/test/plugin.c @@ -0,0 +1,810 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Raymond Lu + * 13 February 2013 + * + * Purpose: Tests the plugin module (H5PL) + */ +#include <stdlib.h> +#include <time.h> + +#include "h5test.h" +#include "H5srcdir.h" + +/* + * This file needs to access private datatypes from the H5Z package. + */ +#define H5Z_PACKAGE +#include "H5Zpkg.h" + +const char *FILENAME[] = { + "plugin", + NULL +}; +#define FILENAME_BUF_SIZE 1024 +#define KB 1024 + +#define FILE_DEFLATE_NAME "deflate.h5" + +/* Dataset names for testing filters */ +#define DSET_DEFAULT_NAME "default" +#define DSET_CHUNKED_NAME "chunked" +#define DSET_COMPACT_NAME "compact" +#define DSET_SIMPLE_IO_NAME "simple_io" +#define DSET_USERBLOCK_IO_NAME "userblock_io" +#define DSET_COMPACT_IO_NAME "compact_io" +#define DSET_COMPACT_MAX_NAME "max_compact" +#define DSET_COMPACT_MAX2_NAME "max_compact_2" +#define DSET_CONV_BUF_NAME "conv_buf" +#define DSET_TCONV_NAME "tconv" +#define DSET_DEFLATE_NAME "deflate" +#define DSET_BZIP2_NAME "bzip2" +#define DSET_DYNLIB1_NAME "dynlib1" +#define DSET_DYNLIB2_NAME "dynlib2" +#ifdef H5_HAVE_FILTER_SZIP +#define DSET_SZIP_NAME "szip" +#endif /* H5_HAVE_FILTER_SZIP */ +#define DSET_SHUFFLE_NAME "shuffle" +#define DSET_FLETCHER32_NAME "fletcher32" +#define DSET_FLETCHER32_NAME_2 "fletcher32_2" +#define DSET_FLETCHER32_NAME_3 "fletcher32_3" +#define DSET_SHUF_DEF_FLET_NAME "shuffle+deflate+fletcher32" +#define DSET_SHUF_DEF_FLET_NAME_2 "shuffle+deflate+fletcher32_2" +#if defined H5_HAVE_FILTER_SZIP && defined H5_HAVE_FILTER_SHUFFLE && defined H5_HAVE_FILTER_FLETCHER32 +#define DSET_SHUF_SZIP_FLET_NAME "shuffle+szip+fletcher32" +#define DSET_SHUF_SZIP_FLET_NAME_2 "shuffle+szip+fletcher32_2" +#endif /* defined H5_HAVE_FILTER_SZIP && defined H5_HAVE_FILTER_SHUFFLE && defined H5_HAVE_FILTER_FLETCHER32 */ + +#define DSET_MISSING_NAME "missing" +#define DSET_CAN_APPLY_NAME "can_apply" +#define DSET_CAN_APPLY_NAME2 "can_apply2" +#ifdef H5_HAVE_FILTER_SZIP +#define DSET_CAN_APPLY_SZIP_NAME "can_apply_szip" +#endif /* H5_HAVE_FILTER_SZIP */ +#define DSET_SET_LOCAL_NAME "set_local" +#define DSET_SET_LOCAL_NAME_2 "set_local_2" +#define DSET_ONEBYTE_SHUF_NAME "onebyte_shuffle" +#define DSET_NBIT_INT_NAME "nbit_int" +#define DSET_NBIT_FLOAT_NAME "nbit_float" +#define DSET_NBIT_DOUBLE_NAME "nbit_double" +#define DSET_NBIT_ARRAY_NAME "nbit_array" +#define DSET_NBIT_COMPOUND_NAME "nbit_compound" +#define DSET_NBIT_COMPOUND_NAME_2 "nbit_compound_2" +#define DSET_NBIT_COMPOUND_NAME_3 "nbit_compound_3" +#define DSET_NBIT_INT_SIZE_NAME "nbit_int_size" +#define DSET_NBIT_FLT_SIZE_NAME "nbit_flt_size" +#define DSET_SCALEOFFSET_INT_NAME "scaleoffset_int" +#define DSET_SCALEOFFSET_INT_NAME_2 "scaleoffset_int_2" +#define DSET_SCALEOFFSET_FLOAT_NAME "scaleoffset_float" +#define DSET_SCALEOFFSET_FLOAT_NAME_2 "scaleoffset_float_2" +#define DSET_SCALEOFFSET_DOUBLE_NAME "scaleoffset_double" +#define DSET_SCALEOFFSET_DOUBLE_NAME_2 "scaleoffset_double_2" +#define DSET_COMPARE_DCPL_NAME "compare_dcpl" +#define DSET_COMPARE_DCPL_NAME_2 "compare_dcpl_2" +#define DSET_COPY_DCPL_NAME_1 "copy_dcpl_1" +#define DSET_COPY_DCPL_NAME_2 "copy_dcpl_2" +#define COPY_DCPL_EXTFILE_NAME "ext_file" +#define DSET_DEPREC_NAME "deprecated" +#define DSET_DEPREC_NAME_CHUNKED "deprecated_chunked" +#define DSET_DEPREC_NAME_COMPACT "deprecated_compact" +#define DSET_DEPREC_NAME_FILTER "deprecated_filter" + +#define USER_BLOCK 1024 +#define SIXTY_FOUR_KB 65536 + +/* Temporary filter IDs used for testing */ + +/* Flags for testing filters */ +#define DISABLE_FLETCHER32 0 +#define ENABLE_FLETCHER32 1 +#define DATA_CORRUPTED 1 +#define DATA_NOT_CORRUPTED 0 + +/* Parameters for the "set local" test */ +#define BOGUS2_PERM_NPARMS 2 /* Number of "permanent" parameters */ +#define BOGUS2_PARAM_1 13 /* (No particular meaning, just for checking value) */ +#define BOGUS2_PARAM_2 35 /* (No particular meaning, just for checking value) */ +#define BOGUS2_ALL_NPARMS 4 /* Total number of parameter = permanent + "local" parameters */ + +/* Dimensionality for conversion buffer test */ +#define DIM1 100 /* Dim. Size of data member # 1 */ +#define DIM2 5000 /* Dim. Size of data member # 2 */ +#define DIM3 10 /* Dim. Size of data member # 3 */ + +/* Parameters for internal filter test */ +#define FILTER_CHUNK_DIM1 2 +#define FILTER_CHUNK_DIM2 25 +#define FILTER_HS_OFFSET1 7 +#define FILTER_HS_OFFSET2 30 +#define FILTER_HS_SIZE1 4 +#define FILTER_HS_SIZE2 50 + +/* Names for noencoder test */ +#ifdef H5_HAVE_FILTER_SZIP +#define NOENCODER_FILENAME "noencoder.h5" +#define NOENCODER_COPY_FILENAME "noencoder.h5.copy" +#define NOENCODER_TEST_DATASET "noencoder_tdset.h5" +#define NOENCODER_SZIP_DATASET "noencoder_szip_dset.h5" +#define NOENCODER_SZIP_SHUFF_FLETCH_DATASET "noencoder_szip_shuffle_fletcher_dset.h5" +#endif /* H5_HAVE_FILTER_SZIP */ + +/* Names for zero-dim test */ +#define ZERODIM_DATASET "zerodim" + +/* Parameters for zero-dim test */ +#define MISSING_CHUNK_DATASET "missing_chunk" +#define MISSING_CHUNK_DIM 100 + +/* Names for random chunks test */ +#define NPOINTS 50 + +/* Parameters for huge chunks test */ +#define HUGE_DATASET "Dataset" +#define HUGE_DIM ((hsize_t)16 * 1024 * 1024 * 1024) +#define HUGE_CHUNK_DIM ((hsize_t)2 * 1024 * 1024 * 1024) +#define TOO_HUGE_CHUNK_DIM ((hsize_t)4 * 1024 * 1024 * 1024) +#define HUGE_DATASET2 "Dataset2" +#define HUGE_DIM2_0 ((hsize_t)16 * 1024) +#define HUGE_DIM2_1 ((hsize_t)16 * 1024) +#define HUGE_DIM2_2 ((hsize_t)16 * 1024) +#define HUGE_CHUNK_DIM2_0 ((hsize_t)2 * 1024) +#define HUGE_CHUNK_DIM2_1 ((hsize_t)1024) +#define HUGE_CHUNK_DIM2_2 ((hsize_t)1024) +#define TOO_HUGE_CHUNK_DIM2_0 ((hsize_t)4 * 1024) +#define TOO_HUGE_CHUNK_DIM2_1 ((hsize_t)1024) +#define TOO_HUGE_CHUNK_DIM2_2 ((hsize_t)1024) + +/* Parameters for testing bypassing chunk cache */ +#define BYPASS_DATASET1 "Dset1" +#define BYPASS_DATASET2 "Dset2" +#define BYPASS_DIM 1000 +#define BYPASS_CHUNK_DIM 500 +#define BYPASS_FILL_VALUE 7 + +/* Shared global arrays */ +#define DSET_DIM1 100 +#define DSET_DIM2 200 + +int points_deflate[DSET_DIM1][DSET_DIM2], + points_dynlib1[DSET_DIM1][DSET_DIM2], + points_dynlib2[DSET_DIM1][DSET_DIM2], + points_bzip2[DSET_DIM1][DSET_DIM2]; + + +/*------------------------------------------------------------------------- + * Function: test_filter_internal + * + * Purpose: Tests + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Raymond Lu + * 27 February 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_filter_internal(hid_t fid, const char *name, hid_t dcpl, hsize_t *dset_size) +{ + hid_t dataset; /* Dataset ID */ + hid_t dxpl; /* Dataset xfer property list ID */ + hid_t write_dxpl; /* Dataset xfer property list ID for writing */ + hid_t sid; /* Dataspace ID */ + const hsize_t size[2] = {DSET_DIM1, DSET_DIM2}; /* Dataspace dimensions */ + const hsize_t hs_offset[2] = {FILTER_HS_OFFSET1, FILTER_HS_OFFSET2}; /* Hyperslab offset */ + const hsize_t hs_size[2] = {FILTER_HS_SIZE1, FILTER_HS_SIZE2}; /* Hyperslab size */ + void *tconv_buf = NULL; /* Temporary conversion buffer */ + int points[DSET_DIM1][DSET_DIM2], check[DSET_DIM1][DSET_DIM2]; + size_t i, j; /* Local index variables */ + int n = 0; + herr_t status; /* Error status */ + + /* Create the data space */ + if((sid = H5Screate_simple(2, size, NULL)) < 0) goto error; + + /* + * Create a small conversion buffer to test strip mining. We + * might as well test all we can! + */ + if((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) goto error; + tconv_buf = HDmalloc((size_t)1000); + if(H5Pset_buffer(dxpl, (size_t)1000, tconv_buf, NULL) < 0) goto error; + if((write_dxpl = H5Pcopy(dxpl)) < 0) TEST_ERROR; + + TESTING(" filters (setup)"); + + /* Check if all the filters are available */ + if(H5Pall_filters_avail(dcpl)!=TRUE) { + H5_FAILED(); + printf(" Line %d: Incorrect filter availability\n",__LINE__); + goto error; + } /* end if */ + + /* Create the dataset */ + if((dataset = H5Dcreate2(fid, name, H5T_NATIVE_INT, sid, H5P_DEFAULT, + dcpl, H5P_DEFAULT)) < 0) goto error; + + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 1: Read uninitialized data. It should be zero. + *---------------------------------------------------------------------- + */ + TESTING(" filters (uninitialized read)"); + + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) + TEST_ERROR; + + for(i=0; i<(size_t)size[0]; i++) { + for(j=0; j<(size_t)size[1]; j++) { + if(0!=check[i][j]) { + H5_FAILED(); + printf(" Read a non-zero value.\n"); + printf(" At index %lu,%lu\n", + (unsigned long)i, (unsigned long)j); + goto error; + } + } + } + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 2: Test filters by setting up a chunked dataset and writing + * to it. + *---------------------------------------------------------------------- + */ + TESTING(" filters (write)"); + + for(i=n=0; i<size[0]; i++) { + for(j=0; j<size[1]; j++) { + points[i][j] = (int)(n++); + } + } + + if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, write_dxpl, points) < 0) + TEST_ERROR; + + if((*dset_size=H5Dget_storage_size(dataset))==0) TEST_ERROR; + + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 3: Try to read the data we just wrote. + *---------------------------------------------------------------------- + */ + TESTING(" filters (read)"); + + /* Read the dataset back */ + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) + TEST_ERROR; + + /* Check that the values read are the same as the values written */ + for(i=0; i<size[0]; i++) { + for(j=0; j<size[1]; j++) { + if(points[i][j] != check[i][j]) { + H5_FAILED(); + fprintf(stderr," Read different values than written.\n"); + fprintf(stderr," At index %lu,%lu\n", (unsigned long)i, (unsigned long)j); + fprintf(stderr," At original: %d\n", (int)points[i][j]); + fprintf(stderr," At returned: %d\n", (int)check[i][j]); + goto error; + } + } + } + + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 4: Write new data over the top of the old data. The new data is + * random thus not very compressible, and will cause the chunks to move + * around as they grow. We only change values for the left half of the + * dataset although we rewrite the whole thing. + *---------------------------------------------------------------------- + */ + TESTING(" filters (modify)"); + + for(i=0; i<size[0]; i++) { + for(j=0; j<size[1]/2; j++) { + /*points[i][j] = (int)7;*/ + points[i][j] = (int)HDrandom (); + } + } + if(H5Dwrite (dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, write_dxpl, points) < 0) + TEST_ERROR; + + /* Read the dataset back and check it */ + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) + TEST_ERROR; + + /* Check that the values read are the same as the values written */ + for(i=0; i<size[0]; i++) { + for(j=0; j<size[1]; j++) { + if(points[i][j] != check[i][j]) { + H5_FAILED(); + printf(" Read different values than written.\n"); + printf(" At index %lu,%lu\n", + (unsigned long)i, (unsigned long)j); + goto error; + } + } + } + + if((*dset_size=H5Dget_storage_size(dataset))==0) TEST_ERROR; + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 5: Close the dataset and then open it and read it again. This + * insures that the filters message is picked up properly from the + * object header. + *---------------------------------------------------------------------- + */ + TESTING(" filters (re-open)"); + + if(H5Dclose(dataset) < 0) TEST_ERROR; + if((dataset = H5Dopen2(fid, name, H5P_DEFAULT)) < 0) TEST_ERROR; + + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) + TEST_ERROR; + + /* Check that the values read are the same as the values written */ + for(i = 0; i < size[0]; i++) + for(j = 0; j < size[1]; j++) + if(points[i][j] != check[i][j]) { + H5_FAILED(); + printf(" Read different values than written.\n"); + printf(" At index %lu,%lu\n", + (unsigned long)i, (unsigned long)j); + goto error; + } /* end if */ + + PASSED(); + + /*---------------------------------------------------------------------- + * STEP 6: Test partial I/O by writing to and then reading from a + * hyperslab of the dataset. The hyperslab does not line up on chunk + * boundaries (we know that case already works from above tests). + *---------------------------------------------------------------------- + */ + TESTING(" filters (partial I/O)"); + + for(i=0; i<(size_t)hs_size[0]; i++) { + for(j=0; j<(size_t)hs_size[1]; j++) { + points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j] = (int)HDrandom(); + } + } + if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, hs_offset, NULL, hs_size, + NULL) < 0) TEST_ERROR; + /* (Use the "read" DXPL because partial I/O on corrupted data test needs to ignore errors during writing) */ + if(H5Dwrite (dataset, H5T_NATIVE_INT, sid, sid, dxpl, points) < 0) + TEST_ERROR; + + if(H5Dread (dataset, H5T_NATIVE_INT, sid, sid, dxpl, check) < 0) + TEST_ERROR; + + /* Check that the values read are the same as the values written */ + for(i=0; i<(size_t)hs_size[0]; i++) { + for(j=0; j<(size_t)hs_size[1]; j++) { + if(points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j] != + check[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]) { + H5_FAILED(); + fprintf(stderr," Read different values than written.\n"); + fprintf(stderr," At index %lu,%lu\n", + (unsigned long)((size_t)hs_offset[0]+i), + (unsigned long)((size_t)hs_offset[1]+j)); + fprintf(stderr," At original: %d\n", + (int)points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]); + fprintf(stderr," At returned: %d\n", + (int)check[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]); + goto error; + } + } + } + + PASSED(); + + for(i=0; i<size[0]; i++) { + for(j=0; j<size[1]; j++) { + if(!HDstrcmp(name, DSET_DEFLATE_NAME)) { + points_deflate[i][j] = points[i][j]; + } else if(!HDstrcmp(name, DSET_DYNLIB1_NAME)) { + points_dynlib1[i][j] = points[i][j]; + } else if(!HDstrcmp(name, DSET_DYNLIB2_NAME)) { + points_dynlib2[i][j] = points[i][j]; + } else if(!HDstrcmp(name, DSET_BZIP2_NAME)) { + points_bzip2[i][j] = points[i][j]; + } + } + } + + /* Get the storage size of the dataset */ + if((*dset_size=H5Dget_storage_size(dataset))==0) goto error; + /* Clean up objects used for this test */ + if(H5Dclose (dataset) < 0) goto error; + if(H5Sclose (sid) < 0) goto error; + if(H5Pclose (dxpl) < 0) goto error; + free (tconv_buf); + + return(0); + +error: + if(tconv_buf) + free (tconv_buf); + return -1; +} + +/*------------------------------------------------------------------------- + * Function: test_filters + * + * Purpose: Tests dataset filter. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_filters(hid_t file, hid_t fapl) +{ + hid_t dc; /* Dataset creation property list ID */ + const hsize_t chunk_size[2] = {FILTER_CHUNK_DIM1, FILTER_CHUNK_DIM2}; /* Chunk dimensions */ + hsize_t null_size; /* Size of dataset with null filter */ + int compress_level = 9; + +#ifdef H5_HAVE_FILTER_DEFLATE + hsize_t deflate_size; /* Size of dataset with deflate filter */ +#endif /* H5_HAVE_FILTER_DEFLATE */ + + /*---------------------------------------------------------- + * STEP 2: Test deflation by itself. + *---------------------------------------------------------- + */ +#ifdef H5_HAVE_FILTER_DEFLATE + puts("Testing deflate filter"); + if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error; + if(H5Pset_chunk (dc, 2, chunk_size) < 0) goto error; + if(H5Pset_deflate (dc, 6) < 0) goto error; + + if(test_filter_internal(file,DSET_DEFLATE_NAME,dc,&deflate_size) < 0) goto error; + /* Clean up objects used for this test */ + if(H5Pclose (dc) < 0) goto error; +#else /* H5_HAVE_FILTER_DEFLATE */ + TESTING("deflate filter"); + SKIPPED(); + puts(" Deflate filter not enabled"); +#endif /* H5_HAVE_FILTER_DEFLATE */ + + /*---------------------------------------------------------- + * STEP 2: Test DYNLIB1 by itself. + *---------------------------------------------------------- + */ + puts("Testing DYNLIB1 filter"); + if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error; + if(H5Pset_chunk (dc, 2, chunk_size) < 0) goto error; + if(H5Pset_filter (dc, H5Z_FILTER_DYNLIB1, H5Z_FLAG_MANDATORY, 1, &compress_level) < 0) goto error; + + if(test_filter_internal(file,DSET_DYNLIB1_NAME,dc,&deflate_size) < 0) goto error; + /* Clean up objects used for this test */ + if(H5Pclose (dc) < 0) goto error; + /* Unregister the dynamic filter DYNLIB1 for testing purpose. The next time when this test is run for + * the new file format, the library's H5PL code has to search in the table of loaded plugin libraries + * for this filter. */ + if(H5Zunregister(H5Z_FILTER_DYNLIB1) < 0) goto error; + +#ifdef TMP + /*---------------------------------------------------------- + * STEP 2: Test Bogus2 by itself. + *---------------------------------------------------------- + */ + puts("Testing DYNLIB2 filter"); + if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error; + if(H5Pset_chunk (dc, 2, chunk_size) < 0) goto error; + if(H5Pset_filter (dc, H5Z_FILTER_DYNLIB2, H5Z_FLAG_MANDATORY, 1, &compress_level) < 0) goto error; + + if(test_filter_internal(file,DSET_DYNLIB2_NAME,dc,&deflate_size) < 0) goto error; + /* Clean up objects used for this test */ + if(H5Pclose (dc) < 0) goto error; + /* Unregister the dynamic filter BOGUS for testing purpose. The next time when this test is run for + * the new file format, the library's H5PL code has to search in the table of loaded plugin libraries + * for this filter. */ + if(H5Zunregister(H5Z_FILTER_DYNLIB2) < 0) goto error; + + + /*---------------------------------------------------------- + * STEP 3: Test BZIP2 by itself. + *---------------------------------------------------------- + */ + puts("Testing BZIP2 filter"); + if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) goto error; + if(H5Pset_chunk (dc, 2, chunk_size) < 0) goto error; + if(H5Pset_filter (dc, H5Z_FILTER_BZIP2, H5Z_FLAG_MANDATORY, 1, &compress_level) < 0) goto error; + + if(test_filter_internal(file,DSET_BZIP2_NAME,dc,&deflate_size) < 0) goto error; + /* Clean up objects used for this test */ + if(H5Pclose (dc) < 0) goto error; + /* Unregister the dynamic filter BOGUS for testing purpose. The next time when this test is run for + * the new file format, the library's H5PL code has to search in the table of loaded plugin libraries + * for this filter. */ + if(H5Zunregister(H5Z_FILTER_BZIP2) < 0) goto error; +#endif + + return 0; + +error: + return -1; +} + +/*------------------------------------------------------------------------- + * Function: test_read_data + * + * Purpose: Tests dataset filter. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_read_data(hid_t dataset, int *origin_data) +{ + int check[DSET_DIM1][DSET_DIM2]; + const hsize_t size[2] = {DSET_DIM1, DSET_DIM2}; /* Dataspace dimensions */ + int *data_p = origin_data; + size_t i, j; /* Local index variables */ + + /* Read the dataset back */ + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, check) < 0) + TEST_ERROR; + + /* Check that the values read are the same as the values written */ + for(i=0; i<size[0]; i++) { + for(j=0; j<size[1]; j++) { + if(*data_p != check[i][j]) { + H5_FAILED(); + fprintf(stderr," Read different values than written.\n"); + fprintf(stderr," At index %lu,%lu\n", (unsigned long)i, (unsigned long)j); + fprintf(stderr," At original: %d\n", *data_p); + fprintf(stderr," At returned: %d\n", (int)check[i][j]); + goto error; + } + data_p++; + } + } + + PASSED(); + return 0; + +error: + return -1; +} + +/*------------------------------------------------------------------------- + * Function: test_read_with_filters + * + * Purpose: Tests dataset filter. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_read_with_filters(hid_t file, hid_t fapl) +{ + hid_t dset; /* Dataset ID */ + hsize_t null_size; /* Size of dataset with null filter */ + int compress_level = 9; + +#ifdef H5_HAVE_FILTER_DEFLATE + hsize_t deflate_size; /* Size of dataset with deflate filter */ +#endif /* H5_HAVE_FILTER_DEFLATE */ + + /*---------------------------------------------------------- + * STEP 2: Test deflation by itself. + *---------------------------------------------------------- + */ +#ifdef H5_HAVE_FILTER_DEFLATE + TESTING("Testing deflate filter"); + + if(H5Zfilter_avail(H5Z_FILTER_DEFLATE) != TRUE) TEST_ERROR + + if((dset = H5Dopen2(file,DSET_DEFLATE_NAME,H5P_DEFAULT)) < 0) TEST_ERROR + + if(test_read_data(dset, points_deflate) < 0) TEST_ERROR + + if(H5Dclose(dset) < 0) TEST_ERROR + + /* Clean up objects used for this test */ +#else /* H5_HAVE_FILTER_DEFLATE */ + TESTING("deflate filter"); + SKIPPED(); + puts(" Deflate filter not enabled"); +#endif /* H5_HAVE_FILTER_DEFLATE */ + + /*---------------------------------------------------------- + * STEP 2: Test DYNLIB1 by itself. + *---------------------------------------------------------- + */ + TESTING("Testing DYNLIB1 filter"); + + if((dset = H5Dopen2(file,DSET_DYNLIB1_NAME,H5P_DEFAULT)) < 0) TEST_ERROR + + if(test_read_data(dset, points_dynlib1) < 0) TEST_ERROR + + if(H5Dclose(dset) < 0) TEST_ERROR + +#ifdef TMP + /*---------------------------------------------------------- + * STEP 2: Test Bogus2 by itself. + *---------------------------------------------------------- + */ + TESTING("Testing DYNLIB2 filter"); + + if((dset = H5Dopen2(file,DSET_DYNLIB2_NAME,H5P_DEFAULT)) < 0) TEST_ERROR + + if(test_read_data(dset, points_dynlib2) < 0) TEST_ERROR + + if(H5Dclose(dset) < 0) TEST_ERROR + + /*---------------------------------------------------------- + * STEP 3: Test BZIP2 by itself. + *---------------------------------------------------------- + */ + TESTING("Testing BZIP2 filter"); + + if((dset = H5Dopen2(file,DSET_BZIP2_NAME,H5P_DEFAULT)) < 0) TEST_ERROR + + if(test_read_data(dset, points_bzip2) < 0) TEST_ERROR + + if(H5Dclose(dset) < 0) TEST_ERROR + +#endif + + return 0; + +error: + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Tests the dataset interface (H5D) + * + * Return: Success: exit(0) + * + * Failure: exit(1) + * + * Programmer: Robb Matzke + * Tuesday, December 9, 1997 + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + char filename[FILENAME_BUF_SIZE]; + hid_t file, grp, fapl, fapl2; + hbool_t new_format; + int mdc_nelmts; + size_t rdcc_nelmts; + size_t rdcc_nbytes; + double rdcc_w0; + int nerrors = 0; + const char *envval; + + /* Don't run this test using certain file drivers */ + envval = HDgetenv("HDF5_DRIVER"); + if(envval == NULL) + envval = "nomatch"; + + /* Set the random # seed */ + HDsrandom((unsigned)HDtime(NULL)); + + /* Testing setup */ + h5_reset(); + fapl = h5_fileaccess(); + + /* Turn off the chunk cache, so all the chunks are immediately written to disk */ + if(H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts, &rdcc_nbytes, &rdcc_w0) < 0) + TEST_ERROR + rdcc_nbytes = 0; + if(H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0) + TEST_ERROR + + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Set the "use the latest version of the format" bounds for creating objects in the file */ + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR + + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + /* Test with old & new format groups */ + for(new_format = FALSE; new_format <= TRUE; new_format++) { + hid_t my_fapl; + + /* Set the FAPL for the type of format */ + if(new_format) { + puts("\nTesting with new file format:"); + my_fapl = fapl2; + } /* end if */ + else { + puts("Testing with old file format:"); + my_fapl = fapl; + } /* end else */ + + /* Create the file for this test */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) + TEST_ERROR + + /* Cause the library to emit initial messages */ + if((grp = H5Gcreate2(file, "emit diagnostics", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Oset_comment(grp, "Causes diagnostic messages to be emitted") < 0) + TEST_ERROR + if(H5Gclose(grp) < 0) + TEST_ERROR + + nerrors += (test_filters(file, my_fapl) < 0 ? 1 : 0); + + if(H5Fclose(file) < 0) + TEST_ERROR + } /* end for */ + + /* Close FAPL */ + if(H5Pclose(fapl2) < 0) TEST_ERROR + if(H5Pclose(fapl) < 0) TEST_ERROR + + puts("\nTesting reading data with with dynamic plugin filters:"); + + /* Close the library so that all loaded plugin libraries are unloaded */ + h5_reset(); + fapl = h5_fileaccess(); + + /* Reopen the file for testing data reading */ + if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) + TEST_ERROR + + nerrors += (test_read_with_filters(file, fapl) < 0 ? 1 : 0); + + if(H5Fclose(file) < 0) + TEST_ERROR + + if(nerrors) + TEST_ERROR + printf("All dataset tests passed.\n"); + h5_cleanup(FILENAME, fapl); + + return 0; + +error: + nerrors = MAX(1, nerrors); + printf("***** %d DATASET TEST%s FAILED! *****\n", + nerrors, 1 == nerrors ? "" : "S"); + return 1; +} diff --git a/test/plugin_lib/Makefile.in b/test/plugin_lib/Makefile.in new file mode 100644 index 0000000..aecb36e --- /dev/null +++ b/test/plugin_lib/Makefile.in @@ -0,0 +1,26 @@ +CFLAGS = -fPIC -g +CC = @CC@ +SRCDIR = @srcdir@ +TOP_SRCDIR = @top_srcdir@ +TOP_BUILDDIR = @top_builddir@ +MAJOR = 0 +MINOR = 1 +NAME1 = dynlib1 +VERSION = $(MAJOR).$(MINOR) + +# Include files in hdf5/src build/src directories for hdf5.h and H5pubconf.h +INCLUDES = -I$(TOP_SRCDIR)/src -I$(TOP_BUILDDIR)/src + +lib: lib$(NAME1).so.$(VERSION) + +$(NAME1).o: $(SRCDIR)/$(NAME1).c + $(CC) $(CFLAGS) $(INCLUDES) -c $(SRCDIR)/$(NAME1).c + +lib$(NAME1).so.$(VERSION): $(NAME1).o + $(CC) -shared -Wl,-soname,lib$(NAME1).so.$(MAJOR) $^ -o $@ + +clean: + $(RM) *.o *.so* Makefile + +distclean: + $(RM) *.o *.so* Makefile diff --git a/test/plugin_lib/dynlib1.c b/test/plugin_lib/dynlib1.c new file mode 100644 index 0000000..619fe66 --- /dev/null +++ b/test/plugin_lib/dynlib1.c @@ -0,0 +1,73 @@ +#include "dynlib1.h" + +/* This message derives from H5Z */ +const H5Z_class2_t H5Z_DYNLIB1[1] = {{ + H5Z_CLASS_T_VERS, /* H5Z_class_t version */ + H5Z_FILTER_DYNLIB1, /* Filter id number */ + 1, 1, /* Encoding and decoding enabled */ + "dynlib1", /* Filter name for debugging */ + NULL, /* The "can apply" callback */ + NULL, /* The "set local" callback */ + (H5Z_func_t)H5Z_filter_dynlib1, /* The actual filter function */ +}}; + +const H5PL_type_t H5PL_get_plugin_type(void) {return H5PL_TYPE_FILTER;} +const int H5PL_get_plugin_version(void) {return (int)FILTER_DYNLIB1_VERS;} +const char* H5PL_get_plugin_name(void) {return "dynlib1";} +const H5Z_class2_t* H5PL_get_plugin_info(void) {return H5Z_DYNLIB1;} + +/*------------------------------------------------------------------------- + * Function: H5Z_filter_dynlib1 + * + * Purpose: A dynlib1 compression method that doesn't do anything. + * + * Return: Success: Data chunk size + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Tuesday, April 21, 1998 + * + *------------------------------------------------------------------------- + */ +static size_t +H5Z_filter_dynlib1(unsigned int flags, size_t cd_nelmts, + const unsigned int *cd_values, size_t nbytes, + size_t *buf_size, void **buf) +{ + int *int_ptr=(int *)*buf; /* Pointer to the data values */ + size_t buf_left=*buf_size; /* Amount of data buffer left to process */ + int add_on = 0; + +/*fprintf(stderr, "cd_nelmts=%d, cd_values=%d\n", cd_nelmts, cd_values[0]);*/ + /* Check for the correct number of parameters */ + if(cd_nelmts==0) + return(0); + + /* Check that permanent parameters are set correctly */ + if(cd_values[0]<0 || cd_values[0]>9) + return(0); + + add_on = cd_values[0]; + +/*fprintf(stderr, "add_on=%d\n", add_on);*/ + + if(flags & H5Z_FLAG_REVERSE) { /*read*/ + /* Substract the "add on" value to all the data values */ + while(buf_left>0) { + *int_ptr++ -= add_on; + buf_left -= sizeof(int); + } /* end while */ + } /* end if */ + else { /*write*/ + /* Add the "add on" value to all the data values */ + while(buf_left>0) { + *int_ptr++ += add_on; + buf_left -= sizeof(int); + } /* end while */ + } /* end else */ + +/*fprintf(stderr, "nbytes=%d\n", nbytes);*/ + + return nbytes; +} diff --git a/test/plugin_lib/dynlib1.h b/test/plugin_lib/dynlib1.h new file mode 100644 index 0000000..f255ee4 --- /dev/null +++ b/test/plugin_lib/dynlib1.h @@ -0,0 +1,9 @@ +#include <stdlib.h> +#include <stdio.h> +#include <hdf5.h> + +#define FILTER_DYNLIB1_VERS 1 + +/* Local prototypes for filter functions */ +static size_t H5Z_filter_dynlib1(unsigned int flags, size_t cd_nelmts, + const unsigned int *cd_values, size_t nbytes, size_t *buf_size, void **buf); diff --git a/test/test_plugin.sh.in b/test/test_plugin.sh.in new file mode 100644 index 0000000..a1287a5 --- /dev/null +++ b/test/test_plugin.sh.in @@ -0,0 +1,57 @@ +#! /bin/sh +# +# 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. +# +# Tests for test_error and err_compat + +srcdir=@srcdir@ +TOP_BUILDDIR=@top_builddir@ + +echo $srcdir +echo $TOP_BUILDDIR + +# Determine backward compatibility options eneabled +DEPRECATED_SYMBOLS="@DEPRECATED_SYMBOLS@" + +nerrors=0 +verbose=yes + +#test -d ./plugin_lib +MAKE_CMD=make +CD=cd +TEST_NAME=plugin +TEST_BIN=`pwd`/$TEST_NAME +ENVCMD="env HDF5_PLUGIN_PATH=`pwd`/plugin_lib" + +# Run the test +$CD ./plugin_lib +echo "$MAKE_CMD" +$MAKE_CMD +$CD ../ +$ENVCMD $TEST_BIN +echo "$HDF5_PLUGIN_PATH" + +# Print a line-line message left justified in a field of 70 characters +# beginning with the word "Testing". +# +TESTING() { + SPACES=" " + echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012' +} + +if test $nerrors -eq 0 ; then + echo "All Error API tests passed." +fi + +exit $nerrors |