Compare commits

...

12 Commits

Author SHA1 Message Date
Dana Robinson
f3469bbf4a Merge pull request #1633 in HDFFV/hdf5 from ~DEROBINS/hdf5_der:feature/json_vol to feature/json_vol
* commit '9b2bc5956784f311ff23512e1a359c29c1bd69a9':
  Yanked H5private.h and added hdf5.h.
2019-04-02 17:53:51 -05:00
Dana Robinson
9b2bc59567 Yanked H5private.h and added hdf5.h. 2019-04-01 15:17:53 -07:00
Dana Robinson
6e0d81dc8b Merge pull request #1629 in HDFFV/hdf5 from ~DEROBINS/hdf5_der:feature/json_vol to feature/json_vol
* commit '799a732650735b8ad05a0398781d2a26ec47b288': (185 commits)
  Updated the VOL struct. The json_vol test fails, though, because the plugin can't be found. Will diagnose later.
  Correct examples for packaging
  HDFFV-10738 Wrong INTENT for H5LTread_dataset_double_f
  Changes that show the right way to iterate over enums.
  Changes that show the right way to iterate over enums.
  Test improvement Description     Moved the new tests to a more appropriate test function. Platforms tested:     Linux/64 (jelly)
  Used the H5_INC_ENUM macro to squash enum value increment warnings.
  Fixed HDFFV-10210 and HDFFV-10587 Description:     - Added parameter validation (HDFFV-10210)     - Added detection of division by zero (HDFFV-10587 - CVE-2018-17438)     - Fixed typos in various tests Platforms tested:     Linux/64 (jelly)     Linux/64 (platypus)     Darwin (osx1011test)
  Fix CMake error in name
  Commented out memcpy overlap check while we investigate parallel filters issues.
  Yanked check for memcpy n > 0
  - Added H5MMprivate.h #includes where needed - Added casts to quiet H5MM_memcpy warnings - Removed char * casts from HDmemcpy
  Added an H5MM_memcpy call that checks for buffer overlap.
  Added the HDopen work-around on windows to pio_engine.c
  Adds _wopen support on Windows so that files with UTF-8 names can be opened.
  CMake: fix pthread linking to only be private
  Add API routines to retrieve, restore, reset, and free library state.
  Added a note of bug fix for HDFFV-10705.
  Fixed the MANIFEST
  Fix issue with direct chunk write not updating the "last chunk" index cache.  Fix issues involving datasets being "no allocated" when they contain cached raw data.
  ...
2019-03-30 20:31:11 -05:00
Dana Robinson
799a732650 Updated the VOL struct. The json_vol test fails, though, because
the plugin can't be found. Will diagnose later.
2019-03-30 18:29:07 -07:00
Dana Robinson
70c21ab3be Merge branch 'develop' into feature/json_vol 2019-03-30 17:48:05 -07:00
Dana Robinson
fdbbe61bcf Added some initial group construction code. 2019-01-06 10:17:49 -08:00
Dana Robinson
10495f34f8 Added libuuid for generating UUIDs. 2019-01-06 09:45:46 -08:00
Dana Robinson
c1f1c89f5a Updated the notes in BRANCH.md. 2019-01-06 08:57:40 -08:00
Dana Robinson
1b90939dab Added initial JSON string handling to the connector. 2019-01-06 08:43:35 -08:00
Dana Robinson
db9668da65 Added file create/open/close callbacks. These just perform the
file operations right now and don't deal with JSON streams.
2019-01-06 08:22:31 -08:00
Dana Robinson
1a95b844f2 * Checked in a correction to Makefile.am
* Added a BRANCH.md file
* Added Jansson configuration support
2019-01-06 07:09:43 -08:00
Dana Robinson
25a8e2e680 Added the JSON VOL connector plugin framework and a test to
ensure that the plugin can be loaded.
2019-01-06 06:48:41 -08:00
8 changed files with 847 additions and 4 deletions

30
BRANCH.md Normal file
View File

