diff options
author | jhendersonHDF <jhenderson@hdfgroup.org> | 2021-09-29 18:28:12 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-29 18:28:12 (GMT) |
commit | 3da0802c40d58759995916bf9d0880e19f0af44d (patch) | |
tree | 809ada78cec1cbaaf6ec2ace5b4429a56d0f6574 /src/H5Pfapl.c | |
parent | 0fa5836cc5f037dd9f2cdd7f9a1051ddcc1c9ad0 (diff) | |
download | hdf5-3da0802c40d58759995916bf9d0880e19f0af44d.zip hdf5-3da0802c40d58759995916bf9d0880e19f0af44d.tar.gz hdf5-3da0802c40d58759995916bf9d0880e19f0af44d.tar.bz2 |
VFD plugins (#602)
* Implement support for loading of Virtual File Drivers as plugins
Fix plugin caching for VOL connector and VFD plugins
Fix plugin iteration to skip paths that can't be opened
* Enable dynamic loading of VFDs with HDF5_DRIVER environment variable
* Temporarily disable error reporting during H5F_open double file open
* Default to using HDstat in h5_get_file_size for unknown VFDs
* Use macros for some environment variables that HDF5 interprets
* Update "null" and "ctl testing" VFDs
Diffstat (limited to 'src/H5Pfapl.c')
-rw-r--r-- | src/H5Pfapl.c | 567 |
1 files changed, 544 insertions, 23 deletions
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index a8e0d8e..f37cb74 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -41,8 +41,28 @@ #include "H5VMprivate.h" /* Vector Functions */ /* Includes needed to set default file driver */ -#include "H5FDsec2.h" /* POSIX unbuffered I/O */ +#include "H5FDsec2.h" /* POSIX unbuffered I/O */ +#include "H5FDcore.h" +#include "H5FDlog.h" +#include "H5FDfamily.h" +#include "H5FDmulti.h" #include "H5FDstdio.h" /* Standard C buffered I/O */ +#include "H5FDsplitter.h" +#ifdef H5_HAVE_PARALLEL +#include "H5FDmpio.h" +#endif +#ifdef H5_HAVE_DIRECT +#include "H5FDdirect.h" +#endif +#ifdef H5_HAVE_MIRROR_VFD +#include "H5FDmirror.h" +#endif +#ifdef H5_HAVE_LIBHDFS +#include "H5FDhdfs.h" +#endif +#ifdef H5_HAVE_ROS3_VFD +#include "H5FDros3.h" +#endif #ifdef H5_HAVE_WINDOWS #include "H5FDwindows.h" /* Win32 I/O */ #endif @@ -113,7 +133,7 @@ #define H5F_ACS_FILE_DRV_SIZE sizeof(H5FD_driver_prop_t) #define H5F_ACS_FILE_DRV_DEF \ { \ - H5_DEFAULT_VFD, NULL \ + H5_DEFAULT_VFD, NULL, NULL \ } #define H5F_ACS_FILE_DRV_CRT H5P__facc_file_driver_create #define H5F_ACS_FILE_DRV_SET H5P__facc_file_driver_set @@ -398,6 +418,9 @@ static int H5P__facc_mpi_info_cmp(const void *value1, const void *value2, siz static herr_t H5P__facc_mpi_info_close(const char *name, size_t size, void *value); #endif /* H5_HAVE_PARALLEL */ +/* Internal routines */ +static herr_t H5P__facc_set_def_driver_check_predefined(const char *driver_name, hid_t *driver_id); + /*********************/ /* Package Variables */ /*********************/ @@ -809,6 +832,208 @@ done: } /* end H5P__facc_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P__facc_set_def_driver + * + * Purpose: Parses a string that contains the name of the default VFL + * driver for the default FAPL. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__facc_set_def_driver(void) +{ + const char *driver_env_var; + hbool_t driver_ref_inc = FALSE; + hid_t driver_id = H5I_INVALID_HID; /* VFL driver ID */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + /* Check if VFL driver environment variable is set */ + driver_env_var = HDgetenv(HDF5_DRIVER); + + /* Only parse VFL driver string if it's set */ + if (driver_env_var && *driver_env_var) { + H5FD_driver_prop_t driver_prop; + H5P_genplist_t * def_fapl; /* Default file access property list */ + H5P_genclass_t * def_fapclass; /* Default file access property class */ + const char * driver_config_env_var; + htri_t driver_is_registered; + + /* Check to see if the driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_name(driver_env_var, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFL driver is already registered") + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "unable to increment ref count on VFD") + driver_ref_inc = TRUE; + } /* end else-if */ + else { + /* Check for VFL drivers that ship with the library */ + if (H5P__facc_set_def_driver_check_predefined(driver_env_var, &driver_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check for predefined VFL driver name") + else if (driver_id > 0) { + if (H5I_inc_ref(driver_id, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "can't increment VFL driver refcount") + driver_ref_inc = TRUE; + } + else { + /* Register the VFL driver */ + if ((driver_id = H5FD_register_driver_by_name(driver_env_var, TRUE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "can't register VFL driver") + driver_ref_inc = TRUE; + } /* end else */ + } /* end else */ + + /* Retrieve driver configuration string from environment variable, if set. */ + driver_config_env_var = HDgetenv(HDF5_DRIVER_CONFIG); + + driver_prop.driver_id = driver_id; + driver_prop.driver_info = NULL; + driver_prop.driver_config_str = driver_config_env_var; + + /* Get default file access pclass */ + if (NULL == (def_fapclass = (H5P_genclass_t *)H5I_object(H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_VFL, H5E_BADID, FAIL, + "can't find object for default file access property class ID") + + /* Set new default VFL driver for default file access pclass */ + if (H5P__class_set(def_fapclass, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, + "can't set default VFL driver for default file access property list class") + + /* Get default file access plist */ + if (NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_VFL, H5E_BADID, FAIL, "can't find object for default fapl ID") + + /* Set new default VFL driver for default FAPL */ + if (H5P_set_driver(def_fapl, driver_prop.driver_id, driver_prop.driver_info, + driver_prop.driver_config_str) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default VFL driver for default FAPL") + } + +done: + /* Clean up on error */ + if (ret_value < 0) { + if (driver_id >= 0 && driver_ref_inc && H5I_dec_app_ref(driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "unable to unregister VFL driver") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__facc_set_def_driver() */ + +/*------------------------------------------------------------------------- + * Function: H5P__facc_set_def_driver_check_predefined + * + * Purpose: Checks a given driver name against a list of predefined + * names for VFL drivers that are internal to HDF5. If a name + * is matched, the ID for that driver is returned through + * `driver_id`. Otherwise, `driver_id` is set to + * H5I_INVALID_HID. + * + * Return: Non-negative on sucess/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__facc_set_def_driver_check_predefined(const char *driver_name, hid_t *driver_id) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(driver_name); + HDassert(driver_id); + + if (!HDstrcmp(driver_name, "sec2")) { + if ((*driver_id = H5FD_SEC2) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize sec2 VFD") + } + else if (!HDstrcmp(driver_name, "core") || !HDstrcmp(driver_name, "core_paged")) { + if ((*driver_id = H5FD_CORE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize core VFD") + } + else if (!HDstrcmp(driver_name, "log")) { + if ((*driver_id = H5FD_LOG) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize log VFD") + } + else if (!HDstrcmp(driver_name, "family")) { + if ((*driver_id = H5FD_FAMILY) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize family VFD") + } + else if (!HDstrcmp(driver_name, "multi") || !HDstrcmp(driver_name, "split")) { + if ((*driver_id = H5FD_MULTI) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize multi VFD") + } + else if (!HDstrcmp(driver_name, "stdio")) { + if ((*driver_id = H5FD_STDIO) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize stdio VFD") + } + else if (!HDstrcmp(driver_name, "splitter")) { + if ((*driver_id = H5FD_SPLITTER) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize splitter VFD") + } + else if (!HDstrcmp(driver_name, "mpio")) { +#ifdef H5_HAVE_PARALLEL + if ((*driver_id = H5FD_MPIO) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize MPI I/O VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "MPI-I/O VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "direct")) { +#ifdef H5_HAVE_DIRECT + if ((*driver_id = H5FD_DIRECT) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize Direct I/O VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Direct I/O VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "mirror")) { +#ifdef H5_HAVE_MIRROR_VFD + if ((*driver_id = H5FD_MIRROR) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize mirror VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Mirror VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "hdfs")) { +#ifdef H5_HAVE_LIBHDFS + if ((*driver_id = H5FD_HDFS) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize HDFS VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "HDFS VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "ros3")) { +#ifdef H5_HAVE_ROS3_VFD + if ((*driver_id = H5FD_ROS3) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize ROS3 VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "ROS3 VFD is not enabled") +#endif + } + else if (!HDstrcmp(driver_name, "windows")) { +#ifdef H5_HAVE_WINDOWS + if ((*driver_id = H5FD_WINDOWS) < 0) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL, "couldn't initialize Windows VFD") +#else + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "Windows VFD is not enabled") +#endif + } + else { + *driver_id = H5I_INVALID_HID; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__facc_set_def_driver_check_predefined() */ + +/*------------------------------------------------------------------------- * Function: H5Pset_alignment * * Purpose: Sets the alignment properties of a file access property list @@ -899,42 +1124,52 @@ done: } /* end H5Pget_alignment() */ /*------------------------------------------------------------------------- - * Function: H5P_set_driver + * Function: H5P_set_driver * - * Purpose: Set the file driver (DRIVER_ID) for a file access - * property list (PLIST_ID) and supply an optional - * struct containing the driver-specific properites - * (DRIVER_INFO). The driver properties will be copied into the - * property list and the reference count on the driver will be - * incremented, allowing the caller to close the driver ID but - * still use the property list. + * Purpose: Set the file driver (NEW_DRIVER_ID) for a file access + * property list (PLIST). A struct (NEW_DRIVER_INFO) or string + * (NEW_DRIVER_CONFIG_STR) containing the driver-specific + * properties can optionally be supplied. The driver properties + * (struct or string) will be copied into the property list and + * the reference count on the driver will be incremented, + * allowing the caller to close the driver ID but still use the + * property list. * - * Return: Success: Non-negative - * Failure: Negative + * Note: Only one of either NEW_DRIVER_INFO or NEW_DRIVER_CONFIG_STR + * should be specified, but not both. + * + * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Tuesday, August 3, 1999 + * Tuesday, August 3, 1999 * *------------------------------------------------------------------------- */ herr_t -H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info) +H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info, + const char *new_driver_config_str) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* If VFD configuration information is supplied, ensure that either binary + * configuration data or a configuration string is supplied, but not both. + */ + HDassert(!new_driver_info || !new_driver_config_str); + if (NULL == H5I_object_verify(new_driver_id, H5I_VFL)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID") if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & config. string */ /* Prepare the driver property */ - driver_prop.driver_id = new_driver_id; - driver_prop.driver_info = new_driver_info; + driver_prop.driver_id = new_driver_id; + driver_prop.driver_info = new_driver_info; + driver_prop.driver_config_str = new_driver_config_str; - /* Set the driver ID & info property */ + /* Set the driver ID, info & config. string property */ if (H5P_set(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver ID & info") } /* end if */ @@ -980,7 +1215,7 @@ H5Pset_driver(hid_t plist_id, hid_t new_driver_id, const void *new_driver_info) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID") /* Set the driver */ - if (H5P_set_driver(plist, new_driver_id, new_driver_info) < 0) + if (H5P_set_driver(plist, new_driver_id, new_driver_info, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") done: @@ -988,6 +1223,180 @@ done: } /* end H5Pset_driver() */ /*------------------------------------------------------------------------- + * Function: H5P_set_driver_by_name + * + * Purpose: Set the file driver name (DRIVER_NAME) for a file access + * property list (PLIST) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_NAME is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_set_driver_by_name(H5P_genplist_t *plist, const char *driver_name, const char *driver_config, + hbool_t app_ref) +{ + hid_t new_driver_id = H5I_INVALID_HID; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + assert(plist); + assert(driver_name); + + /* Register the driver */ + if ((new_driver_id = H5FD_register_driver_by_name(driver_name, app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register VFD") + + /* Set the driver */ + if (H5P_set_driver(plist, new_driver_id, NULL, driver_config) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + if (ret_value < 0) { + if (new_driver_id >= 0 && H5I_dec_app_ref(new_driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement count on VFD ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_set_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_driver_by_name + * + * Purpose: Set the file driver name (DRIVER_NAME) for a file access + * property list (PLIST_ID) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_NAME is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_driver_by_name(hid_t plist_id, const char *driver_name, const char *driver_config) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*s*s", plist_id, driver_name, driver_config); + + /* Check arguments */ + if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if (!driver_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "driver_name parameter cannot be NULL") + if (!*driver_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "driver_name parameter cannot be an empty string") + + /* Set the driver */ + if (H5P_set_driver_by_name(plist, driver_name, driver_config, TRUE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5P_set_driver_by_value + * + * Purpose: Set the file driver value (DRIVER_VALUE) for a file access + * property list (PLIST) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_VALUE is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_set_driver_by_value(H5P_genplist_t *plist, H5FD_class_value_t driver_value, const char *driver_config, + hbool_t app_ref) +{ + hid_t new_driver_id = H5I_INVALID_HID; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + assert(plist); + assert(driver_value >= 0); + + /* Register the driver */ + if ((new_driver_id = H5FD_register_driver_by_value(driver_value, app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, FAIL, "unable to register VFD") + + /* Set the driver */ + if (H5P_set_driver(plist, new_driver_id, NULL, driver_config) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + if (ret_value < 0) { + if (new_driver_id >= 0 && H5I_dec_app_ref(new_driver_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement count on VFD ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_set_driver_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_driver_by_value + * + * Purpose: Set the file driver value (DRIVER_VALUE) for a file access + * property list (PLIST_ID) and supply an optional string + * containing the driver-specific properties (DRIVER_CONFIG). + * The driver properties string will be copied into the + * property list. + * + * If the file driver specified by DRIVER_VALUE is not + * currently registered, an attempt will be made to load the + * driver as a plugin. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_driver_by_value(hid_t plist_id, H5FD_class_value_t driver_value, const char *driver_config) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iDV*s", plist_id, driver_value, driver_config); + + /* Check arguments */ + if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + if (driver_value < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "negative VFD value is disallowed") + + /* Set the driver */ + if (H5P_set_driver_by_value(plist, driver_value, driver_config, TRUE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_driver_by_value() */ + +/*------------------------------------------------------------------------- * Function: H5P_peek_driver * * Purpose: Return the ID of the low-level file driver. PLIST_ID should @@ -1014,7 +1423,7 @@ H5P_peek_driver(H5P_genplist_t *plist) /* Get the current driver ID */ if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID") @@ -1098,7 +1507,7 @@ H5P_peek_driver_info(H5P_genplist_t *plist) /* Get the current driver info */ if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { - H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */ + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver info") @@ -1151,13 +1560,104 @@ done: } /* end H5Pget_driver_info() */ /*------------------------------------------------------------------------- + * Function: H5P_peek_driver_config_str + * + * Purpose: Returns a pointer directly to the file driver configuration + * string of a file access property list. + * + * Return: Success: Ptr to *uncopied* driver configuration string, if + * any. + * + * Failure: NULL. NULL is also returned if the driver has not + * been configured with a driver configuration string. + * + *------------------------------------------------------------------------- + */ +const char * +H5P_peek_driver_config_str(H5P_genplist_t *plist) +{ + const char *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* Get the current driver configuration string */ + if (TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) { + H5FD_driver_prop_t driver_prop; /* Property for driver ID, info & configuration string */ + + if (H5P_peek(plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver configuration string") + ret_value = driver_prop.driver_config_str; + } /* end if */ + else + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL, "not a file access property list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_peek_driver_config_str() */ + +/*------------------------------------------------------------------------- + * Function: H5Pget_driver_config_str + * + * Purpose: Retrieves a string representation of the configuration for + * the driver set on the given FAPL. The returned string can + * be used to configure the same driver in an identical way. + * + * `config_buf` may be NULL, in which case the length of the + * driver configuration string is simply returned. The caller + * can then allocate a buffer of the appropriate size and call + * this routine again. + * + * Return: Length of the driver configuration string on success (not + * including the NUL terminator) + * Negative on failure + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Pget_driver_config_str(hid_t fapl_id, char *config_buf, size_t buf_size) +{ + H5P_genplist_t *plist; /* Property list pointer */ + const char * config_str = NULL; + ssize_t ret_value = -1; + + FUNC_ENTER_API((-1)) + H5TRACE3("Zs", "i*sz", fapl_id, config_buf, buf_size); + + /* Check arguments */ + if (!config_buf && buf_size) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "config_buf cannot be NULL if buf_size is non-zero") + + /* Get the plist structure */ + if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "can't find object for ID") + + /* Retrieve configuration string property */ + if ((config_str = H5P_peek_driver_config_str(plist))) { + size_t config_str_len = HDstrlen(config_str); + + if (config_buf) { + HDstrncpy(config_buf, config_str, MIN(config_str_len + 1, buf_size)); + if (config_str_len >= buf_size) + config_buf[buf_size - 1] = '\0'; + } + + ret_value = (ssize_t)config_str_len; + } + else + ret_value = 0; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Pget_driver_config_str() */ + +/*------------------------------------------------------------------------- * Function: H5P__file_driver_copy * * Purpose: Copy file driver ID & info. * * Note: This is an "in-place" copy, since this routine gets called * after the top-level copy has been performed and this routine - * finishes the "deep" part of the copy. + * finishes the "deep" part of the copy. * * Return: Success: Non-negative * Failure: Negative @@ -1208,6 +1708,15 @@ H5P__file_driver_copy(void *value) /* Set the driver info for the copy */ info->driver_info = new_pl; } /* end if */ + + /* Copy driver configuration string, if it exists */ + if (info->driver_config_str) { + char *new_config_str = NULL; + + if (NULL == (new_config_str = H5MM_strdup(info->driver_config_str))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "driver configuration string copy failed") + info->driver_config_str = new_config_str; + } /* end if */ } /* end if */ } /* end if */ @@ -1238,7 +1747,6 @@ H5P__file_driver_free(void *value) if (value) { H5FD_driver_prop_t *info = (H5FD_driver_prop_t *)value; /* Driver ID & info struct */ - /* Copy the driver & info, if there is one */ if (info->driver_id > 0) { /* Free the driver info, if it exists */ @@ -1246,6 +1754,9 @@ H5P__file_driver_free(void *value) if (H5FD_free_driver_info(info->driver_id, info->driver_info) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "driver info free request failed") + /* Free the driver configuration string, if it exists */ + H5MM_xfree_const(info->driver_config_str); + /* Decrement reference count for driver */ if (H5I_dec_ref(info->driver_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDEC, FAIL, "can't decrement reference count for driver ID") @@ -1465,6 +1976,16 @@ H5P__facc_file_driver_cmp(const void *_info1, const void *_info2, size_t H5_ATTR HGOTO_DONE(cmp_value); } /* end if */ + /* Compare driver configuration strings */ + if (info1->driver_config_str == NULL && info2->driver_config_str != NULL) + HGOTO_DONE(-1); + if (info1->driver_config_str != NULL && info2->driver_config_str == NULL) + HGOTO_DONE(1); + if (info1->driver_config_str) { + if (0 != (cmp_value = HDstrcmp(info1->driver_config_str, info2->driver_config_str))) + HGOTO_DONE(cmp_value); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__facc_file_driver_cmp() */ |