summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST10
-rw-r--r--Makefile.in11
-rw-r--r--config/cmake/ConfigureChecks.cmake2
-rw-r--r--config/cmake/H5pubconf.h.in6
-rwxr-xr-xconfigure71
-rw-r--r--configure.ac6
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/H5.c1
-rw-r--r--src/H5Edefin.h4
-rw-r--r--src/H5Einit.h12
-rw-r--r--src/H5Epubgen.h6
-rw-r--r--src/H5Eterm.h4
-rw-r--r--src/H5PL.c660
-rw-r--r--src/H5PLprivate.h53
-rw-r--r--src/H5PLpublic.h58
-rw-r--r--src/H5Pocpl.c74
-rw-r--r--src/H5Z.c77
-rw-r--r--src/H5Zprivate.h1
-rw-r--r--src/H5Zpublic.h5
-rw-r--r--src/H5config.h.in6
-rw-r--r--src/H5err.txt5
-rw-r--r--src/H5private.h12
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.in7
-rw-r--r--src/hdf5.h1
-rw-r--r--test/CMakeLists.txt15
-rw-r--r--test/Makefile.am10
-rw-r--r--test/Makefile.in46
-rw-r--r--test/plugin.c671
-rw-r--r--test/plugin_lib/CMakeLists.txt83
-rw-r--r--test/plugin_lib/Makefile.in45
-rw-r--r--test/plugin_lib/dynlib1.c98
-rw-r--r--test/test_plugin.sh.in60
-rw-r--r--test/testerror.sh.in9
-rw-r--r--tools/h5dump/testh5dump.sh.in5
35 files changed, 2104 insertions, 50 deletions
diff --git a/MANIFEST b/MANIFEST
index 25c118c8..ca718f5 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -849,6 +849,9 @@
./src/H5Ppublic.h
./src/H5Pstrcpl.c
./src/H5Ptest.c
+./src/H5PL.c
+./src/H5PLprivate.h
+./src/H5PLpublic.h
./src/H5R.c
./src/H5Rdeprec.c
./src/H5Rpkg.h
@@ -1030,6 +1033,7 @@
./test/ntypes.c
./test/ohdr.c
./test/objcopy.c
+./test/plugin.c
./test/reserved.c
./test/pool.c
./test/set_extent.c
@@ -1052,6 +1056,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
@@ -1090,6 +1095,10 @@
./test/gen_filters.c
./test/chunk_info.c
+./test/plugin_lib/dynlib1.c
+./test/plugin_lib/Makefile.in
+./test/plugin_lib/CMakeLists.txt
+
./test/testfiles/err_compat_1
./test/testfiles/err_compat_2
./test/testfiles/error_test_1
@@ -2412,6 +2421,7 @@
./perform/CMakeLists.txt
./src/CMakeLists.txt
./test/CMakeLists.txt
+./test/plugin_lib/CMakeLists.txt
./testpar/CMakeLists.txt
./tools/CMakeLists.txt
./tools/h5copy/CMakeLists.txt
diff --git a/Makefile.in b/Makefile.in
index a53e904..2ecc508 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
diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake
index 6db6d78..b2078e2 100644
--- a/config/cmake/ConfigureChecks.cmake
+++ b/config/cmake/ConfigureChecks.cmake
@@ -205,6 +205,7 @@ ENDIF (CYGWIN)
#-----------------------------------------------------------------------------
IF (NOT WINDOWS)
CHECK_LIBRARY_EXISTS_CONCAT ("m" ceil H5_HAVE_LIBM)
+ CHECK_LIBRARY_EXISTS_CONCAT ("dl" dlopen H5_HAVE_LIBDL)
CHECK_LIBRARY_EXISTS_CONCAT ("ws2_32" WSAStartup H5_HAVE_LIBWS2_32)
CHECK_LIBRARY_EXISTS_CONCAT ("wsock32" gethostbyname H5_HAVE_LIBWSOCK32)
ENDIF (NOT WINDOWS)
@@ -367,6 +368,7 @@ CHECK_INCLUDE_FILE_CONCAT ("sys/types.h" H5_HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILE_CONCAT ("stddef.h" H5_HAVE_STDDEF_H)
CHECK_INCLUDE_FILE_CONCAT ("setjmp.h" H5_HAVE_SETJMP_H)
CHECK_INCLUDE_FILE_CONCAT ("features.h" H5_HAVE_FEATURES_H)
+CHECK_INCLUDE_FILE_CONCAT ("dirent.h" H5_HAVE_DIRENT_H)
CHECK_INCLUDE_FILE_CONCAT ("stdint.h" H5_HAVE_STDINT_H)
# IF the c compiler found stdint, check the C++ as well. On some systems this
diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in
index d9f0997..2736daf 100644
--- a/config/cmake/H5pubconf.h.in
+++ b/config/cmake/H5pubconf.h.in
@@ -124,6 +124,9 @@
/* Define if the direct I/O virtual file driver should be compiled */
#cmakedefine H5_HAVE_DIRECT @H5_HAVE_DIRECT@
+/* Define to 1 if you have the <dirent.h> header file. */
+#cmakedefine H5_HAVE_DIRENT_H @H5_HAVE_DIRENT_H@
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine H5_HAVE_DLFCN_H @H5_HAVE_DLFCN_H@
@@ -230,6 +233,9 @@
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine H5_HAVE_IO_H @H5_HAVE_IO_H@
+/* Define to 1 if you have the `dl' library (-ldl). */
+#cmakedefine H5_HAVE_LIBDL @H5_HAVE_LIBDL@
+
/* Define to 1 if you have the `dmalloc' library (-ldmalloc). */
#cmakedefine H5_HAVE_LIBDMALLOC @H5_HAVE_LIBDMALLOC@
diff --git a/configure b/configure
index a31c67a..55bb4b3 100755
--- a/configure
+++ b/configure
@@ -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
@@ -22728,6 +22781,18 @@ fi
done
+for ac_header in dirent.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default"
+if test "x$ac_cv_header_dirent_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DIRENT_H 1
+_ACEOF
+
+fi
+
+done
+
for ac_header in stdint.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default"
@@ -31158,7 +31223,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
@@ -32419,6 +32484,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 a57d149..cfe6cec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1243,9 +1243,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
@@ -1275,6 +1276,7 @@ AC_CHECK_FUNCS([clock_gettime],[have_clock_gettime="yes"],[have_clock_gettime="n
AC_CHECK_HEADERS([sys/resource.h sys/time.h unistd.h sys/ioctl.h sys/stat.h])
AC_CHECK_HEADERS([sys/socket.h sys/types.h])
AC_CHECK_HEADERS([stddef.h setjmp.h features.h])
+AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([stdint.h], [C9x=yes])
## Darwin
@@ -4443,6 +4445,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
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f964992..4b70259 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -477,6 +477,15 @@ SET (H5P_HDRS
)
IDE_GENERATED_PROPERTIES ("H5P" "${H5P_HDRS}" "${H5P_SRCS}" )
+SET (H5PL_SRCS
+ ${HDF5_SRC_DIR}/H5PL.c
+)
+
+SET (H5PL_HDRS
+ ${HDF5_SRC_DIR}/H5PLpublic.h
+)
+IDE_GENERATED_PROPERTIES ("H5PL" "${H5PL_HDRS}" "${H5PL_SRCS}" )
+
SET (H5R_SRCS
${HDF5_SRC_DIR}/H5R.c
@@ -662,6 +671,7 @@ SET (common_SRCS
${H5MP_SRCS}
${H5O_SRCS}
${H5P_SRCS}
+ ${H5PL_SRCS}
${H5R_SRCS}
${H5RC_SRCS}
${H5RS_SRCS}
@@ -701,6 +711,7 @@ SET (H5_PUBLIC_HEADERS
${H5MP_HDRS}
${H5O_HDRS}
${H5P_HDRS}
+ ${H5PL_HDRS}
${H5R_HDRS}
${H5S_HDRS}
${H5SM_HDRS}
@@ -739,6 +750,7 @@ SET (H5_PRIVATE_HEADERS
${HDF5_SRC_DIR}/H5MPprivate.h
${HDF5_SRC_DIR}/H5Oprivate.h
${HDF5_SRC_DIR}/H5Pprivate.h
+ ${HDF5_SRC_DIR}/H5PLprivate.h
${HDF5_SRC_DIR}/H5RCprivate.h
${HDF5_SRC_DIR}/H5Rprivate.h
${HDF5_SRC_DIR}/H5RSprivate.h
@@ -825,6 +837,9 @@ SET_SOURCE_FILES_PROPERTIES (${HDF5_BINARY_DIR}/H5overflow.h GENERATED)
ADD_LIBRARY (${HDF5_LIB_TARGET} ${LIB_TYPE} ${common_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS})
TARGET_LINK_LIBRARIES (${HDF5_LIB_TARGET} ${LINK_LIBS})
+IF (NOT WIN32)
+ TARGET_LINK_LIBRARIES (${HDF5_LIB_TARGET} dl)
+ENDIF (NOT WIN32)
SET_GLOBAL_VARIABLE (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET})
H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} ${LIB_TYPE})
SET_TARGET_PROPERTIES (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries)
diff --git a/src/H5.c b/src/H5.c
index 14ec7ca..25525a4 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -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..183f72c 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,9 @@ hid_t H5E_PATH_g = FAIL; /* Problem with path to object */
/* No error */
hid_t H5E_NONE_MINOR_g = FAIL; /* No error */
+/* Plugin errors */
+hid_t H5E_OPENERROR_g = FAIL; /* Can't open directory or file */
+
/* 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..9724748 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,13 @@ 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 */
+assert(H5E_OPENERROR_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't open directory or file"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_OPENERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+
/* 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..e79106f 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,10 @@ 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 */
+#define H5E_OPENERROR (H5OPEN H5E_OPENERROR_g)
+H5_DLLVAR hid_t H5E_OPENERROR_g; /* Can't open directory or file */
+
/* 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..5db503c 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,9 @@ H5E_PATH_g=
/* No error */
H5E_NONE_MINOR_g=
+/* Plugin errors */
+H5E_OPENERROR_g=
+
/* 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..85ca97d
--- /dev/null
+++ b/src/H5PL.c
@@ -0,0 +1,660 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5PL__init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLprivate.h" /* Plugin */
+#include "H5Zprivate.h" /* Filter pipeline */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5PL_MAX_PATH_NUM 16
+
+/****************************/
+/* Macros for supporting
+ * both Windows and Unix */
+/****************************/
+/* Windows support */
+#ifdef H5_HAVE_WIN32_API
+
+#define H5PL_DEFAULT_PATH ".;/ProgramData;/Users/Public"
+#define H5PL_PATH_SEPARATOR ";"
+
+/* Handle for dynamic library */
+#define H5PL_HANDLE HINSTANCE
+
+/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
+#define H5PL_OPEN_DLIB(S) LoadLibraryEx(TEXT(S), NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
+
+/* Get the address of a symbol in dynamic library */
+#define H5PL_GET_LIB_FUNC(H,N) GetProcAddress(H,N)
+
+/* Close dynamic library */
+#define H5PL_CLOSE_LIB(H) FreeLibrary(H)
+
+/* Clear error - nothing to do */
+#define H5PL_CLR_ERROR
+
+typedef const H5Z_class2_t *(__cdecl *get_filter_info_t)();
+
+/* Unix support */
+#else /* H5_HAVE_WIN32_API */
+
+#define H5PL_DEFAULT_PATH "/usr:/usr/lib:/usr/local"
+#define H5PL_PATH_SEPARATOR ":"
+
+/* Handle for dynamic library */
+#define H5PL_HANDLE void *
+
+/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
+#define H5PL_OPEN_DLIB(S) dlopen(S, RTLD_NOW|RTLD_LAZY)
+
+/* Get the address of a symbol in dynamic library */
+#define H5PL_GET_LIB_FUNC(H,N) dlsym(H,N)
+
+/* Close dynamic library */
+#define H5PL_CLOSE_LIB(H) dlclose(H)
+
+/* Clear error */
+#define H5PL_CLR_ERROR dlerror()
+
+typedef const H5Z_class2_t *(*get_filter_info_t)();
+#endif /* H5_HAVE_WIN32_API */
+
+/* Special symbol to indicate no plugin loading */
+#define H5PL_NO_PLUGIN "::"
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Type for the list of info for opened plugin libraries */
+typedef struct H5PL_table_t {
+ H5PL_type_t pl_type; /* plugin type */
+ int pl_id; /* ID for the plugin */
+ H5PL_HANDLE handle; /* plugin handle */
+} H5PL_table_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5PL__init_path_table(void);
+static htri_t H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, void **info);
+static htri_t H5PL__open(H5PL_type_t pl_type, char *libname, int plugin_id, void **pl_info);
+static htri_t H5PL__search_table(H5PL_type_t plugin_type, int type_id, void **info);
+static herr_t H5PL__close(H5PL_HANDLE handle);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Table for opened plugin libraries */
+static size_t H5PL_table_alloc_g = 0;
+static size_t H5PL_table_used_g = 0;
+static H5PL_table_t *H5PL_table_g = NULL;
+
+/* Table of location paths for plugin libraries */
+static char *H5PL_path_table_g[H5PL_MAX_PATH_NUM];
+static size_t H5PL_num_paths_g = 0;
+static htri_t H5PL_path_found_g = FALSE;
+
+/* Table of preload pathnames for plugin libraries */
+static char *H5PL_preload_table_g[H5PL_MAX_PATH_NUM];
+static size_t H5PL_num_preload_g = 0;
+static hbool_t H5PL_no_plugin_g = FALSE;
+
+
+/*--------------------------------------------------------------------------
+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)
+{
+ char *preload_path = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Retrieve pathnames from HDF5_PLUGIN_PRELOAD if the user sets it
+ * to tell the library to load plugin libraries without search.
+ */
+ if(!(preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD")))
+ HGOTO_DONE(ret_value)
+
+ /* Special symbal "::" means no plugin during data reading. */
+ if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN)) {
+ H5PL_no_plugin_g = TRUE;
+ HGOTO_DONE(ret_value)
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_no_plugin
+ *
+ * Purpose: Quick way for filter module to query whether to load plugin
+ *
+ * Return: TRUE: No plugin loading during data reading
+ *
+ * FALSE: Load plugin during data reading
+ *
+ * Programmer: Raymond Lu
+ * 20 February 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t H5PL_no_plugin(void)
+{
+ hbool_t ret_value = FALSE;
+
+ FUNC_ENTER_NOAPI(ret_value)
+
+ ret_value = H5PL_no_plugin_g;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_term_interface
+ *
+ * Purpose: Terminate the H5PL 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)
+{
+ int i = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(H5_interface_initialize_g) {
+ size_t u; /* Local index variable */
+
+ /* Close opened dynamic libraries */
+ for(u = 0; u < H5PL_table_used_g; u++)
+ H5PL__close((H5PL_table_g[u]).handle);
+
+ /* Free the table of dynamic libraries */
+ H5PL_table_g = (H5PL_table_t *)H5MM_xfree(H5PL_table_g);
+ H5PL_table_used_g = H5PL_table_alloc_g = 0;
+
+ /* Free the table of search paths */
+ for(u = 0; u < H5PL_num_paths_g; u++)
+ if(H5PL_path_table_g[u])
+ H5PL_path_table_g[u] = (char *)H5MM_xfree(H5PL_path_table_g[u]);
+ H5PL_num_paths_g = 0;
+ H5PL_path_found_g = FALSE;
+
+ H5_interface_initialize_g = 0;
+ i = 1;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(i)
+} /* end H5PL_term_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_load
+ *
+ * Purpose: Given the plugin type and identifier, this function searches
+ * and/or loads a dynamic plugin library first among the already
+ * opened libraries then in the designated location paths.
+ *
+ * Return: Non-NULL on success/NULL on failure
+ *
+ * Programmer: Raymond Lu
+ * 13 February 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5PL_load(H5PL_type_t type, int id)
+{
+ htri_t found; /* Whether the plugin was found */
+ H5Z_class2_t *plugin_info = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Initialize the location paths for dynamic libraries, if they aren't
+ * already set up.
+ */
+ if(FALSE == H5PL_path_found_g)
+ if(H5PL__init_path_table() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, NULL, "can't initialize search path table")
+
+ /* Search in the table of already loaded plugin libraries */
+ if((found = H5PL__search_table(type, id, (void **)&plugin_info)) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in table failed")
+
+ /* If not found, iterate through the path table to find the right dynamic library */
+ if(!found) {
+ size_t i; /* Local index variable */
+
+ for(i = 0; i < H5PL_num_paths_g; i++) {
+ if((found = H5PL__find(type, id, H5PL_path_table_g[i], (void **)&plugin_info)) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in paths failed")
+
+ /* Break out if found */
+ if(found) {
+ HDassert(plugin_info);
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
+ /* Check if we found the plugin */
+ if(found)
+ ret_value = plugin_info;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__init_path_table
+ *
+ * Purpose: Initialize the path table.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * 18 March 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__init_path_table(void)
+{
+ char *dl_path = NULL;
+ char *origin_dl_path;
+ char *dir;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it
+ * or from the default paths if it isn't set.
+ */
+ origin_dl_path = HDgetenv("HDF5_PLUGIN_PATH");
+ if(NULL == origin_dl_path)
+ dl_path = HDstrdup(H5PL_DEFAULT_PATH);
+ else
+ dl_path = HDstrdup(origin_dl_path);
+ if(NULL == dl_path)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ /* Put paths in the path table. They are separated by ":" */
+ dir = HDstrtok(dl_path, H5PL_PATH_SEPARATOR);
+ while(dir) {
+ if(NULL == (H5PL_path_table_g[H5PL_num_paths_g] = HDstrdup(dir)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+ H5PL_num_paths_g++;
+ dir = HDstrtok(NULL, H5PL_PATH_SEPARATOR);
+ } /* end while */
+
+ H5PL_path_found_g = TRUE;
+
+done:
+ if(dl_path)
+ dl_path = (char *)H5MM_xfree(dl_path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__init_path_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__find
+ *
+ * Purpose: Given a path, this function opens the directory and envokes
+ * another function to go through all files to find the right
+ * plugin library. Two function definitions are for Unix and
+ * Windows.
+ *
+ * Return: TRUE on success,
+ * FALSE on not found,
+ * negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 13 February 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef H5_HAVE_WIN32_API
+static htri_t
+H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, void **info)
+{
+ char *pathname = NULL;
+ DIR *dirp = NULL;
+ struct dirent *dp;
+ htri_t ret_value = FALSE;
+
+ FUNC_ENTER_STATIC
+
+ /* Open the directory */
+ if(!(dirp = HDopendir(dir)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory")
+
+ /* Iterates through all entries in the directory to find the right plugin library */
+ while((dp = HDreaddir(dirp)) != NULL) {
+ /* The library we are looking for should be called libxxx.so... on Unix
+ * or libxxx.xxx.dylib on Mac.
+ */
+ if(!HDstrncmp(dp->d_name, "lib", (size_t)3) &&
+ (HDstrstr(dp->d_name, ".so") || HDstrstr(dp->d_name, ".dylib"))) {
+ h5_stat_t my_stat;
+ htri_t found_in_dir;
+
+ pathname = (char *)H5MM_malloc(HDstrlen(dir) + HDstrlen(dp->d_name) + 2);
+ HDstrncpy(pathname, dir, HDstrlen(dir) + 1);
+ HDstrcat(pathname, "/");
+ HDstrcat(pathname, dp->d_name);
+
+ if(HDstat(pathname, &my_stat) == -1)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file: %s", strerror(errno))
+
+ /* If it is a directory, skip it */
+ if(S_ISDIR(my_stat.st_mode))
+ continue;
+
+ /* Attempt to open the dynamic library as a filter library */
+ if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
+ if(found_in_dir) {
+ /* Indicate success */
+ ret_value = TRUE;
+ break;
+ } /* end if */
+ else
+ if(pathname)
+ pathname = (char *)H5MM_xfree(pathname);
+ } /* end if */
+ } /* end while */
+
+done:
+ if(dirp)
+ if(HDclosedir(dirp) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", strerror(errno))
+ if(pathname)
+ pathname = (char *)H5MM_xfree(pathname);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find() */
+#else
+static htri_t
+H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, void **info)
+{
+ WIN32_FIND_DATA fdFile;
+ HANDLE hFind;
+ char *pathname = NULL;
+ htri_t ret_value = FALSE;
+ char service[2048];
+
+ FUNC_ENTER_STATIC
+
+ /* Specify a file mask. *.* = We want everything! */
+ sprintf(service, "%s\/*.*", dir);
+ if((hFind = FindFirstFile(service, &fdFile)) == INVALID_HANDLE_VALUE)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory")
+
+ do {
+ /* Find first file will always return "."
+ * and ".." as the first two directories.
+ */
+ if(HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) {
+ htri_t found_in_dir;
+
+ pathname = (char *)H5MM_malloc(HDstrlen(dir) + HDstrlen(fdFile.cFileName) + 2);
+ HDstrncpy(pathname, dir, HDstrlen(dir)+1);
+ HDstrcat(pathname, "\\");
+ HDstrcat(pathname, fdFile.cFileName);
+
+ /* Is the entity a File or Folder? */
+ if(fdFile.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
+ if(found_in_dir) {
+ /* Indicate success */
+ ret_value = TRUE;
+ break;
+ } /* end if */
+ else
+ if(pathname)
+ pathname = (char *)H5MM_xfree(pathname);
+ } /* end if */
+ } while(FindNextFile(hFind, &fdFile)); /* Find the next file. */
+
+done:
+ if(hFind)
+ FindClose(hFind);
+ if(pathname)
+ pathname = (char *)H5MM_xfree(pathname);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find() */
+#endif
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__open
+ *
+ * Purpose: 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
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5PL__open(H5PL_type_t pl_type, char *libname, int pl_id, void **pl_info)
+{
+ H5PL_HANDLE handle = NULL;
+ get_filter_info_t get_plugin_info = NULL;
+ htri_t ret_value = FALSE;
+
+ FUNC_ENTER_STATIC
+
+ /* There are different reasons why a library can't be open, e.g. wrong architecture.
+ * simply continue if we can't open it.
+ */
+ if(NULL == (handle = H5PL_OPEN_DLIB(libname))) {
+ H5PL_CLR_ERROR; /* clear error */
+ } /* end if */
+ else {
+ /* Return a handle for the function H5PL_get_plugin_info in the dynamic library.
+ * The plugin library is suppose to define this function.
+ */
+ if(NULL == (get_plugin_info = (get_filter_info_t)H5PL_GET_LIB_FUNC(handle, "H5PL_get_plugin_info"))) {
+ if(H5PL__close(handle) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
+ } /* end if */
+ else {
+ H5Z_class2_t *plugin_info;
+
+ /* Invoke H5PL_get_plugin_info to verify this is the right library we are looking for.
+ * Move on if it isn't.
+ */
+ if(NULL == (plugin_info = (*get_plugin_info)())) {
+ if(H5PL__close(handle) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info")
+ } /* end if */
+
+ /* Successfully found plugin library, check if it's the right one */
+ if(plugin_info->id == pl_id) {
+ /* Expand the table if it is too 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 */
+
+ (H5PL_table_g[H5PL_table_used_g]).handle = handle;
+ (H5PL_table_g[H5PL_table_used_g]).pl_type = pl_type;
+ (H5PL_table_g[H5PL_table_used_g]).pl_id = plugin_info->id;
+ H5PL_table_used_g++;
+
+ /* Set the plugin info to return */
+ *pl_info = (void *)plugin_info;
+
+ /* Indicate success */
+ ret_value = TRUE;
+ } /* end if */
+ else
+ if(H5PL__close(handle) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
+ } /* end if */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__search_table
+ *
+ * Purpose: Search in the list of already opened dynamic libraries
+ * to see if the one we are looking for is already opened.
+ *
+ * Return: TRUE on success,
+ * FALSE on not found,
+ * Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 13 February 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5PL__search_table(H5PL_type_t plugin_type, int type_id, void **info)
+{
+ size_t i;
+ H5Z_class2_t *plugin_info;
+ get_filter_info_t get_plugin_info = NULL;
+ htri_t ret_value = FALSE;
+
+ FUNC_ENTER_STATIC
+
+ /* Search in the table of already opened dynamic libraries */
+ if(H5PL_table_used_g > 0) {
+ 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 == (get_plugin_info = (get_filter_info_t)H5PL_GET_LIB_FUNC((H5PL_table_g[i]).handle, "H5PL_get_plugin_info")))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function for H5PL_get_plugin_info")
+
+ if(NULL == (plugin_info = (*get_plugin_info)()))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info")
+
+ *info = (void *)plugin_info;
+ ret_value = TRUE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__search_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__close
+ *
+ * Purpose: Closes the handle for dynamic library
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 13 February 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__close(H5PL_HANDLE handle)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ H5PL_CLOSE_LIB(handle);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5PL__close() */
+
diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h
new file mode 100644
index 0000000..127ba98
--- /dev/null
+++ b/src/H5PLprivate.h
@@ -0,0 +1,53 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 */
+
+
+/**************************/
+/* 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 hbool_t H5PL_no_plugin(void);
+
+#endif /* _H5PLprivate_H */
diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h
new file mode 100644
index 0000000..6b17197
--- /dev/null
+++ b/src/H5PLpublic.h
@@ -0,0 +1,58 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 "H5Zpublic.h"
+
+/****************************/
+/* Library Public Typedefs */
+/****************************/
+
+/* Plugin type */
+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;
+
+
+/* plugins always export */
+#if defined (_MSC_VER) /* MSVC Compiler Case */
+ #define H5PLUGIN_DLL __declspec(dllexport)
+#elif (__GNUC__ >= 4) /* GCC 4.x has support for visibility options */
+ #define H5PLUGIN_DLL __attribute__ ((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ H5PLUGIN_DLL const H5PL_type_t H5PL_get_plugin_type(void);
+ H5PLUGIN_DLL const H5Z_class2_t* H5PL_get_plugin_info(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5PLpublic_H */
+
diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c
index d8ddfee..d3de509 100644
--- a/src/H5Pocpl.c
+++ b/src/H5Pocpl.c
@@ -40,6 +40,8 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5Ppkg.h" /* Property lists */
+#include "H5PLprivate.h" /* Dynamic plugin */
+#include "H5Zprivate.h" /* Filter pipeline */
/****************/
@@ -90,6 +92,9 @@ static herr_t H5P__ocrt_pipeline_enc(const void *value, void **_pp, size_t *size
static herr_t H5P__ocrt_pipeline_dec(const void **_pp, void *value);
static int H5P__ocrt_pipeline_cmp(const void *value1, const void *value2, size_t size);
+/* Local routines */
+static 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*/]);
/*********************/
/* Package Variables */
@@ -765,6 +770,71 @@ 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
+ *
+ *-------------------------------------------------------------------------
+ */
+static 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 */
+ htri_t filter_avail; /* Filter availability */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if filter is already available */
+ if((filter_avail = H5Z_filter_avail(filter)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't check filter availability")
+
+ /* If filter is not available, try to dynamically load it */
+ if(!filter_avail) {
+ H5Z_class2_t *filter_info;
+
+ if(NULL == (filter_info = (H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, (int)filter)))
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, FAIL, "failed to load dynamically loaded plugin")
+ if(H5Z_register(filter_info) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter")
+ } /* end if */
+
/* 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")
@@ -778,8 +848,8 @@ H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags,
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set pipeline")
done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Pset_filter() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__set_filter() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Z.c b/src/H5Z.c
index 3bb3a44..f838328 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -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 */
@@ -450,7 +451,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,13 +459,9 @@ 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")
-
- /* 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)
@@ -473,6 +469,36 @@ done:
/*-------------------------------------------------------------------------
+ * 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
+ *
+ *-------------------------------------------------------------------------
+ */
+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++)
+ if(H5Z_table_g[i].id == id)
+ HGOTO_DONE(TRUE)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5Z_filter_avail() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Z_prelude_callback
*
* Purpose: Makes a dataset creation "prelude" callback for the "can_apply"
@@ -1088,16 +1114,43 @@ H5Z_pipeline(const H5O_pline_t *pline, unsigned flags,
failed |= (unsigned)1 << idx;
continue;/*filter excluded*/
}
- if ((fclass_idx=H5Z_find_idx(pline->filter[idx].id))<0) {
+
+ /* 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_no_plugin()) {
+ H5Z_class2_t *filter_info;
+
+ if(NULL != (filter_info = (H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, (int)(pline->filter[idx].id)))) {
+ if(H5Z_register(filter_info) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter")
+ } /* end if */
+ 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")
+ } /* end else */
+
+ /* 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)
+ else
+ HGOTO_ERROR(H5E_PLINE, H5E_READERROR, FAIL, "required filter (name unavailable) is not registered")
+ } /* end if */
+ } else if((fclass_idx = H5Z_find_idx(pline->filter[idx].id)) < 0 && H5PL_no_plugin()) {
/* 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)
+ 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")
+ }
- }
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..c7c3562 100644
--- a/src/H5Zpublic.h
+++ b/src/H5Zpublic.h
@@ -42,6 +42,11 @@ 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 */
+
+/* Filters for HDF5 internal test */
+#define H5Z_FILTER_DYNLIB1 257
+#define H5Z_FILTER_DYNLIB2 258
+
#define H5Z_FILTER_MAX 65535 /*maximum filter id */
/* General macros */
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 0308b38..fc41c5a 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -87,6 +87,9 @@
/* Define if the direct I/O virtual file driver should be compiled */
#undef HAVE_DIRECT
+/* Define to 1 if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
@@ -187,6 +190,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..5a38cdf 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
@@ -258,5 +260,8 @@ MINOR, PIPELINE, H5E_CANTFILTER, Filter operation failed
# System level errors
MINOR, SYSTEM, H5E_SYSERRSTR, System error message
+# Plugin errors
+MINOR, PLUGIN, H5E_OPENERROR, Can't open directory or file
+
# No error, for backward compatibility */
MINOR, NONE, H5E_NONE_MINOR, No error
diff --git a/src/H5private.h b/src/H5private.h
index 44dd01b..78d3d9d 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -149,6 +149,17 @@
# include <io.h>
#endif
+/*
+ * Dynamic library handling. These are needed for dynamically loading I/O
+ * filters and VFDs.
+ */
+#ifdef H5_HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#ifdef H5_HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
#ifdef H5_HAVE_WIN32_API
/* The following two defines must be before any windows headers are included */
@@ -2351,6 +2362,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..a7f7bd9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,6 +90,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
H5Pgcpl.c H5Pint.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
+ H5PL.c \
H5R.c H5Rdeprec.c \
H5RC.c \
H5RS.c \
@@ -117,7 +118,9 @@ 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 H5Ppublic.h \
+ H5PLpublic.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 febb111..f280987 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@
diff --git a/src/hdf5.h b/src/hdf5.h
index a37329d..c2e4866 100644
--- a/src/hdf5.h
+++ b/src/hdf5.h
@@ -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/CMakeLists.txt b/test/CMakeLists.txt
index 6af1e94..d104978 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -7,6 +7,21 @@ PROJECT (HDF5_TEST)
ADD_DEFINITIONS (${HDF5_EXTRA_C_FLAGS})
#-----------------------------------------------------------------------------
+# If plugin library tests can be tested
+#-----------------------------------------------------------------------------
+IF (BUILD_SHARED_LIBS)
+ IF (EXISTS "${HDF5_TEST_SOURCE_DIR}/plugin_lib" AND IS_DIRECTORY "${HDF5_TEST_SOURCE_DIR}/plugin_lib")
+ ADD_SUBDIRECTORY (${HDF5_TEST_SOURCE_DIR}/plugin_lib ${PROJECT_BINARY_DIR}/plugin_lib)
+ ENDIF (EXISTS "${HDF5_TEST_SOURCE_DIR}/plugin_lib" AND IS_DIRECTORY "${HDF5_TEST_SOURCE_DIR}/plugin_lib")
+ELSE (BUILD_SHARED_LIBS)
+ MESSAGE (STATUS " **** Plugins libraries must be built as shared libraries **** ")
+ ADD_TEST (
+ NAME H5PLUGIN-SKIPPED
+ COMMAND ${CMAKE_COMMAND} -E echo "SKIP H5PLUGIN TESTING"
+ )
+ENDIF (BUILD_SHARED_LIBS)
+
+#-----------------------------------------------------------------------------
# Define Sources
#-----------------------------------------------------------------------------
SET (TEST_LIB_SRCS
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 64fd98a..81681ef 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..d5a30f9
--- /dev/null
+++ b/test/plugin.c
@@ -0,0 +1,671 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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"
+
+/* Filters for HDF5 internal test */
+#define H5Z_FILTER_DYNLIB1 257
+#define H5Z_FILTER_DYNLIB2 258
+
+/* Bzip2 filter */
+#define H5Z_FILTER_BZIP2 307
+
+const char *FILENAME[] = {
+ "plugin",
+ NULL
+};
+#define FILENAME_BUF_SIZE 1024
+
+/* Dataset names for testing filters */
+#define DSET_DEFLATE_NAME "deflate"
+#define DSET_BZIP2_NAME "bzip2"
+#define DSET_DYNLIB1_NAME "dynlib1"
+#define DSET_DYNLIB2_NAME "dynlib2"
+
+/* 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
+
+/* 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 writing entire data and partial data with filters
+ *
+ * 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)
+{
+ 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;
+
+ /* 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;
+
+ 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;
+ }
+ }
+ }
+
+ 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();
+
+ /* Save the data written to the file for later comparison when the file
+ * is reopened for read test */
+ 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];
+ }
+ }
+ }
+
+ /* 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 creating datasets and writing data with dynamically
+ * loaded filters
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * 14 March 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+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 */
+ unsigned int compress_level = 9;
+
+ /*----------------------------------------------------------
+ * 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) < 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, (size_t)1, &compress_level) < 0) goto error;
+
+ if(test_filter_internal(file,DSET_DYNLIB1_NAME,dc) < 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) < 0) goto error;
+
+ /* Clean up objects used for this test */
+ if(H5Pclose (dc) < 0) goto error;
+
+ /* Unregister the dynamic filter DYNLIB2 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) < 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 reading data and compares values
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * 14 March 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+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 reading dataset created with dynamically loaded filters
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * 14 March 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+test_read_with_filters(hid_t file, hid_t fapl)
+{
+ hid_t dset; /* Dataset ID */
+
+ /*----------------------------------------------------------
+ * 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 plugin module (H5PL)
+ *
+ * Return: Success: exit(0)
+ *
+ * Failure: exit(1)
+ *
+ * Programmer: Raymond Lu
+ * 14 March 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ char filename[FILENAME_BUF_SIZE];
+ hid_t file, fapl, fapl2;
+ hbool_t new_format;
+ int mdc_nelmts;
+ size_t rdcc_nelmts;
+ size_t rdcc_nbytes;
+ double rdcc_w0;
+ int nerrors = 0;
+
+ /* 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
+
+ /* Test dynamically loaded filters */
+ 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
+
+ /* Read the data with filters */
+ nerrors += (test_read_with_filters(file, fapl) < 0 ? 1 : 0);
+
+ if(H5Fclose(file) < 0)
+ TEST_ERROR
+
+ if(nerrors)
+ TEST_ERROR
+ printf("All plugin tests passed.\n");
+ h5_cleanup(FILENAME, fapl);
+
+ return 0;
+
+error:
+ nerrors = MAX(1, nerrors);
+ printf("***** %d PLUGIN TEST%s FAILED! *****\n",
+ nerrors, 1 == nerrors ? "" : "S");
+ return 1;
+}
+
diff --git a/test/plugin_lib/CMakeLists.txt b/test/plugin_lib/CMakeLists.txt
new file mode 100644
index 0000000..9428153
--- /dev/null
+++ b/test/plugin_lib/CMakeLists.txt
@@ -0,0 +1,83 @@
+cmake_minimum_required (VERSION 2.8.10)
+PROJECT (HDF5_TEST_PLUGIN_LIB)
+
+#-----------------------------------------------------------------------------
+# Set the core name of the library
+#-----------------------------------------------------------------------------
+SET (HDF5_TEST_PLUGIN_LIB_CORENAME "dynlib1")
+
+#-----------------------------------------------------------------------------
+# Set the true names of all the libraries if customized by external project
+#-----------------------------------------------------------------------------
+SET (HDF5_TEST_PLUGIN_LIB_NAME "${HDF5_EXTERNAL_LIB_PREFIX}${HDF5_TEST_PLUGIN_LIB_CORENAME}")
+
+#-----------------------------------------------------------------------------
+# Set the target names of all the libraries
+#-----------------------------------------------------------------------------
+SET (HDF5_TEST_PLUGIN_LIB_TARGET ${HDF5_TEST_PLUGIN_LIB_CORENAME})
+
+#-----------------------------------------------------------------------------
+# Apply Definitions to compiler in this directory and below
+#-----------------------------------------------------------------------------
+ADD_DEFINITIONS (${HDF5_EXTRA_C_FLAGS})
+
+#-----------------------------------------------------------------------------
+# Setup include Directories
+#-----------------------------------------------------------------------------
+INCLUDE_DIRECTORIES (${HDF5_SRC_DIR})
+
+#-----------------------------------------------------------------------------
+# Define Sources
+#-----------------------------------------------------------------------------
+
+SET (H5_TEST_PLUGIN_LIB_SRCS
+ ${HDF5_TEST_PLUGIN_LIB_SOURCE_DIR}/dynlib1.c
+)
+
+#-----------------------------------------------------------------------------
+# Generate the H5srcdir_str.h file containing user settings needed by compilation
+#-----------------------------------------------------------------------------
+SET (srcdir ${CMAKE_CURRENT_SOURCE_DIR})
+CONFIGURE_FILE (${HDF5_TEST_SOURCE_DIR}/H5srcdir_str.h.in H5srcdir_str.h @ONLY)
+INCLUDE_DIRECTORIES (${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY (${HDF5_TEST_PLUGIN_LIB_TARGET} ${LIB_TYPE} ${H5_TEST_PLUGIN_LIB_SRCS})
+TARGET_LINK_LIBRARIES (${HDF5_TEST_PLUGIN_LIB_TARGET} ${HDF5_TEST_LIB_TARGET})
+#SET_GLOBAL_VARIABLE( HDF5_LIBRARIES_TO_EXPORT "${HDF5_LIBRARIES_TO_EXPORT};${HDF5_TEST_PLUGIN_LIB_TARGET}")
+H5_SET_LIB_OPTIONS (
+ ${HDF5_TEST_PLUGIN_LIB_TARGET} ${HDF5_TEST_PLUGIN_LIB_NAME}
+ ${LIB_TYPE}
+ HDF5_TEST_PLUGIN_LIB_NAME_RELEASE
+ HDF5_TEST_PLUGIN_LIB_NAME_DEBUG
+)
+SET_TARGET_PROPERTIES (${HDF5_TEST_PLUGIN_LIB_TARGET} PROPERTIES FOLDER libraries/TEST_PLUGIN)
+
+#
+# Copy plugin library to a plugins folder
+#
+
+# make plugins dir
+FILE (MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/plugins")
+ADD_CUSTOM_COMMAND (
+ TARGET ${HDF5_TEST_PLUGIN_LIB_TARGET}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different
+ "$<TARGET_FILE:${HDF5_TEST_PLUGIN_LIB_TARGET}>"
+ "${CMAKE_BINARY_DIR}/plugins/$<TARGET_FILE_NAME:${HDF5_TEST_PLUGIN_LIB_TARGET}>"
+ )
+
+##############################################################################
+##############################################################################
+### T E S T S ###
+##############################################################################
+##############################################################################
+
+#-- Adding test for plugin
+ADD_EXECUTABLE (plugin ${HDF5_TEST_SOURCE_DIR}/plugin.c)
+TARGET_NAMING (plugin ${LIB_TYPE})
+TARGET_LINK_LIBRARIES (plugin ${HDF5_TEST_PLUGIN_LIB_TARGET})
+SET_TARGET_PROPERTIES (plugin PROPERTIES FOLDER test)
+
+ADD_TEST (NAME H5PLUGIN-plugin COMMAND $<TARGET_FILE:plugin>)
+SET_TESTS_PROPERTIES (H5PLUGIN-plugin PROPERTIES ENVIRONMENT "HDF5_PLUGIN_PATH=${CMAKE_BINARY_DIR}/plugins")
diff --git a/test/plugin_lib/Makefile.in b/test/plugin_lib/Makefile.in
new file mode 100644
index 0000000..00a2ea5
--- /dev/null
+++ b/test/plugin_lib/Makefile.in
@@ -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.
+#
+# HDF5 Library Test Makefile(.in)
+#
+# This Makefile.in is NOT generated by automake. Since we want to build
+# shared libraries for testing, automake can't create shared libraries when
+# configure asks to build static library.
+#
+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 $^ -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..d663bd7
--- /dev/null
+++ b/test/plugin_lib/dynlib1.c
@@ -0,0 +1,98 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 <stdio.h>
+#include <hdf5.h>
+
+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);
+
+/* 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 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/test_plugin.sh.in b/test/test_plugin.sh.in
new file mode 100644
index 0000000..c00df8c
--- /dev/null
+++ b/test/test_plugin.sh.in
@@ -0,0 +1,60 @@
+#! /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.
+#
+# This script file first envokes the Makefile in plugin_lib to build dynamic
+# plugin libraries. Then it moves the libraries to some locations and points
+# HDF5_PLUGIN_PATH to these locations. In the end, it runs plugin.c test.
+#
+
+srcdir=@srcdir@
+TOP_BUILDDIR=@top_builddir@
+
+echo $srcdir
+echo $TOP_BUILDDIR
+
+# Determine backward compatibility options enabled
+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 Plugin API tests passed."
+fi
+
+exit $nerrors
diff --git a/test/testerror.sh.in b/test/testerror.sh.in
index b68fa7e..eb01fb1 100644
--- a/test/testerror.sh.in
+++ b/test/testerror.sh.in
@@ -23,6 +23,9 @@ DEPRECATED_SYMBOLS="@DEPRECATED_SYMBOLS@"
CMP='cmp -s'
DIFF='diff -c'
+# Skip plugin module to test missing filter
+ENVCMD="env HDF5_PLUGIN_PRELOAD=::"
+
nerrors=0
verbose=yes
@@ -61,7 +64,9 @@ TEST() {
echo "#############################"
echo "Expected output for $TEST_ERR"
echo "#############################"
- $RUNSERIAL $TEST_ERR_BIN
+
+ # Skip the plugin for testing missing filter.
+ $ENVCMD $RUNSERIAL $TEST_ERR_BIN
) >$actual 2>$actual_err
# Extract file name, line number, version and thread IDs because they may be different
sed -e 's/thread [0-9]*/thread (IDs)/' -e 's/: .*\.c /: (file name) /' \
@@ -109,7 +114,7 @@ else
TEST err_compat
fi
-# test for error_test
+# test for error_test. Skip the plugin for testing missing filter.
TEST error_test
if test $nerrors -eq 0 ; then
diff --git a/tools/h5dump/testh5dump.sh.in b/tools/h5dump/testh5dump.sh.in
index 238eee9..cdd292a 100644
--- a/tools/h5dump/testh5dump.sh.in
+++ b/tools/h5dump/testh5dump.sh.in
@@ -38,6 +38,9 @@ DIRNAME='dirname'
LS='ls'
AWK='awk'
+# Skip plugin module to test missing filter
+ENVCMD="env HDF5_PLUGIN_PRELOAD=::"
+
nerrors=0
verbose=yes
@@ -675,7 +678,7 @@ TOOLTEST4() {
TESTING $DUMPER $@
(
cd $TESTDIR
- $RUNSERIAL $DUMPER_BIN "$@"
+ $ENVCMD $RUNSERIAL $DUMPER_BIN "$@"
) >$actual 2>$actual_err
# save actual and actual_err in case they are needed later.