@@ -0,0 +1,30 @@
This branch is for the development of a test VOL connector to better
test the VOL API. In particular, this will expose any issues where
we've baked 'native file'-ness into the API.
The intent is to implement 100% of the HDF5 library's functionality
so it can be transparently subbed in for the native VOL connector.
The JSON parser I've chosen is Jannsen, which is used in other THG
products and projects and has an MIT license.
It currently only supports the Autotools, but it will not be difficult
to add CMake support.
Plan:
* Implement configuration and building via the autotools. (DONE)
* Add a test program that loads the connector. (DONE)
* Implement basic file operations.
* Implement group operations.
* Implement basic dataset operations.
* Implement basic attribute operations.
NOTES:
* The internets says to use libuuid to generate UUIDs as it's pretty
lightweight.
* Due to dependencies on libuuid and jansson, we're going to need to
protect the code and only build when everything is present. I think
this is okay since this is more of a test for ensuring the VOL doesn't
suck than it is a test that someone's build is working normally.
* Partial I/O is going to be crazy slow unless I want to add in some
sort of optimized data container behind the scenes.

View File

@@ -23,6 +23,7 @@
./.autom4te.cfg _DO_NOT_DISTRIBUTE_
./.h5chkright.ini _DO_NOT_DISTRIBUTE_
./ACKNOWLEDGMENTS
./BRANCH.md _DO_NOT_DISTRIBUTE_
./COPYING
./COPYING_LBNL_HDF5
./MANIFEST
@@ -1061,6 +1062,9 @@
./test/h5test.h
./test/hyperslab.c
./test/istore.c
./test/json_vol.c
./test/json_vol_connector.c
./test/json_vol_connector.h
./test/le_data.h5
./test/le_extlink1.h5
./test/le_extlink2.h5
@@ -1124,6 +1128,7 @@
./test/testframe.c
./test/testhdf5.c
./test/testhdf5.h
./test/test_json_vol.sh.in
./test/testlibinfo.sh.in
./test/test_usecases.sh.in
./test/test_vol_plugin.sh.in

View File

