From 238a207f2dedb9b4e5a33e6701a96e3ab055895d Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 28 Nov 2018 10:26:03 -0600 Subject: Add pass-through VOL connector --- MANIFEST | 2 + src/CMakeLists.txt | 2 + src/H5VLpassthru.c | 3061 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5VLpassthru.h | 46 + src/Makefile.am | 4 +- src/hdf5.h | 5 +- 6 files changed, 3116 insertions(+), 4 deletions(-) create mode 100644 src/H5VLpassthru.c create mode 100644 src/H5VLpassthru.h diff --git a/MANIFEST b/MANIFEST index 4342d97..c24fb32 100644 --- a/MANIFEST +++ b/MANIFEST @@ -896,6 +896,8 @@ ./src/H5VLnative.c ./src/H5VLnative.h ./src/H5VLnative_private.h +./src/H5VLpassthru.c +./src/H5VLpassthru.h ./src/H5VLpkg.h ./src/H5VLprivate.h ./src/H5VLpublic.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1193b8..80b26ff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -628,9 +628,11 @@ set (H5VL_SOURCES ${HDF5_SRC_DIR}/H5VLcallback.c ${HDF5_SRC_DIR}/H5VLint.c ${HDF5_SRC_DIR}/H5VLnative.c + ${HDF5_SRC_DIR}/H5VLpassthru.c ) set (H5VL_HDRS ${HDF5_SRC_DIR}/H5VLnative.h + ${HDF5_SRC_DIR}/H5VLpassthru.h ${HDF5_SRC_DIR}/H5VLpublic.h ) IDE_GENERATED_PROPERTIES ("H5VL" "${H5VL_HDRS}" "${H5VL_SOURCES}" ) diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c new file mode 100644 index 0000000..3181834 --- /dev/null +++ b/src/H5VLpassthru.c @@ -0,0 +1,3061 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: This is a "pass through" VOL connector, which forwards each + * VOL callback to an underlying connector. + * + * It is designed as an example VOL connector for developers to + * use when creating new connectors, especially connectors that + * are outside of the HDF5 library. As such, it should _NOT_ + * include _any_ private HDF5 header files. This connector should + * therefore only make public HDF5 API calls and use standard C / + * POSIX calls. + */ + + +/* Header files needed */ +/* (Public HDF5 and standard C / POSIX only) */ +#include +#include +#include +#include +#include "hdf5.h" +#include "H5VLpassthru.h" + + +/**********/ +/* Macros */ +/**********/ + +/* Whether to display log messge when callback is invoked */ +/* (Uncomment to enable) */ +/* #define ENABLE_LOGGING */ + + +/************/ +/* Typedefs */ +/************/ + +/* The pass through VOL info object */ +typedef struct H5VL_pass_through_t { + hid_t under_vol_id; /* ID for underlying VOL connector */ + void *under_object; /* Info object for underlying VOL connector */ +} H5VL_pass_through_t; + +/* The pass through VOL wrapper context */ +typedef struct H5VL_pass_through_wrap_ctx_t { + hid_t under_vol_id; /* VOL ID for under VOL */ + void *under_wrap_ctx; /* Object wrapping context for under VOL */ +} H5VL_pass_through_wrap_ctx_t; + + +/********************* */ +/* Function prototypes */ +/********************* */ + +/* "Management" callbacks */ +static herr_t H5VL_pass_through_init(hid_t vipl_id); +static herr_t H5VL_pass_through_term(void); +static void *H5VL_pass_through_info_copy(const void *info); +static herr_t H5VL_pass_through_info_cmp(int *cmp_value, const void *info1, const void *info2); +static herr_t H5VL_pass_through_info_free(void *info); +static herr_t H5VL_pass_through_info_to_str(const void *info, char **str); +static herr_t H5VL_pass_through_str_to_info(const char *str, void **info); +static void *H5VL_pass_through_get_object(const void *obj); +static herr_t H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx); +static herr_t H5VL_pass_through_free_wrap_ctx(void *obj); +static void *H5VL_pass_through_wrap_object(void *obj, void *wrap_ctx); + +/* Attribute callbacks */ +static void *H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); +static void *H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_attr_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req); + +/* Dataset callbacks */ +static void *H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req); +static void *H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t dapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, void *buf, void **req); +static herr_t H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf, void **req); +static herr_t H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_dataset_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req); + +/* Datatype callbacks */ +static void *H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); +static void *H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_datatype_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req); + +/* File callbacks */ +static void *H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req); +static void *H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_file_optional(void *file, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req); + +/* Group callbacks */ +static void *H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); +static void *H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_group_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req); + +/* Link callbacks */ +static herr_t H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_link_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); + +/* Object callbacks */ +static void *H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params, const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_pass_through_object_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments); + +/* Async request callbacks */ +static herr_t H5VL_pass_through_request_wait(void *req, uint64_t timeout, H5ES_status_t *status); +static herr_t H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx); +static herr_t H5VL_pass_through_request_cancel(void *req); +static herr_t H5VL_pass_through_request_specific(void *req, H5VL_request_specific_t specific_type, va_list arguments); +static herr_t H5VL_pass_through_request_optional(void *req, va_list arguments); +static herr_t H5VL_pass_through_request_free(void *req); + +/*******************/ +/* Local variables */ +/*******************/ + +/* Pass through VOL connector class struct */ +static const H5VL_class_t H5VL_pass_through_g = { + H5VL_PASSTHRU_VERSION, /* version */ + (H5VL_class_value_t)H5VL_PASSTHRU_VALUE, /* value */ + H5VL_PASSTHRU_NAME, /* name */ + 0, /* capability flags */ + H5VL_pass_through_init, /* initialize */ + H5VL_pass_through_term, /* terminate */ + sizeof(H5VL_pass_through_t), /* info size */ + H5VL_pass_through_info_copy, /* info copy */ + H5VL_pass_through_info_cmp, /* info compare */ + H5VL_pass_through_info_free, /* info free */ + H5VL_pass_through_info_to_str, /* info to str */ + H5VL_pass_through_str_to_info, /* str to info */ + H5VL_pass_through_get_object, /* get_object */ + H5VL_pass_through_get_wrap_ctx, /* get_wrap_ctx */ + H5VL_pass_through_wrap_object, /* wrap_object */ + H5VL_pass_through_free_wrap_ctx, /* free_wrap_ctx */ + { /* attribute_cls */ + H5VL_pass_through_attr_create, /* create */ + H5VL_pass_through_attr_open, /* open */ + H5VL_pass_through_attr_read, /* read */ + H5VL_pass_through_attr_write, /* write */ + H5VL_pass_through_attr_get, /* get */ + H5VL_pass_through_attr_specific, /* specific */ + H5VL_pass_through_attr_optional, /* optional */ + H5VL_pass_through_attr_close /* close */ + }, + { /* dataset_cls */ + H5VL_pass_through_dataset_create, /* create */ + H5VL_pass_through_dataset_open, /* open */ + H5VL_pass_through_dataset_read, /* read */ + H5VL_pass_through_dataset_write, /* write */ + H5VL_pass_through_dataset_get, /* get */ + H5VL_pass_through_dataset_specific, /* specific */ + H5VL_pass_through_dataset_optional, /* optional */ + H5VL_pass_through_dataset_close /* close */ + }, + { /* datatype_cls */ + H5VL_pass_through_datatype_commit, /* commit */ + H5VL_pass_through_datatype_open, /* open */ + H5VL_pass_through_datatype_get, /* get_size */ + H5VL_pass_through_datatype_specific, /* specific */ + H5VL_pass_through_datatype_optional, /* optional */ + H5VL_pass_through_datatype_close /* close */ + }, + { /* file_cls */ + H5VL_pass_through_file_create, /* create */ + H5VL_pass_through_file_open, /* open */ + H5VL_pass_through_file_get, /* get */ + H5VL_pass_through_file_specific, /* specific */ + H5VL_pass_through_file_optional, /* optional */ + H5VL_pass_through_file_close /* close */ + }, + { /* group_cls */ + H5VL_pass_through_group_create, /* create */ + H5VL_pass_through_group_open, /* open */ + H5VL_pass_through_group_get, /* get */ + H5VL_pass_through_group_specific, /* specific */ + H5VL_pass_through_group_optional, /* optional */ + H5VL_pass_through_group_close /* close */ + }, + { /* link_cls */ + H5VL_pass_through_link_create, /* create */ + H5VL_pass_through_link_copy, /* copy */ + H5VL_pass_through_link_move, /* move */ + H5VL_pass_through_link_get, /* get */ + H5VL_pass_through_link_specific, /* specific */ + H5VL_pass_through_link_optional, /* optional */ + }, + { /* object_cls */ + H5VL_pass_through_object_open, /* open */ + H5VL_pass_through_object_copy, /* copy */ + H5VL_pass_through_object_get, /* get */ + H5VL_pass_through_object_specific, /* specific */ + H5VL_pass_through_object_optional, /* optional */ + }, + { /* request_cls */ + H5VL_pass_through_request_wait, /* wait */ + H5VL_pass_through_request_notify, /* notify */ + H5VL_pass_through_request_cancel, /* cancel */ + H5VL_pass_through_request_specific, /* specific */ + H5VL_pass_through_request_optional, /* optional */ + H5VL_pass_through_request_free /* free */ + }, + NULL /* optional */ +}; + +/* The connector identification number, initialized at runtime */ +static hid_t H5VL_PASSTHRU_g = 0; + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_register + * + * Purpose: Register the pass-through VOL connector and retrieve an ID + * for it. + * + * Return: Success: The ID for the pass-through VOL connector + * Failure: -1 + * + * Programmer: Quincey Koziol + * Wednesday, November 28, 2018 + * + *------------------------------------------------------------------------- + */ +hid_t +H5VL_pass_through_register(void) +{ + /* Clear the error stack */ + H5Eclear2(H5E_DEFAULT); + + /* Singleton register the pass-through VOL connector ID */ + if(H5I_VOL != H5Iget_type(H5VL_PASSTHRU_g)) + H5VL_PASSTHRU_g = H5VLregister_connector(&H5VL_pass_through_g, H5P_DEFAULT); + + return(H5VL_PASSTHRU_g); +} /* end H5VL_pass_through_register() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_init + * + * Purpose: Initialize this VOL connector, performing any necessary + * operations for the connector that will apply to all containers + * accessed with the connector. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_init(hid_t vipl_id) +{ +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INIT\n"); +#endif + + /* Shut compiler up about unused parameter */ + vipl_id = vipl_id; + + return(0); +} /* end H5VL_pass_through_init() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_term + * + * Purpose: Terminate this VOL connector, performing any necessary + * operations for the connector that release connector-wide + * resources (usually created / initialized with the 'init' + * callback). + * + * Return: Success: 0 + * Failure: (Can't fail) + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_term(void) +{ +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL TERM\n"); +#endif + + /* Reset VOL ID */ + H5VL_PASSTHRU_g = 0; + + return(0); +} /* end H5VL_pass_through_term() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_info_copy + * + * Purpose: Duplicate the connector's info object. + * + * Returns: Success: New connector info object + * Failure: NULL + * + *--------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_info_copy(const void *_info) +{ + const H5VL_pass_through_info_t *info = (const H5VL_pass_through_info_t *)_info; + H5VL_pass_through_info_t *new_info; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INFO Copy\n"); +#endif + + /* Allocate new VOL info struct for the pass through connector */ + new_info = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t)); + + /* Increment reference count on underlying VOL ID, and copy the VOL info */ + new_info->under_vol_id = info->under_vol_id; + H5Iinc_ref(new_info->under_vol_id); + if(info->under_vol_info) + H5VLcopy_connector_info(new_info->under_vol_id, &(new_info->under_vol_info), info->under_vol_info); + + return(new_info); +} /* end H5VL_pass_through_info_copy() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_info_cmp + * + * Purpose: Compare two of the connector's info objects, setting *cmp_value, + * following the same rules as strcmp(). + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_info_cmp(int *cmp_value, const void *_info1, const void *_info2) +{ + const H5VL_pass_through_info_t *info1 = (const H5VL_pass_through_info_t *)_info1; + const H5VL_pass_through_info_t *info2 = (const H5VL_pass_through_info_t *)_info2; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INFO Compare\n"); +#endif + + /* Sanity checks */ + assert(info1); + assert(info2); + + /* Initialize comparison value */ + *cmp_value = 0; + + /* Compare under VOL connector classes */ + H5VLcmp_connector_cls(cmp_value, info1->under_vol_id, info2->under_vol_id); + if(*cmp_value != 0) + return(0); + + /* Compare under VOL connector info objects */ + H5VLcmp_connector_info(cmp_value, info1->under_vol_id, info1->under_vol_info, info2->under_vol_info); + if(*cmp_value != 0) + return(0); + + return(0); +} /* end H5VL_pass_through_info_cmp() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_info_free + * + * Purpose: Release an info object for the connector. + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_info_free(void *_info) +{ + H5VL_pass_through_info_t *info = (H5VL_pass_through_info_t *)_info; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INFO Free\n"); +#endif + + /* Release underlying VOL ID and info */ + if(info->under_vol_info) + H5VLfree_connector_info(info->under_vol_id, info->under_vol_info); + H5Idec_ref(info->under_vol_id); + + /* Free pass through info object itself */ + free(info); + + return(0); +} /* end H5VL_pass_through_info_free() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_info_to_str + * + * Purpose: Serialize an info object for this connector into a string + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_info_to_str(const void *_info, char **str) +{ + const H5VL_pass_through_info_t *info = (const H5VL_pass_through_info_t *)_info; + H5VL_class_value_t under_value = (H5VL_class_value_t)-1; + char *under_vol_string = NULL; + size_t under_vol_str_len = 0; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INFO To String\n"); +#endif + + /* Get value and string for underlying VOL connector */ + H5VLget_value(info->under_vol_id, &under_value); + H5VLconnector_info_to_str(info->under_vol_info, info->under_vol_id, &under_vol_string); + + /* Determine length of underlying VOL info string */ + if(under_vol_string) + under_vol_str_len = strlen(under_vol_string); + + /* Allocate space for our info */ + *str = (char *)H5allocate_memory(32 + under_vol_str_len, (hbool_t)0); + assert(*str); + + /* Encode our info */ + snprintf(*str, 32 + under_vol_str_len, "under_val=%u, under_info={%s}", (unsigned)under_value, (under_vol_string ? under_vol_string : "")); + + return(0); +} /* end H5VL_pass_through_info_to_str() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_str_to_info + * + * Purpose: Deserialize a string into an info object for this connector. + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_str_to_info(const char *str, void **_info) +{ + H5VL_pass_through_info_t *info; + unsigned under_vol_value; + const char *under_vol_info_start, *under_vol_info_end; + hid_t under_vol_id; + void *under_vol_info = NULL; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL INFO String To Info\n"); +#endif + + /* Retrieve the underlying VOL connector value and info */ + sscanf(str, "under_vol=%u,", &under_vol_value); + under_vol_id = H5VLregister_connector_by_value((H5VL_class_value_t)under_vol_value, H5P_DEFAULT); + under_vol_info_start = strchr(str, '{'); + under_vol_info_end = strrchr(str, '}'); + assert(under_vol_info_end > under_vol_info_start); + if(under_vol_info_end != (under_vol_info_start + 1)) { + char *under_vol_info_str; + + under_vol_info_str = (char *)malloc((size_t)(under_vol_info_end - under_vol_info_start)); + memcpy(under_vol_info_str, under_vol_info_start + 1, (size_t)((under_vol_info_end - under_vol_info_start) - 1)); + *(under_vol_info_str + (under_vol_info_end - under_vol_info_start)) = '\0'; + + H5VLconnector_str_to_info(under_vol_info_str, under_vol_id, &under_vol_info); + + free(under_vol_info_str); + } /* end else */ + + /* Allocate new pass-through VOL connector info and set its fields */ + info = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t)); + info->under_vol_id = under_vol_id; + info->under_vol_info = under_vol_info; + + /* Set return value */ + *_info = info; + + return(0); +} /* end H5VL_pass_through_str_to_info() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_get_object + * + * Purpose: Retrieve the 'data' for a VOL object. + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_get_object(const void *obj) +{ + const H5VL_pass_through_t *o = (const H5VL_pass_through_t *)obj; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL Get object\n"); +#endif + + return(H5VLget_object(o->under_object, o->under_vol_id)); +} /* end H5VL_pass_through_get_object() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_get_wrap_ctx + * + * Purpose: Retrieve a "wrapper context" for an object + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx) +{ + const H5VL_pass_through_t *o = (const H5VL_pass_through_t *)obj; + H5VL_pass_through_wrap_ctx_t *new_wrap_ctx; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL WRAP CTX Get\n"); +#endif + + /* Allocate new VOL object wrapping context for the pass through connector */ + new_wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)calloc(1, sizeof(H5VL_pass_through_wrap_ctx_t)); + + /* Increment reference count on underlying VOL ID, and copy the VOL info */ + new_wrap_ctx->under_vol_id = o->under_vol_id; + H5Iinc_ref(new_wrap_ctx->under_vol_id); + H5VLget_wrap_ctx(o->under_object, o->under_vol_id, &new_wrap_ctx->under_wrap_ctx); + + /* Set wrap context to return */ + *wrap_ctx = new_wrap_ctx; + + return(0); +} /* end H5VL_pass_through_get_wrap_ctx() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_wrap_object + * + * Purpose: Use a "wrapper context" to wrap a data object + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_wrap_object(void *obj, void *_wrap_ctx) +{ + H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx; + H5VL_pass_through_t *new_obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL WRAP Object\n"); +#endif + + /* Wrap the object with the underlying VOL */ + under = H5VLwrap_object(obj, wrap_ctx->under_vol_id, wrap_ctx->under_wrap_ctx); + if(under) { + new_obj = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + new_obj->under_object = under; + new_obj->under_vol_id = wrap_ctx->under_vol_id; + H5Iinc_ref(new_obj->under_vol_id); + } /* end if */ + else + new_obj = NULL; + + return(new_obj); +} /* end H5VL_pass_through_wrap_object() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_free_wrap_ctx + * + * Purpose: Release a "wrapper context" for an object + * + * Return: Success: 0 + * Failure: -1 + * + *--------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_free_wrap_ctx(void *_wrap_ctx) +{ + H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL WRAP CTX Free\n"); +#endif + + /* Release underlying VOL ID and wrap context */ + if(wrap_ctx->under_wrap_ctx) + H5VLfree_wrap_ctx(wrap_ctx->under_wrap_ctx, wrap_ctx->under_vol_id); + H5Idec_ref(wrap_ctx->under_vol_id); + + /* Free pass through wrap context object itself */ + free(wrap_ctx); + + return(0); +} /* end H5VL_pass_through_free_wrap_ctx() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_create + * + * Purpose: Creates an attribute on an object. + * + * Return: Success: Pointer to attribute object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *attr; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Create\n"); +#endif + + under = H5VLattr_create(o->under_object, loc_params, o->under_vol_id, name, acpl_id, aapl_id, dxpl_id, req); + if(under) { + attr = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + attr->under_object = under; + attr->under_vol_id = o->under_vol_id; + H5Iinc_ref(attr->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + attr = NULL; + + return((void*)attr); +} /* end H5VL_pass_through_attr_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_open + * + * Purpose: Opens an attribute on an object. + * + * Return: Success: Pointer to attribute object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t aapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *attr; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Open\n"); +#endif + + under = H5VLattr_open(o->under_object, loc_params, o->under_vol_id, name, aapl_id, dxpl_id, req); + if(under) { + attr = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + attr->under_object = under; + attr->under_vol_id = o->under_vol_id; + H5Iinc_ref(attr->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + attr = NULL; + + return((void *)attr); +} /* end H5VL_pass_through_attr_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_read + * + * Purpose: Reads data from attribute. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf, + hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Read\n"); +#endif + + ret_value = H5VLattr_read(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_attr_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_write + * + * Purpose: Writes data to attribute. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf, + hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Write\n"); +#endif + + ret_value = H5VLattr_write(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_attr_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_get + * + * Purpose: Gets information about an attribute + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, + void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Get\n"); +#endif + + ret_value = H5VLattr_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_attr_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_specific + * + * Purpose: Specific operation on attribute + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, + H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Specific\n"); +#endif + + ret_value = H5VLattr_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return ret_value; +} /* end H5VL_pass_through_attr_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_optional + * + * Purpose: Perform a connector-specific operation on an attribute + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Optional\n"); +#endif + + ret_value = H5VLattr_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return ret_value; +} /* end H5VL_pass_through_attr_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_attr_close + * + * Purpose: Closes an attribute. + * + * Return: Success: 0 + * Failure: -1, attr not closed. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL ATTRIBUTE Close\n"); +#endif + + ret_value = H5VLattr_close(o->under_object, o->under_vol_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + /* Release our wrapper, if underlying attribute was closed */ + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_attr_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_create + * + * Purpose: Creates a dataset in a container + * + * Return: Success: Pointer to a dataset object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *dset; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Create\n"); +#endif + + under = H5VLdataset_create(o->under_object, loc_params, o->under_vol_id, name, dcpl_id, dapl_id, dxpl_id, req); + if(under) { + dset = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + dset->under_object = under; + dset->under_vol_id = o->under_vol_id; + H5Iinc_ref(dset->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + dset = NULL; + + return((void *)dset); +} /* end H5VL_pass_through_dataset_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_open + * + * Purpose: Opens a dataset in a container + * + * Return: Success: Pointer to a dataset object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t dapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *dset; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Open\n"); +#endif + + under = H5VLdataset_open(o->under_object, loc_params, o->under_vol_id, name, dapl_id, dxpl_id, req); + if(under) { + dset = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + dset->under_object = under; + dset->under_vol_id = o->under_vol_id; + H5Iinc_ref(dset->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + dset = NULL; + + return((void *)dset); +} /* end H5VL_pass_through_dataset_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_read + * + * Purpose: Reads data elements from a dataset into a buffer. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, void *buf, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Read\n"); +#endif + + ret_value = H5VLdataset_read(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id, plist_id, buf, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_dataset_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_write + * + * Purpose: Writes data elements from a buffer into a dataset. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, const void *buf, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Write\n"); +#endif + + ret_value = H5VLdataset_write(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id, plist_id, buf, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return ret_value; +} /* end H5VL_pass_through_dataset_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_get + * + * Purpose: Gets information about a dataset + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Get\n"); +#endif + + ret_value = H5VLdataset_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return ret_value; +} /* end H5VL_pass_through_dataset_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_specific + * + * Purpose: Specific operation on a dataset + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL H5Dspecific\n"); +#endif + + ret_value = H5VLdataset_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + return ret_value; +} /* end H5VL_pass_through_dataset_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_optional + * + * Purpose: Perform a connector-specific operation on a dataset + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Optional\n"); +#endif + + ret_value = H5VLdataset_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + return(ret_value); +} /* end H5VL_pass_through_dataset_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_dataset_close + * + * Purpose: Closes a dataset. + * + * Return: Success: 0 + * Failure: -1, dataset not closed. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATASET Close\n"); +#endif + + ret_value = H5VLdataset_close(o->under_object, o->under_vol_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + /* Release our wrapper, if underlying dataset was closed */ + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_dataset_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_commit + * + * Purpose: Commits a datatype inside a container. + * + * Return: Success: Pointer to datatype object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, + hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *dt; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Commit\n"); +#endif + + under = H5VLdatatype_commit(o->under_object, loc_params, o->under_vol_id, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req); + if(under) { + dt = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + dt->under_object = under; + dt->under_vol_id = o->under_vol_id; + H5Iinc_ref(dt->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + dt = NULL; + + return((void *)dt); +} /* end H5VL_pass_through_datatype_commit() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_open + * + * Purpose: Opens a named datatype inside a container. + * + * Return: Success: Pointer to datatype object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t tapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *dt; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Open\n"); +#endif + + under = H5VLdatatype_open(o->under_object, loc_params, o->under_vol_id, name, tapl_id, dxpl_id, req); + if(under) { + dt = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + dt->under_object = under; + dt->under_vol_id = o->under_vol_id; + H5Iinc_ref(dt->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + dt = NULL; + + return((void *)dt); +} /* end H5VL_pass_through_datatype_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_get + * + * Purpose: Get information about a datatype + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Get\n"); +#endif + + ret_value = H5VLdatatype_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + return(ret_value); +} /* end H5VL_pass_through_datatype_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_specific + * + * Purpose: Specific operations for datatypes + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Specific\n"); +#endif + + ret_value = H5VLdatatype_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + return(ret_value); +} /* end H5VL_pass_through_datatype_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_optional + * + * Purpose: Perform a connector-specific operation on a datatype + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_datatype_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Optional\n"); +#endif + + ret_value = H5VLdatatype_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + return(ret_value); +} /* end H5VL_pass_through_datatype_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_datatype_close + * + * Purpose: Closes a datatype. + * + * Return: Success: 0 + * Failure: -1, datatype not closed. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL DATATYPE Close\n"); +#endif + + assert(o->under_object); + + ret_value = H5VLdatatype_close(o->under_object, o->under_vol_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } + + /* Release our wrapper, if underlying datatype was closed */ + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_datatype_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_create + * + * Purpose: Creates a container using this connector + * + * Return: Success: Pointer to a file object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id, + hid_t fapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_info_t *info; + H5VL_pass_through_t *file; + hid_t under_fapl_id; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL FILE Create\n"); +#endif + + /* Get copy of our VOL info from FAPL */ + H5Pget_vol_info(fapl_id, (void **)&info); + + /* Copy the FAPL */ + under_fapl_id = H5Pcopy(fapl_id); + + /* Set the VOL ID and info for the underlying FAPL */ + H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info); + + /* Open the file with the underlying VOL connector */ + under = H5VLfile_create(name, flags, fcpl_id, under_fapl_id, dxpl_id, req); + if(under) { + file = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + file->under_object = under; + file->under_vol_id = info->under_vol_id; + H5Iinc_ref(file->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = info->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + file = NULL; + + /* Close underlying FAPL */ + H5Pclose(under_fapl_id); + + /* Release copy of our VOL info */ + H5VL_pass_through_info_free(info); + + return((void *)file); +} /* end H5VL_pass_through_file_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_open + * + * Purpose: Opens a container created with this connector + * + * Return: Success: Pointer to a file object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id, + hid_t dxpl_id, void **req) +{ + H5VL_pass_through_info_t *info; + H5VL_pass_through_t *file; + hid_t under_fapl_id; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL FILE Open\n"); +#endif + + /* Get copy of our VOL info from FAPL */ + H5Pget_vol_info(fapl_id, (void **)&info); + + /* Copy the FAPL */ + under_fapl_id = H5Pcopy(fapl_id); + + /* Set the VOL ID and info for the underlying FAPL */ + H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info); + + /* Open the file with the underlying VOL connector */ + under = H5VLfile_open(name, flags, under_fapl_id, dxpl_id, req); + if(under) { + file = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + file->under_object = under; + file->under_vol_id = info->under_vol_id; + H5Iinc_ref(file->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = info->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + file = NULL; + + /* Close underlying FAPL */ + H5Pclose(under_fapl_id); + + /* Release copy of our VOL info */ + H5VL_pass_through_info_free(info); + + return((void *)file); +} /* end H5VL_pass_through_file_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_get + * + * Purpose: Get info about a file + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, + void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)file; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL FILE Get\n"); +#endif + + ret_value = H5VLfile_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_file_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_specific_reissue + * + * Purpose: Re-wrap vararg arguments into a va_list and reissue the + * file specific callback to the underlying VOL connector. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_file_specific_reissue(void *obj, hid_t connector_id, + H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...) +{ + va_list arguments; + herr_t ret_value; + + va_start(arguments, req); + ret_value = H5VLfile_specific(obj, connector_id, specific_type, dxpl_id, req, arguments); + va_end(arguments); + + return(ret_value); +} /* end H5VL_pass_through_file_specific_reissue() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_specific + * + * Purpose: Specific operation on file + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)file; + hid_t under_vol_id = -1; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL FILE Specific\n"); +#endif + + /* Unpack arguments to get at the child file pointer when mounting a file */ + if(specific_type == H5VL_FILE_MOUNT) { + H5I_type_t loc_type; + const char *name; + H5VL_pass_through_t *child_file; + hid_t plist_id; + + /* Retrieve parameters for 'mount' operation, so we can unwrap the child file */ + loc_type = va_arg(arguments, H5I_type_t); + name = va_arg(arguments, const char *); + child_file = (H5VL_pass_through_t *)va_arg(arguments, void *); + plist_id = va_arg(arguments, hid_t); + + /* Keep the correct underlying VOL ID for possible async request token */ + under_vol_id = o->under_vol_id; + + /* Re-issue 'file specific' call, using the unwrapped pieces */ + ret_value = H5VL_pass_through_file_specific_reissue(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, loc_type, name, child_file->under_object, plist_id); + } /* end if */ + else if(specific_type == H5VL_FILE_IS_ACCESSIBLE) { + H5VL_pass_through_info_t *info; + hid_t fapl_id, under_fapl_id; + const char *name; + htri_t *ret; + + /* Get the arguments for the 'is accessible' check */ + fapl_id = va_arg(arguments, hid_t); + name = va_arg(arguments, const char *); + ret = va_arg(arguments, htri_t *); + + /* Get copy of our VOL info from FAPL */ + H5Pget_vol_info(fapl_id, (void **)&info); + + /* Copy the FAPL */ + under_fapl_id = H5Pcopy(fapl_id); + + /* Set the VOL ID and info for the underlying FAPL */ + H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info); + + /* Keep the correct underlying VOL ID for possible async request token */ + under_vol_id = info->under_vol_id; + + /* Re-issue 'file specific' call */ + ret_value = H5VL_pass_through_file_specific_reissue(NULL, info->under_vol_id, specific_type, dxpl_id, req, under_fapl_id, name, ret); + + /* Close underlying FAPL */ + H5Pclose(under_fapl_id); + + /* Release copy of our VOL info */ + H5VL_pass_through_info_free(info); + } /* end else-if */ + else { + va_list my_arguments; + + /* Make a copy of the argument list for later, if reopening */ + if(specific_type == H5VL_FILE_REOPEN) + va_copy(my_arguments, arguments); + + /* Keep the correct underlying VOL ID for possible async request token */ + under_vol_id = o->under_vol_id; + + ret_value = H5VLfile_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Wrap file struct pointer, if we reopened one */ + if(specific_type == H5VL_FILE_REOPEN) { + if(ret_value >= 0) { + void **ret = va_arg(my_arguments, void **); + + if(ret && *ret) { + H5VL_pass_through_t *new_file; + + new_file = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + new_file->under_object = *ret; + new_file->under_vol_id = o->under_vol_id; + H5Iinc_ref(new_file->under_vol_id); + + *ret = new_file; + } /* end if */ + } /* end if */ + + /* Finish use of copied vararg list */ + va_end(my_arguments); + } /* end if */ + } /* end else */ + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + assert(under_vol_id); + r->under_vol_id = under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_file_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_optional + * + * Purpose: Perform a connector-specific operation on a file + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_file_optional(void *file, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)file; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL File Optional\n"); +#endif + + ret_value = H5VLfile_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_file_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_file_close + * + * Purpose: Closes a file. + * + * Return: Success: 0 + * Failure: -1, file not closed. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)file; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL FILE Close\n"); +#endif + + ret_value = H5VLfile_close(o->under_object, o->under_vol_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + /* Release our wrapper, if underlying file was closed */ + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_file_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_create + * + * Purpose: Creates a group inside a container + * + * Return: Success: Pointer to a group object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *group; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL GROUP Create\n"); +#endif + + under = H5VLgroup_create(o->under_object, loc_params, o->under_vol_id, name, gcpl_id, gapl_id, dxpl_id, req); + if(under) { + group = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + group->under_object = under; + group->under_vol_id = o->under_vol_id; + H5Iinc_ref(group->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + group = NULL; + + return((void *)group); +} /* end H5VL_pass_through_group_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_open + * + * Purpose: Opens a group inside a container + * + * Return: Success: Pointer to a group object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params, + const char *name, hid_t gapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *group; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL GROUP Open\n"); +#endif + + under = H5VLgroup_open(o->under_object, loc_params, o->under_vol_id, name, gapl_id, dxpl_id, req); + if(under) { + group = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + group->under_object = under; + group->under_vol_id = o->under_vol_id; + H5Iinc_ref(group->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + group = NULL; + + return((void *)group); +} /* end H5VL_pass_through_group_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_get + * + * Purpose: Get info about a group + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, + void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL GROUP Get\n"); +#endif + + ret_value = H5VLgroup_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_group_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_specific + * + * Purpose: Specific operation on a group + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL GROUP Specific\n"); +#endif + + ret_value = H5VLgroup_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_group_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_optional + * + * Purpose: Perform a connector-specific operation on a group + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_group_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL GROUP Optional\n"); +#endif + + ret_value = H5VLgroup_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_group_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_group_close + * + * Purpose: Closes a group. + * + * Return: Success: 0 + * Failure: -1, group not closed. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)grp; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL H5Gclose\n"); +#endif + + ret_value = H5VLgroup_close(o->under_object, o->under_vol_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + /* Release our wrapper, if underlying file was closed */ + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_group_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_link_create + * + * Purpose: Creates a hard / soft / UD / external link. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + hid_t under_vol_id = -1; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Create\n"); +#endif + + /* Try to retrieve the "under" VOL id */ + if(o) + under_vol_id = o->under_vol_id; + + /* Fix up the link target object for hard link creation */ + if(H5VL_LINK_CREATE_HARD == create_type) { + void *cur_obj; + + /* Retrieve the object for the link target */ + H5Pget(lcpl_id, H5VL_PROP_LINK_TARGET, &cur_obj); + + /* If it's a non-NULL pointer, find the 'under object' and re-set the property */ + if(cur_obj) { + /* Check if we still need the "under" VOL ID */ + if(under_vol_id < 0) + under_vol_id = ((H5VL_pass_through_t *)cur_obj)->under_vol_id; + + /* Set the object for the link target */ + H5Pset(lcpl_id, H5VL_PROP_LINK_TARGET, &(((H5VL_pass_through_t *)cur_obj)->under_object)); + } /* end if */ + } /* end if */ + + ret_value = H5VLlink_create(create_type, (o ? o->under_object : NULL), loc_params, under_vol_id, lcpl_id, lapl_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_link_copy + * + * Purpose: Renames an object within an HDF5 container and copies it to a new + * group. The original name SRC is unlinked from the group graph + * and then inserted with the new name DST (which can specify a + * new path for the object) as an atomic operation. The names + * are interpreted relative to SRC_LOC_ID and + * DST_LOC_ID, which are either file IDs or group ID. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, + hid_t lapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj; + H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj; + hid_t under_vol_id = -1; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Copy\n"); +#endif + + /* Retrieve the "under" VOL id */ + if(o_src) + under_vol_id = o_src->under_vol_id; + else if(o_dst) + under_vol_id = o_dst->under_vol_id; + assert(under_vol_id > 0); + + ret_value = H5VLlink_copy((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL), loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_copy() */ + + +/*------------------------------------------------------------------------- + * Function: +H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, + * + * Purpose: Moves a link within an HDF5 file to a new group. The original + * name SRC is unlinked from the group graph + * and then inserted with the new name DST (which can specify a + * new path for the object) as an atomic operation. The names + * are interpreted relative to SRC_LOC_ID and + * DST_LOC_ID, which are either file IDs or group ID. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, + hid_t lapl_id, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj; + H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj; + hid_t under_vol_id = -1; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Move\n"); +#endif + + /* Retrieve the "under" VOL id */ + if(o_src) + under_vol_id = o_src->under_vol_id; + else if(o_dst) + under_vol_id = o_dst->under_vol_id; + assert(under_vol_id > 0); + + ret_value = H5VLlink_move((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL), loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_move() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_link_get + * + * Purpose: Get info about a link + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params, + H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Get\n"); +#endif + + ret_value = H5VLlink_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_link_specific + * + * Purpose: Specific operation on a link + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params, + H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Specific\n"); +#endif + + ret_value = H5VLlink_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_link_optional + * + * Purpose: Perform a connector-specific operation on a link + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_link_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL LINK Optional\n"); +#endif + + ret_value = H5VLlink_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_link_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_object_open + * + * Purpose: Opens an object inside a container. + * + * Return: Success: Pointer to object + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params, + H5I_type_t *opened_type, hid_t dxpl_id, void **req) +{ + H5VL_pass_through_t *new_obj; + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL OBJECT Open\n"); +#endif + + under = H5VLobject_open(o->under_object, loc_params, o->under_vol_id, opened_type, dxpl_id, req); + if(under) { + new_obj = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t)); + new_obj->under_object = under; + new_obj->under_vol_id = o->under_vol_id; + H5Iinc_ref(new_obj->under_vol_id); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + } /* end if */ + else + new_obj = NULL; + + return((void *)new_obj); +} /* end H5VL_pass_through_object_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_object_copy + * + * Purpose: Copies an object inside a container. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params, + const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params, + const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, + void **req) +{ + H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj; + H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL OBJECT Copy\n"); +#endif + + ret_value = H5VLobject_copy(o_src->under_object, src_loc_params, src_name, o_dst->under_object, dst_loc_params, dst_name, o_src->under_vol_id, ocpypl_id, lcpl_id, dxpl_id, req); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o_src->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_object_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_object_get + * + * Purpose: Get info about an object + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL OBJECT Get\n"); +#endif + + ret_value = H5VLobject_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_object_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_object_specific + * + * Purpose: Specific operation on an object + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params, + H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL OBJECT Specific\n"); +#endif + + ret_value = H5VLobject_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_object_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_object_optional + * + * Purpose: Perform a connector-specific operation for an object + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_object_optional(void *obj, hid_t dxpl_id, void **req, + va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL OBJECT Optional\n"); +#endif + + ret_value = H5VLobject_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments); + + /* Check for async request */ + if(req && *req) { + H5VL_pass_through_t *r; + + r = (H5VL_pass_through_t*)calloc(1, sizeof(H5VL_pass_through_t)); + r->under_object = *req; + r->under_vol_id = o->under_vol_id; + H5Iinc_ref(r->under_vol_id); + + *req = r; + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_object_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_wait + * + * Purpose: Wait (with a timeout) for an async operation to complete + * + * Note: Releases the request if the operation has completed and the + * connector callback succeeds + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_wait(void *obj, uint64_t timeout, + H5ES_status_t *status) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Wait\n"); +#endif + + ret_value = H5VLrequest_wait(o->under_object, o->under_vol_id, timeout, status); + + if(ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_request_wait() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_notify + * + * Purpose: Registers a user callback to be invoked when an asynchronous + * operation completes + * + * Note: Releases the request, if connector callback succeeds + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Wait\n"); +#endif + + ret_value = H5VLrequest_notify(o->under_object, o->under_vol_id, cb, ctx); + + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_request_notify() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_cancel + * + * Purpose: Cancels an asynchronous operation + * + * Note: Releases the request, if connector callback succeeds + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_cancel(void *obj) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Cancel\n"); +#endif + + ret_value = H5VLrequest_cancel(o->under_object, o->under_vol_id); + + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_request_cancel() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_specific_reissue + * + * Purpose: Re-wrap vararg arguments into a va_list and reissue the + * request specific callback to the underlying VOL connector. + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_specific_reissue(void *obj, hid_t connector_id, + H5VL_request_specific_t specific_type, ...) +{ + va_list arguments; + herr_t ret_value; + + va_start(arguments, specific_type); + ret_value = H5VLrequest_specific(obj, connector_id, specific_type, arguments); + va_end(arguments); + + return(ret_value); +} /* end H5VL_pass_through_request_specific_reissue() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_specific + * + * Purpose: Specific operation on a request + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_type, + va_list arguments) +{ + herr_t ret_value = -1; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Specific\n"); +#endif + + if(H5VL_REQUEST_WAITANY == specific_type || + H5VL_REQUEST_WAITSOME == specific_type || + H5VL_REQUEST_WAITALL == specific_type) { + va_list tmp_arguments; + size_t req_count; + + /* Sanity check */ + assert(obj == NULL); + + /* Get enough info to call the underlying connector */ + va_copy(tmp_arguments, arguments); + req_count = va_arg(tmp_arguments, size_t); + + /* Can only use a request to invoke the underlying VOL connector when there's >0 requests */ + if(req_count > 0) { + void **req_array; + void **under_req_array; + uint64_t timeout; + H5VL_pass_through_t *o; + size_t u; /* Local index variable */ + + /* Get the request array */ + req_array = va_arg(tmp_arguments, void **); + + /* Get a request to use for determining the underlying VOL connector */ + o = (H5VL_pass_through_t *)req_array[0]; + + /* Create array of underlying VOL requests */ + under_req_array = (void **)malloc(req_count * sizeof(void **)); + for(u = 0; u < req_count; u++) + under_req_array[u] = ((H5VL_pass_through_t *)req_array[u])->under_object; + + /* Remove the timeout value from the vararg list (it's used in all the calls below) */ + timeout = va_arg(tmp_arguments, uint64_t); + + /* Release requests that have completed */ + if(H5VL_REQUEST_WAITANY == specific_type) { + size_t *index; /* Pointer to the index of completed request */ + H5ES_status_t *status; /* Pointer to the request's status */ + + /* Retrieve the remaining arguments */ + index = va_arg(tmp_arguments, size_t *); + assert(*index <= req_count); + status = va_arg(tmp_arguments, H5ES_status_t *); + + /* Reissue the WAITANY 'request specific' call */ + ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, index, status); + + /* Release the completed request, if it completed */ + if(ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS) { + H5VL_pass_through_t *tmp_o; + + tmp_o = (H5VL_pass_through_t *)req_array[*index]; + H5Idec_ref(tmp_o->under_vol_id); + free(tmp_o); + } /* end if */ + } /* end if */ + else if(H5VL_REQUEST_WAITSOME == specific_type) { + size_t *outcount; /* # of completed requests */ + unsigned *array_of_indices; /* Array of indices for completed requests */ + H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */ + + /* Retrieve the remaining arguments */ + outcount = va_arg(tmp_arguments, size_t *); + assert(*outcount <= req_count); + array_of_indices = va_arg(tmp_arguments, unsigned *); + array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *); + + /* Reissue the WAITSOME 'request specific' call */ + ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, outcount, array_of_indices, array_of_statuses); + + /* If any requests completed, release them */ + if(ret_value >= 0 && *outcount > 0) { + unsigned *idx_array; /* Array of indices of completed requests */ + + /* Retrieve the array of completed request indices */ + idx_array = va_arg(tmp_arguments, unsigned *); + + /* Release the completed requests */ + for(u = 0; u < *outcount; u++) { + H5VL_pass_through_t *tmp_o; + + tmp_o = (H5VL_pass_through_t *)req_array[idx_array[u]]; + H5Idec_ref(tmp_o->under_vol_id); + free(tmp_o); + } /* end for */ + } /* end if */ + } /* end else-if */ + else { /* H5VL_REQUEST_WAITALL == specific_type */ + H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */ + + /* Retrieve the remaining arguments */ + array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *); + + /* Reissue the WAITALL 'request specific' call */ + ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, array_of_statuses); + + /* Release the completed requests */ + if(ret_value >= 0) { + for(u = 0; u < req_count; u++) { + if(array_of_statuses[u] != H5ES_STATUS_IN_PROGRESS) { + H5VL_pass_through_t *tmp_o; + + tmp_o = (H5VL_pass_through_t *)req_array[u]; + H5Idec_ref(tmp_o->under_vol_id); + free(tmp_o); + } /* end if */ + } /* end for */ + } /* end if */ + } /* end else */ + + /* Release array of requests for underlying connector */ + free(under_req_array); + } /* end if */ + + /* Finish use of copied vararg list */ + va_end(tmp_arguments); + } /* end if */ + else + assert(0 && "Unknown 'specific' operation"); + + return(ret_value); +} /* end H5VL_pass_through_request_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_optional + * + * Purpose: Perform a connector-specific operation for a request + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_optional(void *obj, va_list arguments) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Optional\n"); +#endif + + ret_value = H5VLrequest_optional(o->under_object, o->under_vol_id, arguments); + + return(ret_value); +} /* end H5VL_pass_through_request_optional() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_pass_through_request_free + * + * Purpose: Releases a request, allowing the operation to complete without + * application tracking + * + * Return: Success: 0 + * Failure: -1 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_pass_through_request_free(void *obj) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + herr_t ret_value; + +#ifdef ENABLE_LOGGING + printf("------- PASS THROUGH VOL REQUEST Free\n"); +#endif + + ret_value = H5VLrequest_free(o->under_object, o->under_vol_id); + + if(ret_value >= 0) { + H5Idec_ref(o->under_vol_id); + free(o); + } /* end if */ + + return(ret_value); +} /* end H5VL_pass_through_request_free() */ + diff --git a/src/H5VLpassthru.h b/src/H5VLpassthru.h new file mode 100644 index 0000000..e640636 --- /dev/null +++ b/src/H5VLpassthru.h @@ -0,0 +1,46 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: The public header file for the pass-through VOL connector. + */ + +#ifndef _H5VLpassthru_H +#define _H5VLpassthru_H + +/* Identifier for the pass-through VOL connector */ +#define H5VL_PASSTHRU (H5VL_pass_through_register()) + +/* Characteristics of the pass-through VOL connector */ +#define H5VL_PASSTHRU_NAME "pass_through" +#define H5VL_PASSTHRU_VALUE 505 /* VOL connector ID */ +#define H5VL_PASSTHRU_VERSION 0 + +/* Pass-through VOL connector info */ +typedef struct H5VL_pass_through_info_t { + hid_t under_vol_id; /* VOL ID for under VOL */ + void *under_vol_info; /* VOL info for under VOL */ +} H5VL_pass_through_info_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +H5_DLL hid_t H5VL_pass_through_register(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _H5VLpassthru_H */ + diff --git a/src/Makefile.am b/src/Makefile.am index d91cca8..69b51b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,7 +114,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Topaque.c \ H5Torder.c \ H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c \ - H5VL.c H5VLcallback.c H5VLint.c H5VLnative.c \ + H5VL.c H5VLcallback.c H5VLint.c H5VLnative.c H5VLpassthru.c \ H5VM.c H5WB.c H5Z.c \ H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \ H5Zscaleoffset.c H5Zszip.c H5Ztrans.c @@ -141,7 +141,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5MMpublic.h H5Opublic.h H5Ppublic.h \ H5PLextern.h H5PLpublic.h \ H5Rpublic.h H5Spublic.h H5Tpublic.h \ - H5VLnative.h H5VLpublic.h H5Zpublic.h + H5VLnative.h H5VLpassthru.h H5VLpublic.h H5Zpublic.h # install libhdf5.settings in lib directory settingsdir=$(libdir) diff --git a/src/hdf5.h b/src/hdf5.h index f19abd9..c12037f 100644 --- a/src/hdf5.h +++ b/src/hdf5.h @@ -52,7 +52,8 @@ #include "H5FDwindows.h" /* Win32 I/O */ #endif -/* Virtual object layer drivers */ -#include "H5VLnative.h" /* Native VOL driver */ +/* Virtual object layer (VOL) connectors */ +#include "H5VLnative.h" /* Native VOL connector */ +#include "H5VLpassthru.h" /* Pass-through VOL connector */ #endif -- cgit v0.12