@@ -1027,6 +1027,7 @@ esac
##
AC_CHECK_LIB([m], [ceil])
AC_CHECK_LIB([dl], [dlopen])
AC_CHECK_LIB([uuid], [uuid_generate])
## ----------------------------------------------------------------------
## Check for system header files.
@@ -1041,6 +1042,7 @@ AC_CHECK_HEADERS([stddef.h setjmp.h features.h])
AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([stdint.h], [C9x=yes])
AC_CHECK_HEADERS([stdbool.h])
AC_CHECK_HEADERS([uuid/uuid.h])
## Darwin
AC_CHECK_HEADERS([mach/mach_time.h])
@@ -1254,6 +1256,87 @@ AC_ARG_WITH([fnord],
include/ and lib/ subdirectories
])
## ----------------------------------------------------------------------
## Is Jansson (JSON parser used for VOL testing) available? It has a
## header file 'jansson.h' and a library '-ljansson' and their locations
## might be specified with the '--with-jansson' command-line switch. The
## value is an include path and/or a library path. If the library path is
## specified then it must be preceded by a comma.
##
## NOTE: If this becomes an actual library thing, we'll eventually start
## distributing Jansson with the library so builders don't have
## have to go dig a copy up and install it. For right now, I
## simply avoid building the JSON VOL connector unless it's
## available.
##
AC_SUBST([HAVE_JANSSON])
## Default is not present
HAVE_JANSSON=no
AC_ARG_WITH([jansson],
[AS_HELP_STRING([--with-jansson=DIR],
["Location of Jansson JSON parser (used for testing)" [default=no]])],,
[withval=no])
case "X-$withval" in
X-yes)
HAVE_JANSSON="yes"
AC_CHECK_HEADERS([jansson.h],, [unset HAVE_JANSSON])
if test "x$HAVE_JANSSON" = "xyes"; then
AC_CHECK_LIB([jansson], [json_loads],, [unset HAVE_JANSSON])
fi
if test -z "$HAVE_JANSSON" -a -n "$HDF5_CONFIG_ABORT"; then
AC_MSG_ERROR([couldn't find Jansson library])
fi
;;
X-|X-no|X-none)
HAVE_JANSSON="no"
AC_MSG_CHECKING([for Jansson library])
AC_MSG_RESULT([suppressed])
;;
*)
HAVE_JANSSON="yes"
case "$withval" in
*,*)
jansson_inc="`echo $withval |cut -f1 -d,`"
jansson_lib="`echo $withval |cut -f2 -d, -s`"
;;
*)
if test -n "$withval"; then
jansson_inc="$withval/include"
jansson_lib="$withval/lib"
fi
;;
esac
saved_CPPFLAGS="$CPPFLAGS"
saved_AM_CPPFLAGS="$AM_CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
saved_AM_LDFLAGS="$AM_LDFLAGS"
if test -n "$jansson_inc"; then
CPPFLAGS="$CPPFLAGS -I$jansson_inc"
AM_CPPFLAGS="$AM_CPPFLAGS -I$jansson_inc"
fi
AC_CHECK_HEADERS([jansson.h],,[CPPFLAGS="$saved_CPPFLAGS"; AM_CPPFLAGS="$saved_AM_CPPFLAGS"] [unset HAVE_JANSSON])
if test "x$HAVE_JANSSON" = "xyes"; then
if test -n "$jansson_lib"; then
LDFLAGS="$LDFLAGS -L$jansson_lib"
AM_LDFLAGS="$AM_LDFLAGS -L$jansson_lib"
fi
AC_CHECK_LIB([jansson], [json_loads],, [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset HAVE_JANSSON])
fi
if test -z "$HAVE_JANSSON" -a -n "$HDF5_CONFIG_ABORT"; then
AC_MSG_ERROR([couldn't find Jansson library])
fi
;;
esac
## ----------------------------------------------------------------------
## Is dmalloc (debug malloc library) requested? It has a header file
## `dmalloc.h' and a library `-ldmalloc' and their locations might be
@@ -3478,6 +3561,7 @@ AC_CONFIG_FILES([src/libhdf5.settings
test/testcheck_version.sh
test/testerror.sh
test/testflushrefresh.sh
test/test_json_vol.sh
test/testlibinfo.sh
test/testlinks_env.sh
test/testswmr.sh

View File

@@ -42,8 +42,8 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) swmr_start_write$(EXEEXT) \
vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT)
if HAVE_SHARED_CONDITIONAL
TEST_SCRIPT += test_filter_plugin.sh test_vol_plugin.sh
SCRIPT_DEPEND += filter_plugin$(EXEEXT) vol_plugin$(EXEEXT)
TEST_SCRIPT += test_filter_plugin.sh test_vol_plugin.sh test_json_vol.sh
SCRIPT_DEPEND += filter_plugin$(EXEEXT) vol_plugin$(EXEEXT) json_vol$(EXEEXT)
endif
check_SCRIPTS = $(TEST_SCRIPT)
@@ -85,7 +85,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \
swmr_check_compat_vfd vds_swmr_gen vds_swmr_reader vds_swmr_writer
if HAVE_SHARED_CONDITIONAL
check_PROGRAMS+= filter_plugin vol_plugin
check_PROGRAMS+= filter_plugin vol_plugin json_vol
endif
# These programs generate test files for the tests. They don't need to be
@@ -108,7 +108,10 @@ if HAVE_SHARED_CONDITIONAL
# The libh5test library provides common support code for the tests.
# The filter_plugin* libraries are for use in filter_plugin.c.
# Build them as shared libraries if that option was enabled in configure.
noinst_LTLIBRARIES=libh5test.la libfilter_plugin1_dsets.la libfilter_plugin2_dsets.la libfilter_plugin3_dsets.la libfilter_plugin4_groups.la libnull_vol_connector.la
noinst_LTLIBRARIES=libh5test.la \
libfilter_plugin1_dsets.la libfilter_plugin2_dsets.la \
libfilter_plugin3_dsets.la libfilter_plugin4_groups.la \
libnull_vol_connector.la libjson_vol_connector.la
libfilter_plugin1_dsets_la_SOURCES=filter_plugin1_dsets.c
libfilter_plugin2_dsets_la_SOURCES=filter_plugin2_dsets.c
libfilter_plugin3_dsets_la_SOURCES=filter_plugin3_dsets.c
@@ -123,8 +126,11 @@ if HAVE_SHARED_CONDITIONAL
# VOL plugin test libraries
#
# null_vol_connector is used for testing basic VOL plugin functionality.
# json_vol_connector is used for testing non-native-HDF5 file storage.
libnull_vol_connector_la_SOURCES=null_vol_connector.c
libnull_vol_connector_la_LDFLAGS=$(AM_LDFLAGS) -avoid-version -module -shared -export-dynamic -rpath /nowhere
libjson_vol_connector_la_SOURCES=json_vol_connector.c
libjson_vol_connector_la_LDFLAGS=$(AM_LDFLAGS) -avoid-version -module -shared -export-dynamic -rpath /nowhere
else
# The libh5test library provides common support code for the tests.

349
test/json_vol.c Normal file
View File

@@ -0,0 +1,349 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* 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 COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Purpose: Tests basic JSON VOL connector operations.
*/
#include "h5test.h"
#include "json_vol_connector.h"
#define JSON_FILE_NAME "json_vol_test.json"
/*-------------------------------------------------------------------------
* Function: test_registration_by_value()
*
* Purpose: Tests if we can load, register, and close the VOL
* connector by value.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_registration_by_value(void)
{
htri_t is_registered = FAIL;
hid_t vol_id = H5I_INVALID_HID;
TESTING("VOL registration by value");
/* The null VOL connector should not be registered at the start of the test */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
/* Register the connector by value */
if((vol_id = H5VLregister_connector_by_value(JSON_VOL_CONNECTOR_VALUE, H5P_DEFAULT)) < 0)
TEST_ERROR;
/* The connector should be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(FALSE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector was not registered");
/* Unregister the connector */
if(H5VLunregister_connector(vol_id) < 0)
TEST_ERROR;
/* The connector should not be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
PASSED();
return SUCCEED;
error:
H5E_BEGIN_TRY {
H5VLunregister_connector(vol_id);
} H5E_END_TRY;
return FAIL;
} /* end test_registration_by_value() */
/*-------------------------------------------------------------------------
* Function: test_registration_by_name()
*
* Purpose: Tests if we can load, register, and close a VOL
* connector by name.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_registration_by_name(void)
{
htri_t is_registered = FAIL;
hid_t vol_id = H5I_INVALID_HID;
TESTING("VOL registration by name");
/* The null VOL connector should not be registered at the start of the test */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
/* Register the connector by name */
if((vol_id = H5VLregister_connector_by_name(JSON_VOL_CONNECTOR_NAME, H5P_DEFAULT)) < 0)
TEST_ERROR;
/* The connector should be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(FALSE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector was not registered");
/* Unregister the connector */
if(H5VLunregister_connector(vol_id) < 0)
TEST_ERROR;
/* The connector should not be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
PASSED();
return SUCCEED;
error:
H5E_BEGIN_TRY {
H5VLunregister_connector(vol_id);
} H5E_END_TRY;
return FAIL;
} /* end test_registration_by_name() */
/*-------------------------------------------------------------------------
* Function: test_multiple_registration()
*
* Purpose: Tests if we can register a VOL connector multiple times.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
#define N_REGISTRATIONS 10
static herr_t
test_multiple_registration(void)
{
htri_t is_registered = FAIL;
hid_t vol_ids[N_REGISTRATIONS];
int i;
TESTING("registering a VOL connector multiple times");
/* The null VOL connector should not be registered at the start of the test */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
/* Register the connector multiple times */
for(i = 0; i < N_REGISTRATIONS; i++) {
if((vol_ids[i] = H5VLregister_connector_by_name(JSON_VOL_CONNECTOR_NAME, H5P_DEFAULT)) < 0)
TEST_ERROR;
}
/* The connector should be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(FALSE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector was not registered");
/* Unregister the connector */
for(i = 0; i < N_REGISTRATIONS; i++) {
if(H5VLunregister_connector(vol_ids[i]) < 0)
TEST_ERROR;
/* Also test close on some of the IDs. This call currently works
* identically to unregister.
*/
i++;
if(H5VLclose(vol_ids[i]) < 0)
TEST_ERROR;
}
/* The connector should not be registered now */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
PASSED();
return SUCCEED;
error:
H5E_BEGIN_TRY {
for(i = 0; i < N_REGISTRATIONS; i++)
H5VLunregister_connector(vol_ids[i]);
} H5E_END_TRY;
return FAIL;
} /* end test_multiple_registration() */
/*-------------------------------------------------------------------------
* Function: test_getters()
*
* Purpose: Tests H5VL getters
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_getters(void)
{
htri_t is_registered = FAIL;
hid_t vol_id = H5I_INVALID_HID;
hid_t vol_id_out = H5I_INVALID_HID;
TESTING("VOL getters");
/* The null VOL connector should not be registered at the start of the test */
if((is_registered = H5VLis_connector_registered(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(TRUE == is_registered)
FAIL_PUTS_ERROR("JSON VOL connector is inappropriately registered");
/* Register the connector by name */
if((vol_id = H5VLregister_connector_by_name(JSON_VOL_CONNECTOR_NAME, H5P_DEFAULT)) < 0)
TEST_ERROR;
/* Get the connector's ID */
if((vol_id_out = H5VLget_connector_id(JSON_VOL_CONNECTOR_NAME)) < 0)
TEST_ERROR;
if(vol_id != vol_id_out)
FAIL_PUTS_ERROR("VOL connector IDs don't match");
/* Unregister the connector */
if(H5VLunregister_connector(vol_id) < 0)
TEST_ERROR;
PASSED();
return SUCCEED;
error:
H5E_BEGIN_TRY {
H5VLunregister_connector(vol_id);
} H5E_END_TRY;
return FAIL;
} /* end test_getters() */
/*-------------------------------------------------------------------------
* Function: test_file_operations()
*
* Purpose: Tests JSON file operations
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_file_operations(void)
{
hid_t vol_id = H5I_INVALID_HID;
hid_t fapl_id = H5I_INVALID_HID;
hid_t fid = H5I_INVALID_HID;
TESTING("File operations");
/* Register the connector by name */
if((vol_id = H5VLregister_connector_by_name(JSON_VOL_CONNECTOR_NAME, H5P_DEFAULT)) < 0)
TEST_ERROR;
/* Set the JSON VOL connector */
if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
TEST_ERROR;
if(H5Pset_vol(fapl_id, vol_id, NULL) < 0)
TEST_ERROR;
/* Create/open/close the file */
if((fid = H5Fcreate(JSON_FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
TEST_ERROR;
if(H5Fclose(fid) < 0)
TEST_ERROR;
if((fid = H5Fopen(JSON_FILE_NAME, H5F_ACC_RDWR, fapl_id)) < 0)
TEST_ERROR;
if(H5Fclose(fid) < 0)
TEST_ERROR;
/* Close remaining IDs */
if(H5Pclose(fapl_id) < 0)
TEST_ERROR;
/* Unregister the connector */
if(H5VLunregister_connector(vol_id) < 0)
TEST_ERROR;
PASSED();
return SUCCEED;
error:
H5E_BEGIN_TRY {
H5VLunregister_connector(vol_id);
H5Fclose(fid);
H5Pclose(fapl_id);
} H5E_END_TRY;
return FAIL;
} /* end test_getters() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests JSON VOL connector operations
*
* Return: EXIT_SUCCESS/EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
int nerrors = 0;
h5_reset();
HDputs("Testing JSON VOL connector functionality.");
nerrors += test_registration_by_name() < 0 ? 1 : 0;
nerrors += test_registration_by_value() < 0 ? 1 : 0;
nerrors += test_multiple_registration() < 0 ? 1 : 0;
nerrors += test_getters() < 0 ? 1 : 0;
nerrors += test_file_operations() < 0 ? 1 : 0;
if(nerrors) {
HDprintf("***** %d JSON VOL connector TEST%s FAILED! *****\n",
nerrors, nerrors > 1 ? "S" : "");
HDexit(EXIT_FAILURE);
}
HDputs("All JSON VOL connector tests passed.");
HDexit(EXIT_SUCCESS);
} /* end main() */

258
test/json_vol_connector.c Normal file
View File

@@ -0,0 +1,258 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* 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 COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Purpose: A virtual object layer (VOL) connector that uses JSON to
* store HDF5 data and metadata.
*
* The JSON representation is taken from hdf5-json, though
* that code can't be directly used because it's in Python.
* (https://github.com/HDFGroup/hdf5-json)
*/
#include "hdf5.h"
#include "H5PLextern.h"
#include "json_vol_connector.h"
/* XXX: Note that we're going to have to guard most of the JSON VOL
* connector content with #ifdefs in the final product...
*/
/* The Jansson JSON parser */
#include <jansson.h>
/* libuuid for generating UUIDs */
#include <uuid/uuid.h>
#define SUCCEED 0
#define FAIL (-1)
/* Callbacks */
/* File */
static void *jvc_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
static void *jvc_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
static herr_t jvc_file_close(void *file, hid_t dxpl_id, void **req);
/* The VOL class struct */
static const H5VL_class_t json_vol_g = {
JSON_VOL_CONNECTOR_VERSION, /* version */
JSON_VOL_CONNECTOR_VALUE, /* value */
JSON_VOL_CONNECTOR_NAME, /* name */
0, /* capability flags */
NULL, /* initialize */
NULL, /* terminate */
{ /* info_cls */
(size_t)0, /* info size */
NULL, /* info copy */
NULL, /* info compare */
NULL, /* info free */
NULL, /* info to str */
NULL /* str to info */
},
{ /* wrap_cls */
NULL, /* get_object */
NULL, /* get_wrap_ctx */
NULL, /* wrap_object */
NULL /* free_wrap_ctx */
},
{ /* attribute_cls */
NULL, /* create */
NULL, /* open */
NULL, /* read */
NULL, /* write */
NULL, /* get */
NULL, /* specific */
NULL, /* optional */
NULL /* close */
},
{ /* dataset_cls */
NULL, /* create */
NULL, /* open */
NULL, /* read */
NULL, /* write */
NULL, /* get */
NULL, /* specific */
NULL, /* optional */
NULL /* close */
},
{ /* datatype_cls */
NULL, /* commit */
NULL, /* open */
NULL, /* get_size */
NULL, /* specific */
NULL, /* optional */
NULL /* close */
},
{ /* file_cls */
jvc_file_create, /* create */
jvc_file_open, /* open */
NULL, /* get */
NULL, /* specific */
NULL, /* optional */
jvc_file_close /* close */
},
{ /* group_cls */
NULL, /* create */
NULL, /* open */
NULL, /* get */
NULL, /* specific */
NULL, /* optional */
NULL /* close */
},
{ /* link_cls */
NULL, /* create */
NULL, /* copy */
NULL, /* move */
NULL, /* get */
NULL, /* specific */
NULL /* optional */
},
{ /* object_cls */
NULL, /* open */
NULL, /* copy */
NULL, /* get */
NULL, /* specific */
NULL /* optional */
},
{ /* request_cls */
NULL, /* wait */
NULL, /* notify */
NULL, /* cancel */
NULL, /* specific */
NULL, /* optional */
NULL /* free */
},
NULL /* optional */
};
/* These two functions are necessary to load this plugin using
* the HDF5 library.
*/
H5PL_type_t H5PLget_plugin_type(void) {return H5PL_TYPE_VOL;}
const void *H5PLget_plugin_info(void) {return &json_vol_g;}
/******************/
/* IMPLEMENTATION */
/******************/
typedef struct json_vol_file_t {
FILE *fp; /* File pointer to JSON file */
json_t *root; /* Root of the JSON tree */
json_t *groups; /* JSON array of groups */
} json_vol_file_t;
#if 0
/* Helper functions */
static herr_t
jvc_helper_create_group(json_vol_file_t *jfile, char *group_name)
{
return SUCCEED;
} /* end jvc_helper_create_group() */
#endif
/* File callback implementation */
static void *
jvc_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req)
{
json_vol_file_t *jfile = NULL;
/* Set up */
if(NULL == (jfile = (json_vol_file_t *)calloc((size_t)1, sizeof(json_vol_file_t))))
goto error;
/* Create the file */
if(NULL == (jfile->fp = fopen(name, "w")))
goto error;
/* Create the JSON root */
jfile->root = json_object();
/* Add the groups array */
jfile->groups = json_array();
json_object_set_new(jfile->root, "groups", jfile->groups);
return (void *)jfile;
error:
if(jfile->fp)
fclose(jfile->fp);
if(jfile)
free(jfile);
return NULL;
} /* end jvc_file_create() */
static void *
jvc_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req)
{
json_vol_file_t *jfile = NULL;
char *json_in = NULL;
long int file_size;
json_error_t jerror;
/* Set up */
if(NULL == (jfile = (json_vol_file_t *)calloc((size_t)1, sizeof(json_vol_file_t))))
goto error;
/* Open the file and get the size */
if(NULL == (jfile->fp = fopen(name, "r")))
goto error;
fseek(jfile->fp, 0, SEEK_END);
file_size = ftell(jfile->fp);
fseek(jfile->fp, 0, SEEK_SET);
/* Create the JSON root */
if(NULL == (json_in = (char *)malloc((size_t)(file_size + 1) * sizeof(char))))
goto error;
fread(json_in, (size_t)file_size, 1, jfile->fp);
jfile->root = json_loads(json_in, 0, &jerror);
/* Will still need to parse out the groups array */
free(json_in);
return (void *)jfile;
error:
if(json_in)
free(json_in);
if(jfile->fp)
fclose(jfile->fp);
if(jfile)
free(jfile);
return NULL;
} /* end jvc_file_open() */
static herr_t
jvc_file_close(void *file, hid_t dxpl_id, void **req)
{
json_vol_file_t *jfile = (json_vol_file_t *)file;
/* Dump the JSON string to the file */
fprintf(jfile->fp, "%s", json_dumps(jfile->root, 0));
/* Close the file */
if(EOF == fclose(jfile->fp))
goto error;
/* Decrement the reference count on the JSON root, closing it */
json_decref(jfile->root);
/* Tear down */
free(jfile);
return SUCCEED;
error:
return FAIL;
} /* end jvc_file_close() */

27
test/json_vol_connector.h Normal file
View File

@@ -0,0 +1,27 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* 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 COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Purpose: A virtual object layer (VOL) connector that uses JSON to
* store HDF5 data and metadata.
*/
#ifndef _json_vol_connector_H
#define _json_vol_connector_H
#include "hdf5.h"
#define JSON_VOL_CONNECTOR_VERSION 1
#define JSON_VOL_CONNECTOR_VALUE ((H5VL_class_value_t)104)
#define JSON_VOL_CONNECTOR_NAME "json_vol_connector"
#endif /* _json_vol_connector_H */

84
test/test_json_vol.sh.in Normal file
View File

@@ -0,0 +1,84 @@
#! /bin/sh
#
# Copyright by The HDF Group.
# 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 COPYING file, which can be found at the root of the source code
# distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
# If you do not have access to either file, you may request a copy from
# help@hdfgroup.org.
#
# This shell script is for testing basic JSON VOL operations.
#
srcdir=@srcdir@
TOP_BUILDDIR=@top_builddir@
EXIT_SUCCESS=0
EXIT_FAILURE=1
nerrors=0
verbose=yes
exit_code=$EXIT_SUCCESS
TEST_NAME=json_vol
TEST_BIN=`pwd`/$TEST_NAME
FROM_DIR=`pwd`/.libs
case $(uname) in
CYGWIN* )
JSON_VOL_PLUGIN="$FROM_DIR/cygjson_vol_connector*"
;;
*)
JSON_VOL_PLUGIN="$FROM_DIR/libjson_vol_connector*"
;;
esac
TEMP_PLUGIN_DIR=json_vol_plugin_dir
CP="cp -p" # Use -p to preserve mode,ownership, timestamps
RM="rm -rf"
# 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'
}
# Main Body
# Create test directory if necessary.
test -d $TEMP_PLUGIN_DIR || mkdir -p $TEMP_PLUGIN_DIR
if [ $? != 0 ]; then
echo "Failed to create VOL connector plugin test directory ($TEMP_PLUGIN_DIR)"
exit $EXIT_FAILURE
fi
# Copy plugin for the tests.
$CP $JSON_VOL_PLUGIN $TEMP_PLUGIN_DIR
if [ $? != 0 ]; then
echo "Failed to copy JSON VOL plugin ($JSON_VOL_PLUGIN) to test directory."
exit $EXIT_FAILURE
fi
# setup plugin path
ENVCMD="env HDF5_PLUGIN_PATH=${TEMP_PLUGIN_DIR}"
# Run the test
$ENVCMD $TEST_BIN
if [ $? != 0 ]; then
nerrors=`expr $nerrors + 1`
fi
# print results
if test $nerrors -ne 0 ; then
echo "$nerrors errors encountered"
exit_code=$EXIT_FAILURE
else
echo "All JSON VOL plugin tests passed."
exit_code=$EXIT_SUCCESS
fi
# Clean up temporary files/directories and leave
$RM $TEMP_PLUGIN_DIR
exit $exit_code