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 | |
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')
43 files changed, 2589 insertions, 500 deletions
@@ -261,7 +261,7 @@ H5_init_library(void) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface") if (H5VL_init_phase1() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface") - if (H5P_init() < 0) + if (H5P_init_phase1() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface") if (H5AC_init() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize metadata caching interface") @@ -273,6 +273,8 @@ H5_init_library(void) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataspace interface") /* Finish initializing interfaces that depend on the interfaces above */ + if (H5P_init_phase2() < 0) + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface") if (H5VL_init_phase2() < 0) HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface") @@ -301,6 +301,62 @@ done: } /* end H5FD_register() */ /*------------------------------------------------------------------------- + * Function: H5FDis_driver_registered_by_name + * + * Purpose: Tests whether a VFD class has been registered or not + * according to a supplied driver name. + * + * Return: >0 if a VFD with that name has been registered + * 0 if a VFD with that name has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FDis_driver_registered_by_name(const char *driver_name) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("t", "*s", driver_name); + + /* Check if driver with this name is registered */ + if ((ret_value = H5FD_is_driver_registered_by_name(driver_name, NULL)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFD is registered") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDis_driver_registered_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FDis_driver_registered_by_value + * + * Purpose: Tests whether a VFD class has been registered or not + * according to a supplied driver value (ID). + * + * Return: >0 if a VFD with that value has been registered + * 0 if a VFD with that value hasn't been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FDis_driver_registered_by_value(H5FD_class_value_t driver_value) +{ + htri_t ret_value = FALSE; + + FUNC_ENTER_API(FAIL) + H5TRACE1("t", "DV", driver_value); + + /* Check if driver with this value is registered */ + if ((ret_value = H5FD_is_driver_registered_by_value(driver_value, NULL)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't check if VFD is registered") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5FDis_driver_registered_by_value() */ + +/*------------------------------------------------------------------------- * Function: H5FDunregister * * Purpose: Removes a driver ID from the library. This in no way affects diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 820c74f..ce96582 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -149,8 +149,10 @@ static herr_t H5FD__core_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__core_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD__core_unlock(H5FD_t *_file); static herr_t H5FD__core_delete(const char *filename, hid_t fapl_id); +static inline const H5FD_core_fapl_t *H5FD__core_get_default_config(void); static const H5FD_class_t H5FD_core_g = { + H5FD_CORE_VALUE, /* value */ "core", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -187,6 +189,11 @@ static const H5FD_class_t H5FD_core_g = { H5FD_FLMAP_DICHOTOMY /* fl_map */ }; +/* Default configurations, if none provided */ +static const H5FD_core_fapl_t H5FD_core_default_config_g = {H5_MB, TRUE, H5FD_CORE_WRITE_TRACKING_FLAG, + H5FD_CORE_WRITE_TRACKING_PAGE_SIZE}; +static const H5FD_core_fapl_t H5FD_core_default_paged_config_g = {H5_MB, TRUE, TRUE, (size_t)4096}; + /* Define a free list to manage the region type */ H5FL_DEFINE(H5FD_core_region_t); @@ -409,6 +416,32 @@ done: } /* end H5FD__core_write_to_bstore() */ /*------------------------------------------------------------------------- + * Function: H5FD__core_get_default_config + * + * Purpose: Retrieves a default configuration for this VFD when no + * configuration information has been provided. + * + * Return: Valid Core VFD configuration information pointer (can't + * fail) + * + *------------------------------------------------------------------------- + */ +static inline const H5FD_core_fapl_t * +H5FD__core_get_default_config(void) +{ + char *driver = HDgetenv(HDF5_DRIVER); + + if (driver) { + if (!HDstrcmp(driver, "core")) + return &H5FD_core_default_config_g; + else if (!HDstrcmp(driver, "core_paged")) + return &H5FD_core_default_paged_config_g; + } + + return &H5FD_core_default_config_g; +} /* end H5FD__core_get_default_config() */ + +/*------------------------------------------------------------------------- * Function: H5FD__init_package * * Purpose: Initializes any interface-specific data or routines. @@ -426,7 +459,7 @@ H5FD__init_package(void) FUNC_ENTER_STATIC /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) @@ -529,7 +562,7 @@ H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size) if (H5FD_CORE != H5P_peek_driver(plist)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") if (NULL == (old_fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info") + old_fa = H5FD__core_get_default_config(); /* Set VFD info values */ HDmemset(&fa, 0, sizeof(H5FD_core_fapl_t)); @@ -539,7 +572,7 @@ H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size) fa.page_size = page_size; /* Set the property values & the driver for the FAPL */ - if (H5P_set_driver(plist, H5FD_CORE, &fa) < 0) + if (H5P_set_driver(plist, H5FD_CORE, &fa, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver") done: @@ -623,7 +656,7 @@ H5Pset_fapl_core(hid_t fapl_id, size_t increment, hbool_t backing_store) fa.page_size = H5FD_CORE_WRITE_TRACKING_PAGE_SIZE; /* Set the property values & the driver for the FAPL */ - if (H5P_set_driver(plist, H5FD_CORE, &fa) < 0) + if (H5P_set_driver(plist, H5FD_CORE, &fa, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver") done: @@ -748,7 +781,7 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") if (NULL == (fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + fa = H5FD__core_get_default_config(); /* Build the open flags */ o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY; @@ -1735,7 +1768,7 @@ H5FD__core_delete(const char *filename, hid_t fapl_id) if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") if (NULL == (fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info") + fa = H5FD__core_get_default_config(); if (fa->backing_store) if (HDremove(filename) < 0) diff --git a/src/H5FDcore.h b/src/H5FDcore.h index d456c3e..590478e 100644 --- a/src/H5FDcore.h +++ b/src/H5FDcore.h @@ -20,7 +20,8 @@ #ifndef H5FDcore_H #define H5FDcore_H -#define H5FD_CORE (H5FD_core_init()) +#define H5FD_CORE (H5FD_core_init()) +#define H5FD_CORE_VALUE H5_VFD_CORE #ifdef __cplusplus extern "C" { diff --git a/src/H5FDdevelop.h b/src/H5FDdevelop.h index 4895658..e897eb0 100644 --- a/src/H5FDdevelop.h +++ b/src/H5FDdevelop.h @@ -160,6 +160,7 @@ typedef struct H5FD_t H5FD_t; /* Class information for each file driver */ typedef struct H5FD_class_t { + H5FD_class_value_t value; const char * name; haddr_t maxaddr; H5F_close_degree_t fc_degree; @@ -235,6 +236,8 @@ extern "C" { #endif H5_DLL hid_t H5FDregister(const H5FD_class_t *cls); +H5_DLL htri_t H5FDis_driver_registered_by_name(const char *driver_name); +H5_DLL htri_t H5FDis_driver_registered_by_value(H5FD_class_value_t driver_value); H5_DLL herr_t H5FDunregister(hid_t driver_id); H5_DLL H5FD_t *H5FDopen(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FDclose(H5FD_t *file); diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 7cca09f..8c5001c 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -120,6 +120,8 @@ typedef struct H5FD_direct_t { /* Prototypes */ static herr_t H5FD__direct_term(void); +static herr_t H5FD__direct_populate_config(size_t boundary, size_t block_size, size_t cbuf_size, + H5FD_direct_fapl_t *fa_out); static void * H5FD__direct_fapl_get(H5FD_t *file); static void * H5FD__direct_fapl_copy(const void *_old_fa); static H5FD_t *H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); @@ -140,6 +142,7 @@ static herr_t H5FD__direct_unlock(H5FD_t *_file); static herr_t H5FD__direct_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_direct_g = { + H5FD_DIRECT_VALUE, /* value */ "direct", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -200,7 +203,7 @@ H5FD__init_package(void) FUNC_ENTER_STATIC /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) @@ -296,28 +299,10 @@ H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbu if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - HDmemset(&fa, 0, sizeof(H5FD_direct_fapl_t)); - if (boundary != 0) - fa.mboundary = boundary; - else - fa.mboundary = MBOUNDARY_DEF; - if (block_size != 0) - fa.fbsize = block_size; - else - fa.fbsize = FBSIZE_DEF; - if (cbuf_size != 0) - fa.cbsize = cbuf_size; - else - fa.cbsize = CBSIZE_DEF; - - /* Set the default to be true for data alignment */ - fa.must_align = TRUE; - - /* Copy buffer size must be a multiple of file block size */ - if (fa.cbsize % fa.fbsize != 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "copy buffer size must be a multiple of block size") + if (H5FD__direct_populate_config(boundary, block_size, cbuf_size, &fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") - ret_value = H5P_set_driver(plist, H5FD_DIRECT, &fa); + ret_value = H5P_set_driver(plist, H5FD_DIRECT, &fa, NULL); done: FUNC_LEAVE_API(ret_value) @@ -367,6 +352,53 @@ done: } /* end H5Pget_fapl_direct() */ /*------------------------------------------------------------------------- + * Function: H5FD__direct_populate_config + * + * Purpose: Populates a H5FD_direct_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__direct_populate_config(size_t boundary, size_t block_size, size_t cbuf_size, H5FD_direct_fapl_t *fa_out) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fa_out); + + HDmemset(fa_out, 0, sizeof(H5FD_direct_fapl_t)); + + if (boundary != 0) + fa_out->mboundary = boundary; + else + fa_out->mboundary = MBOUNDARY_DEF; + + if (block_size != 0) + fa_out->fbsize = block_size; + else + fa_out->fbsize = FBSIZE_DEF; + + if (cbuf_size != 0) + fa_out->cbsize = cbuf_size; + else + fa_out->cbsize = CBSIZE_DEF; + + /* Set the default to be true for data alignment */ + fa_out->must_align = TRUE; + + /* Copy buffer size must be a multiple of file block size */ + if (fa_out->cbsize % fa_out->fbsize != 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "copy buffer size must be a multiple of block size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__direct_populate_config() */ + +/*------------------------------------------------------------------------- * Function: H5FD__direct_fapl_get * * Purpose: Returns a file access property list which indicates how the @@ -450,6 +482,7 @@ H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad int fd = (-1); H5FD_direct_t * file = NULL; const H5FD_direct_fapl_t *fa; + H5FD_direct_fapl_t default_fa; #ifdef H5_HAVE_WIN32_API HFILE filehandle; struct _BY_HANDLE_FILE_INFORMATION fileinfo; @@ -498,8 +531,11 @@ H5FD__direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad /* Get the driver specific information */ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_direct_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_direct_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__direct_populate_config(0, 0, 0, &default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't initialize driver configuration info") + fa = &default_fa; + } file->fd = fd; H5_CHECKED_ASSIGN(file->eof, haddr_t, sb.st_size, h5_stat_size_t); diff --git a/src/H5FDdirect.h b/src/H5FDdirect.h index f06de7f..a439e55 100644 --- a/src/H5FDdirect.h +++ b/src/H5FDdirect.h @@ -21,9 +21,11 @@ #define H5FDdirect_H #ifdef H5_HAVE_DIRECT -#define H5FD_DIRECT (H5FD_direct_init()) +#define H5FD_DIRECT (H5FD_direct_init()) +#define H5FD_DIRECT_VALUE H5_VFD_DIRECT #else -#define H5FD_DIRECT (H5I_INVALID_HID) +#define H5FD_DIRECT (H5I_INVALID_HID) +#define H5FD_DIRECT_VALUE H5_VFD_INVALID #endif /* H5_HAVE_DIRECT */ #ifdef H5_HAVE_DIRECT diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index af67c78..d187b7b 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -47,6 +47,9 @@ /* The size of the member name buffers */ #define H5FD_FAM_MEMB_NAME_BUF_SIZE 4096 +/* Default member size - 100 MiB */ +#define H5FD_FAM_DEF_MEM_SIZE ((hsize_t)(100 * H5_MB)) + /* The driver identification number, initialized at runtime */ static hid_t H5FD_FAMILY_g = 0; @@ -77,6 +80,10 @@ typedef struct H5FD_family_fapl_t { hid_t memb_fapl_id; /*file access property list of each memb*/ } H5FD_family_fapl_t; +/* Private routines */ +static herr_t H5FD__family_get_default_config(H5FD_family_fapl_t *fa_out); +static char * H5FD__family_get_default_printf_filename(const char *old_filename); + /* Callback prototypes */ static herr_t H5FD__family_term(void); static void * H5FD__family_fapl_get(H5FD_t *_file); @@ -105,6 +112,7 @@ static herr_t H5FD__family_delete(const char *filename, hid_t fapl_id); /* The class struct */ static const H5FD_class_t H5FD_family_g = { + H5FD_FAMILY_VALUE, /* value */ "family", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -141,6 +149,122 @@ static const H5FD_class_t H5FD_family_g = { H5FD_FLMAP_DICHOTOMY /* fl_map */ }; +/*------------------------------------------------------------------------- + * Function: H5FD__family_get_default_config + * + * Purpose: Populates a H5FD_family_fapl_t structure with default + * values. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__family_get_default_config(H5FD_family_fapl_t *fa_out) +{ + H5P_genplist_t *def_plist; + H5P_genplist_t *plist; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fa_out); + + fa_out->memb_size = H5FD_FAM_DEF_MEM_SIZE; + + /* Use copy of default file access property list for member FAPL ID. + * The Sec2 driver is explicitly set on the member FAPL ID, as the + * default driver might have been replaced with the Family VFD, which + * would cause recursion badness in the child members. + */ + if (NULL == (def_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if ((fa_out->memb_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fa_out->memb_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on member FAPL") + +done: + if (ret_value < 0 && fa_out->memb_fapl_id >= 0) { + if (H5I_dec_ref(fa_out->memb_fapl_id) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement ref. count on member FAPL ID") + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__family_get_default_config() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__family_get_default_printf_filename + * + * Purpose: Given a filename, allocates and returns a new filename + * buffer that contains the given filename modified into this + * VFD's printf-style format. For example, the filename + * "file1.h5" would be modified to "file1-%06d.h5". This would + * allow for member filenames such as "file1-000000.h5", + * "file1-000001.h5", etc. The caller is responsible for + * freeing the returned buffer. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ +static char * +H5FD__family_get_default_printf_filename(const char *old_filename) +{ + const char *suffix = "-%06d"; + size_t old_filename_len = 0; + size_t new_filename_len = 0; + char * file_extension = NULL; + char * tmp_buffer = NULL; + char * ret_value = NULL; + + FUNC_ENTER_STATIC + + HDassert(old_filename); + + old_filename_len = HDstrlen(old_filename); + if (0 == old_filename_len) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid filename") + + new_filename_len = old_filename_len + HDstrlen(suffix) + 1; + if (NULL == (tmp_buffer = H5MM_malloc(new_filename_len))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "can't allocate new filename buffer") + + /* Determine if filename contains a ".h5" extension. */ + if ((file_extension = strstr(old_filename, ".h5"))) { + /* Insert the printf format between the filename and ".h5" extension. */ + HDstrcpy(tmp_buffer, old_filename); + file_extension = strstr(tmp_buffer, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = strrchr(old_filename, '.'))) { + char *new_extension_loc = NULL; + + /* If the filename doesn't contain a ".h5" extension, but contains + * AN extension, just insert the printf format before that extension. + */ + HDstrcpy(tmp_buffer, old_filename); + new_extension_loc = strrchr(tmp_buffer, '.'); + HDsprintf(new_extension_loc, "%s%s", suffix, file_extension); + } + else { + /* If the filename doesn't contain an extension at all, just insert + * the printf format at the end of the filename. + */ + HDsnprintf(tmp_buffer, new_filename_len, "%s%s", old_filename, suffix); + } + + ret_value = tmp_buffer; + +done: + if (!ret_value) + H5MM_xfree(tmp_buffer); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__family_get_default_printf_filename() */ + /*-------------------------------------------------------------------------- NAME H5FD__init_package -- Initialize interface-specific information @@ -243,7 +367,7 @@ herr_t H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id) { herr_t ret_value; - H5FD_family_fapl_t fa = {0, -1}; + H5FD_family_fapl_t fa = {0, H5I_INVALID_HID}; H5P_genplist_t * plist; /* Property list pointer */ FUNC_ENTER_API(FAIL) @@ -252,18 +376,22 @@ H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id) /* Check arguments */ if (TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (H5P_DEFAULT == memb_fapl_id) - memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + if (H5P_DEFAULT == memb_fapl_id) { + /* Get default configuration for member FAPL */ + if (H5FD__family_get_default_config(&fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default driver configuration info") + } else if (TRUE != H5P_isa_class(memb_fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") /* Initialize driver specific information. */ - fa.memb_size = msize; - fa.memb_fapl_id = memb_fapl_id; + fa.memb_size = msize; + if (H5P_DEFAULT != memb_fapl_id) + fa.memb_fapl_id = memb_fapl_id; if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_FAMILY, &fa); + ret_value = H5P_set_driver(plist, H5FD_FAMILY, &fa, NULL); done: FUNC_LEAVE_API(ret_value) @@ -589,9 +717,10 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad { H5FD_family_t *file = NULL; char * memb_name = NULL, *temp = NULL; - hsize_t eof = HADDR_UNDEF; - unsigned t_flags = flags & ~H5F_ACC_CREAT; - H5FD_t * ret_value = NULL; + hsize_t eof = HADDR_UNDEF; + hbool_t default_config = FALSE; + unsigned t_flags = flags & ~H5F_ACC_CREAT; + H5FD_t * ret_value = NULL; FUNC_ENTER_STATIC @@ -605,21 +734,32 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad if (NULL == (file = (H5FD_family_t *)H5MM_calloc(sizeof(H5FD_family_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct") if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { - file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; - if (H5I_inc_ref(file->memb_fapl_id, FALSE) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") - file->memb_size = 1024 * 1024 * 1024; /*1GB. Actual member size to be updated later */ - file->pmem_size = 1024 * 1024 * 1024; /*1GB. Member size passed in through property */ - file->mem_newsize = 0; /*New member size used by h5repart only */ - } /* end if */ + H5FD_family_fapl_t default_fa; + + /* Get default configuration */ + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default driver configuration info") + + file->memb_fapl_id = default_fa.memb_fapl_id; + file->memb_size = H5FD_FAM_DEF_MEM_SIZE; /* Actual member size to be updated later */ + file->pmem_size = H5FD_FAM_DEF_MEM_SIZE; /* Member size passed in through property */ + file->mem_newsize = 0; /*New member size used by h5repart only */ + + default_config = TRUE; + } /* end if */ else { H5P_genplist_t * plist; /* Property list pointer */ const H5FD_family_fapl_t *fa; + H5FD_family_fapl_t default_fa; if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default family VFD configuration") + fa = &default_fa; + default_config = TRUE; + } /* Check for new family file size. It's used by h5repart only. */ if (H5P_exist_plist(plist, H5F_ACS_FAMILY_NEWSIZE_NAME) > 0) { @@ -643,7 +783,10 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad } /* end else */ file->memb_size = fa->memb_size; /* Actual member size to be updated later */ file->pmem_size = fa->memb_size; /* Member size passed in through property */ - } /* end else */ + + if (default_config && H5I_dec_ref(fa->memb_fapl_id) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTDEC, NULL, "can't decrement ref. count on member FAPL") + } /* end else */ file->name = H5MM_strdup(name); file->flags = flags; @@ -656,8 +799,16 @@ H5FD__family_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxad /* Check that names are unique */ HDsnprintf(memb_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 0); HDsnprintf(temp, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 1); - if (!HDstrcmp(memb_name, temp)) - HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique") + if (!HDstrcmp(memb_name, temp)) { + if (default_config) { + temp = H5MM_xfree(temp); + if (NULL == (temp = H5FD__family_get_default_printf_filename(name))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get default printf-style filename") + name = temp; + } + else + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique") + } /* Open all the family members */ while (1) { @@ -1361,7 +1512,9 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) { H5P_genplist_t * plist; const H5FD_family_fapl_t *fa; - hid_t memb_fapl_id = H5I_INVALID_HID; + H5FD_family_fapl_t default_fa = {0, H5I_INVALID_HID}; + hbool_t default_config = FALSE; + hid_t memb_fapl_id = H5I_INVALID_HID; unsigned current_member; char * member_name = NULL; char * temp = NULL; @@ -1375,13 +1528,21 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) /* Get the driver info (for the member fapl) * The family_open call accepts H5P_DEFAULT, so we'll accept that here, too. */ - if (H5P_FILE_ACCESS_DEFAULT == fapl_id) - memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default family VFD configuration") + memb_fapl_id = default_fa.memb_fapl_id; + default_config = TRUE; + } else { if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad family VFD driver info") + if (NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist))) { + if (H5FD__family_get_default_config(&default_fa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default family VFD configuration") + fa = &default_fa; + default_config = TRUE; + } memb_fapl_id = fa->memb_fapl_id; } @@ -1394,8 +1555,17 @@ H5FD__family_delete(const char *filename, hid_t fapl_id) /* Sanity check to make sure that generated names are unique */ HDsnprintf(member_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, filename, 0); HDsnprintf(temp, H5FD_FAM_MEMB_NAME_BUF_SIZE, filename, 1); - if (!HDstrcmp(member_name, temp)) - HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "provided file name cannot generate unique sub-files") + if (!HDstrcmp(member_name, temp)) { + if (default_config) { + temp = H5MM_xfree(temp); + if (NULL == (temp = H5FD__family_get_default_printf_filename(filename))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get default printf-style filename") + filename = temp; + } + else + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, + "provided file name cannot generate unique sub-files") + } /* Delete all the family members */ current_member = 0; @@ -1431,9 +1601,9 @@ done: if (temp) H5MM_xfree(temp); - /* Don't close memb_fapl_id - We didn't bump its reference count since we're - * only using it in this call. - */ + /* Only close memb_fapl_id if we created one from the default configuration */ + if (default_fa.memb_fapl_id >= 0 && H5I_dec_ref(default_fa.memb_fapl_id) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement ref. count on member FAPL ID") FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD__family_delete() */ diff --git a/src/H5FDfamily.h b/src/H5FDfamily.h index 20ef532..7b76a16 100644 --- a/src/H5FDfamily.h +++ b/src/H5FDfamily.h @@ -20,7 +20,8 @@ #ifndef H5FDfamily_H #define H5FDfamily_H -#define H5FD_FAMILY (H5FD_family_init()) +#define H5FD_FAMILY (H5FD_family_init()) +#define H5FD_FAMILY_VALUE H5_VFD_FAMILY #ifdef __cplusplus extern "C" { diff --git a/src/H5FDhdfs.c b/src/H5FDhdfs.c index ac48b42..bbaf42c 100644 --- a/src/H5FDhdfs.c +++ b/src/H5FDhdfs.c @@ -278,6 +278,7 @@ static herr_t H5FD__hdfs_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__hdfs_validate_config(const H5FD_hdfs_fapl_t *fa); static const H5FD_class_t H5FD_hdfs_g = { + H5FD_HDFS_VALUE, /* value */ "hdfs", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -624,7 +625,7 @@ H5Pset_fapl_hdfs(hid_t fapl_id, H5FD_hdfs_fapl_t *fa) if (FAIL == H5FD__hdfs_validate_config(fa)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid hdfs config") - ret_value = H5P_set_driver(plist, H5FD_HDFS, (void *)fa); + ret_value = H5P_set_driver(plist, H5FD_HDFS, (void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDhdfs.h b/src/H5FDhdfs.h index 7c871a4..a9f34a0 100644 --- a/src/H5FDhdfs.h +++ b/src/H5FDhdfs.h @@ -22,9 +22,11 @@ #define H5FDhdfs_H #ifdef H5_HAVE_LIBHDFS -#define H5FD_HDFS (H5FD_hdfs_init()) +#define H5FD_HDFS (H5FD_hdfs_init()) +#define H5FD_HDFS_VALUE H5_VFD_HDFS #else /* H5_HAVE_LIBHDFS */ -#define H5FD_HDFS (H5I_INVALID_HID) +#define H5FD_HDFS (H5I_INVALID_HID) +#define H5FD_HDFS_VALUE H5_VFD_INVALID #endif /* H5_HAVE_LIBHDFS */ #ifdef H5_HAVE_LIBHDFS diff --git a/src/H5FDint.c b/src/H5FDint.c index f13f222..c567499 100644 --- a/src/H5FDint.c +++ b/src/H5FDint.c @@ -35,6 +35,7 @@ #include "H5Fprivate.h" /* File access */ #include "H5FDpkg.h" /* File Drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5PLprivate.h" /* Plugins */ /****************/ /* Local Macros */ @@ -44,6 +45,20 @@ /* Local Typedefs */ /******************/ +/* Information needed for iterating over the registered VFD hid_t IDs. + * The name or value of the new VFD that is being registered is stored + * in the name (or value) field and the found_id field is initialized to + * H5I_INVALID_HID (-1). If we find a VFD with the same name / value, + * we set the found_id field to the existing ID for return to the function. + */ +typedef struct H5FD_get_driver_ud_t { + /* IN */ + H5PL_vfd_key_t key; + + /* OUT */ + hid_t found_id; /* The driver ID, if we found a match */ +} H5FD_get_driver_ud_t; + /********************/ /* Package Typedefs */ /********************/ @@ -51,6 +66,7 @@ /********************/ /* Local Prototypes */ /********************/ +static int H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data); /*********************/ /* Package Variables */ @@ -425,3 +441,358 @@ H5FD_delete(const char *filename, hid_t fapl_id) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_check_plugin_load + * + * Purpose: Check if a VFD plugin matches the search criteria, and can + * be loaded. + * + * Note: Matching the driver's name / value, but the driver having + * an incompatible version is not an error, but means that the + * driver isn't a "match". Setting the SUCCEED value to FALSE + * and not failing for that case allows the plugin framework + * to keep looking for other DLLs that match and have a + * compatible version. + * + * Return: SUCCEED / FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_check_plugin_load(const H5FD_class_t *cls, const H5PL_key_t *key, hbool_t *success) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(cls); + HDassert(key); + HDassert(success); + + /* Which kind of key are we looking for? */ + if (key->vfd.kind == H5FD_GET_DRIVER_BY_NAME) { + /* Check if plugin name matches VFD class name */ + if (cls->name && !HDstrcmp(cls->name, key->vfd.u.name)) + *success = TRUE; + } /* end if */ + else { + /* Sanity check */ + HDassert(key->vfd.kind == H5FD_GET_DRIVER_BY_VALUE); + + /* Check if plugin value matches VFD class value */ + if (cls->value == key->vfd.u.value) + *success = TRUE; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_check_plugin_load() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__get_driver_cb + * + * Purpose: Callback routine to search through registered VFDs + * + * Return: Success: H5_ITER_STOP if the class and op_data name + * members match. H5_ITER_CONT otherwise. + * Failure: Can't fail + * + *------------------------------------------------------------------------- + */ +static int +H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data) +{ + H5FD_get_driver_ud_t *op_data = (H5FD_get_driver_ud_t *)_op_data; /* User data for callback */ + H5FD_class_t * cls = (H5FD_class_t *)obj; + int ret_value = H5_ITER_CONT; /* Callback return value */ + + FUNC_ENTER_STATIC_NOERR + + if (H5FD_GET_DRIVER_BY_NAME == op_data->key.kind) { + if (0 == HDstrcmp(cls->name, op_data->key.u.name)) { + op_data->found_id = id; + ret_value = H5_ITER_STOP; + } /* end if */ + } /* end if */ + else { + HDassert(H5FD_GET_DRIVER_BY_VALUE == op_data->key.kind); + if (cls->value == op_data->key.u.value) { + op_data->found_id = id; + ret_value = H5_ITER_STOP; + } /* end if */ + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__get_driver_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_register_driver_by_name + * + * Purpose: Registers a new VFD as a member of the virtual file driver + * class. + * + * Return: Success: A VFD ID which is good until the library is + * closed. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_register_driver_by_name(const char *name, hbool_t app_ref) +{ + htri_t driver_is_registered = FALSE; + hid_t driver_id = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Check if driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_name(name, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't check if driver is already registered") + + /* If driver is already registered, increment ref count on ID and return ID */ + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, app_ref) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFD") + } /* end if */ + else { + H5PL_key_t key; + const H5FD_class_t *cls; + + /* Try loading the driver */ + key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; + key.vfd.u.name = name; + if (NULL == (cls = (const H5FD_class_t *)H5PL_load(H5PL_TYPE_VFD, &key))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VFD") + + /* Register the driver we loaded */ + if ((driver_id = H5FD_register(cls, sizeof(*cls), app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VFD ID") + } /* end else */ + + ret_value = driver_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_register_driver_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_register_driver_by_value + * + * Purpose: Registers a new VFD as a member of the virtual file driver + * class. + * + * Return: Success: A VFD ID which is good until the library is + * closed. + * + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_register_driver_by_value(H5FD_class_value_t value, hbool_t app_ref) +{ + htri_t driver_is_registered = FALSE; + hid_t driver_id = H5I_INVALID_HID; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Check if driver is already registered */ + if ((driver_is_registered = H5FD_is_driver_registered_by_value(value, &driver_id)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't check if driver is already registered") + + /* If driver is already registered, increment ref count on ID and return ID */ + if (driver_is_registered) { + HDassert(driver_id >= 0); + + if (H5I_inc_ref(driver_id, app_ref) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFD") + } /* end if */ + else { + H5PL_key_t key; + const H5FD_class_t *cls; + + /* Try loading the driver */ + key.vfd.kind = H5FD_GET_DRIVER_BY_VALUE; + key.vfd.u.value = value; + if (NULL == (cls = (const H5FD_class_t *)H5PL_load(H5PL_TYPE_VFD, &key))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VFD") + + /* Register the driver we loaded */ + if ((driver_id = H5FD_register(cls, sizeof(*cls), app_ref)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VFD ID") + } /* end else */ + + ret_value = driver_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_register_driver_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_is_driver_registered_by_name + * + * Purpose: Checks if a driver with a particular name is registered. + * If `registered_id` is non-NULL and a driver with the + * specified name has been registered, the driver's ID will be + * returned in `registered_id`. + * + * Return: >0 if a VFD with that name has been registered + * 0 if a VFD with that name has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FD_is_driver_registered_by_name(const char *driver_name, hid_t *registered_id) +{ + H5FD_get_driver_ud_t op_data; /* Callback info for driver search */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_NAME; + op_data.key.u.name = driver_name; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with name */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, FAIL, "can't iterate over VFDs") + + /* Found a driver with that name */ + if (op_data.found_id != H5I_INVALID_HID) { + if (registered_id) + *registered_id = op_data.found_id; + ret_value = TRUE; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_is_driver_registered_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_is_driver_registered_by_value + * + * Purpose: Checks if a driver with a particular value (ID) is + * registered. If `registered_id` is non-NULL and a driver + * with the specified value has been registered, the driver's + * ID will be returned in `registered_id`. + * + * Return: >0 if a VFD with that value has been registered + * 0 if a VFD with that value has NOT been registered + * <0 on errors + * + *------------------------------------------------------------------------- + */ +htri_t +H5FD_is_driver_registered_by_value(H5FD_class_value_t driver_value, hid_t *registered_id) +{ + H5FD_get_driver_ud_t op_data; /* Callback info for driver search */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_VALUE; + op_data.key.u.value = driver_value; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with value */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, FAIL, "can't iterate over VFDs") + + /* Found a driver with that value */ + if (op_data.found_id != H5I_INVALID_HID) { + if (registered_id) + *registered_id = op_data.found_id; + ret_value = TRUE; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_is_driver_registered_by_value() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_get_driver_id_by_name + * + * Purpose: Retrieves the ID for a registered VFL driver. + * + * Return: Positive if the VFL driver has been registered + * Negative on error (if the driver is not a valid driver or + * is not registered) + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_get_driver_id_by_name(const char *name, hbool_t is_api) +{ + H5FD_get_driver_ud_t op_data; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with specified name */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VFL drivers") + + /* Found a driver with that name */ + if (op_data.found_id != H5I_INVALID_HID) { + ret_value = op_data.found_id; + if (H5I_inc_ref(ret_value, is_api) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFL driver") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_driver_id_by_name() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_get_driver_id_by_value + * + * Purpose: Retrieves the ID for a registered VFL driver. + * + * Return: Positive if the VFL driver has been registered + * Negative on error (if the driver is not a valid driver or + * is not registered) + * + *------------------------------------------------------------------------- + */ +hid_t +H5FD_get_driver_id_by_value(H5FD_class_value_t value, hbool_t is_api) +{ + H5FD_get_driver_ud_t op_data; + hid_t ret_value = H5I_INVALID_HID; /* Return value */ + + FUNC_ENTER_NOAPI(H5I_INVALID_HID) + + /* Set up op data for iteration */ + op_data.key.kind = H5FD_GET_DRIVER_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; + + /* Find driver with specified value */ + if (H5I_iterate(H5I_VFL, H5FD__get_driver_cb, &op_data, FALSE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VFL drivers") + + /* Found a driver with that value */ + if (op_data.found_id != H5I_INVALID_HID) { + ret_value = op_data.found_id; + if (H5I_inc_ref(ret_value, is_api) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VFL driver") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_driver_id_by_value() */ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 87871ab..1828a88 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -180,42 +180,46 @@ static herr_t H5FD__log_unlock(H5FD_t *_file); static herr_t H5FD__log_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_log_g = { - "log", /* name */ - MAXADDR, /* maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ - H5FD__log_term, /* terminate */ - NULL, /* sb_size */ - NULL, /* sb_encode */ - NULL, /* sb_decode */ - sizeof(H5FD_log_fapl_t), /* fapl_size */ - H5FD__log_fapl_get, /* fapl_get */ - H5FD__log_fapl_copy, /* fapl_copy */ - H5FD__log_fapl_free, /* fapl_free */ - 0, /* dxpl_size */ - NULL, /* dxpl_copy */ - NULL, /* dxpl_free */ - H5FD__log_open, /* open */ - H5FD__log_close, /* close */ - H5FD__log_cmp, /* cmp */ - H5FD__log_query, /* query */ - NULL, /* get_type_map */ - H5FD__log_alloc, /* alloc */ - H5FD__log_free, /* free */ - H5FD__log_get_eoa, /* get_eoa */ - H5FD__log_set_eoa, /* set_eoa */ - H5FD__log_get_eof, /* get_eof */ - H5FD__log_get_handle, /* get_handle */ - H5FD__log_read, /* read */ - H5FD__log_write, /* write */ - NULL, /* flush */ - H5FD__log_truncate, /* truncate */ - H5FD__log_lock, /* lock */ - H5FD__log_unlock, /* unlock */ - H5FD__log_delete, /* del */ - NULL, /* ctl */ - H5FD_FLMAP_DICHOTOMY /* fl_map */ + H5FD_LOG_VALUE, /* value */ + "log", /* name */ + MAXADDR, /* maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ + H5FD__log_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + sizeof(H5FD_log_fapl_t), /* fapl_size */ + H5FD__log_fapl_get, /* fapl_get */ + H5FD__log_fapl_copy, /* fapl_copy */ + H5FD__log_fapl_free, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD__log_open, /* open */ + H5FD__log_close, /* close */ + H5FD__log_cmp, /* cmp */ + H5FD__log_query, /* query */ + NULL, /* get_type_map */ + H5FD__log_alloc, /* alloc */ + H5FD__log_free, /* free */ + H5FD__log_get_eoa, /* get_eoa */ + H5FD__log_set_eoa, /* set_eoa */ + H5FD__log_get_eof, /* get_eof */ + H5FD__log_get_handle, /* get_handle */ + H5FD__log_read, /* read */ + H5FD__log_write, /* write */ + NULL, /* flush */ + H5FD__log_truncate, /* truncate */ + H5FD__log_lock, /* lock */ + H5FD__log_unlock, /* unlock */ + H5FD__log_delete, /* del */ + NULL, /* ctl */ + H5FD_FLMAP_DICHOTOMY /* fl_map */ }; +/* Default configuration, if none provided */ +static const H5FD_log_fapl_t H5FD_log_default_config_g = {NULL, H5FD_LOG_LOC_IO | H5FD_LOG_ALLOC, 4096}; + /* Declare a free list to manage the H5FD_log_t struct */ H5FL_DEFINE_STATIC(H5FD_log_t); @@ -237,7 +241,7 @@ H5FD__init_package(void) FUNC_ENTER_STATIC /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) @@ -348,7 +352,7 @@ H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned long long flags, si fa.flags = flags; fa.buf_size = buf_size; - ret_value = H5P_set_driver(plist, H5FD_LOG, &fa); + ret_value = H5P_set_driver(plist, H5FD_LOG, &fa, NULL); done: if (fa.logfile) @@ -483,10 +487,11 @@ static H5FD_t * H5FD__log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { H5FD_log_t * file = NULL; - H5P_genplist_t * plist; /* Property list */ - const H5FD_log_fapl_t *fa; /* File access property list information */ - int fd = -1; /* File descriptor */ - int o_flags; /* Flags for open() call */ + H5P_genplist_t * plist; /* Property list */ + const H5FD_log_fapl_t *fa; /* File access property list information */ + H5FD_log_fapl_t default_fa = H5FD_log_default_config_g; + int fd = -1; /* File descriptor */ + int o_flags; /* Flags for open() call */ #ifdef H5_HAVE_WIN32_API struct _BY_HANDLE_FILE_INFORMATION fileinfo; #endif @@ -524,8 +529,10 @@ H5FD__log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) /* Get the driver specific information */ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - if (NULL == (fa = (const H5FD_log_fapl_t *)H5P_peek_driver_info(plist))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info") + if (NULL == (fa = (const H5FD_log_fapl_t *)H5P_peek_driver_info(plist))) { + /* Use default driver configuration*/ + fa = &default_fa; + } /* Start timer for open() call */ if (fa->flags & H5FD_LOG_TIME_OPEN) diff --git a/src/H5FDlog.h b/src/H5FDlog.h index 969c091..bc96c52 100644 --- a/src/H5FDlog.h +++ b/src/H5FDlog.h @@ -20,7 +20,8 @@ #ifndef H5FDlog_H #define H5FDlog_H -#define H5FD_LOG (H5FD_log_init()) +#define H5FD_LOG (H5FD_log_init()) +#define H5FD_LOG_VALUE H5_VFD_LOG /* Flags for H5Pset_fapl_log() */ /* Flags for tracking 'meta' operations (truncate) */ diff --git a/src/H5FDmirror.c b/src/H5FDmirror.c index d539f4d..738e9d5 100644 --- a/src/H5FDmirror.c +++ b/src/H5FDmirror.c @@ -160,6 +160,7 @@ static herr_t H5FD__mirror_unlock(H5FD_t *_file); static herr_t H5FD__mirror_verify_reply(H5FD_mirror_t *file); static const H5FD_class_t H5FD_mirror_g = { + H5FD_MIRROR_VALUE, /* value */ "mirror", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -1336,7 +1337,7 @@ H5Pset_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa) if (H5FD_MIRROR_CURR_FAPL_T_VERSION != fa->version) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown fapl_t version"); - ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa); + ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDmirror.h b/src/H5FDmirror.h index 49e24c1..66954b1 100644 --- a/src/H5FDmirror.h +++ b/src/H5FDmirror.h @@ -19,7 +19,8 @@ #ifdef H5_HAVE_MIRROR_VFD -#define H5FD_MIRROR (H5FD_mirror_init()) +#define H5FD_MIRROR (H5FD_mirror_init()) +#define H5FD_MIRROR_VALUE H5_VFD_MIRROR #ifdef __cplusplus extern "C" { diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 7c85897..f4d3fed 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -45,6 +45,9 @@ static hid_t H5FD_MPIO_g = 0; /* (Can be changed by setting "HDF5_MPI_OPT_TYPES" environment variable to '0' or '1') */ hbool_t H5FD_mpi_opt_types_g = TRUE; +/* Whether the driver initialized MPI on its own */ +hbool_t H5FD_mpi_self_initialized = FALSE; + /* * The view is set to this value */ @@ -92,6 +95,7 @@ static herr_t H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, c /* The MPIO file driver information */ static const H5FD_class_t H5FD_mpio_g = { + H5_VFD_MPIO, /* value */ "mpio", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_SEMI, /* fc_degree */ @@ -233,6 +237,7 @@ hid_t H5FD_mpio_init(void) { static int H5FD_mpio_Debug_inited = 0; + char * env = NULL; hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_NOAPI(H5I_INVALID_HID) @@ -241,6 +246,21 @@ H5FD_mpio_init(void) if (H5I_VFL != H5I_get_type(H5FD_MPIO_g)) H5FD_MPIO_g = H5FD_register((const H5FD_class_t *)&H5FD_mpio_g, sizeof(H5FD_class_t), FALSE); + /* Check if MPI driver has been loaded dynamically */ + env = HDgetenv(HDF5_DRIVER); + if (env && !HDstrcmp(env, "mpio")) { + int mpi_initialized = 0; + + /* Initialize MPI if not already initialized */ + if (MPI_SUCCESS != MPI_Initialized(&mpi_initialized)) + HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, H5I_INVALID_HID, "can't check if MPI is initialized") + if (!mpi_initialized) { + if (MPI_SUCCESS != MPI_Init(NULL, NULL)) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, H5I_INVALID_HID, "can't initialize MPI") + H5FD_mpi_self_initialized = TRUE; + } + } + if (!H5FD_mpio_Debug_inited) { const char *s; /* String for environment variables */ @@ -286,6 +306,17 @@ H5FD__mpio_term(void) { FUNC_ENTER_STATIC_NOERR + /* Terminate MPI if the driver initialized it */ + if (H5FD_mpi_self_initialized) { + int mpi_finalized = 0; + + MPI_Finalized(&mpi_finalized); + if (!mpi_finalized) + MPI_Finalize(); + + H5FD_mpi_self_initialized = FALSE; + } + /* Reset VFL ID */ H5FD_MPIO_g = 0; @@ -347,7 +378,7 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI info object") /* duplication is done during driver setting. */ - ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL); + ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL, NULL); done: FUNC_LEAVE_API(ret_value) @@ -802,11 +833,16 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t H5_ATTR if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - /* Get the MPI communicator and info object from the property list */ - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI communicator") - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI info object") + if (H5FD_mpi_self_initialized) { + comm = MPI_COMM_WORLD; + } + else { + /* Get the MPI communicator and info object from the property list */ + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI communicator") + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI info object") + } /* Get the MPI rank of this process and the total number of processes */ if (MPI_SUCCESS != (mpi_code = MPI_Comm_rank(comm, &mpi_rank))) @@ -1768,11 +1804,16 @@ H5FD__mpio_delete(const char *filename, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") HDassert(H5FD_MPIO == H5P_peek_driver(plist)); - /* Get the MPI communicator and info from the fapl */ - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI info object") - if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") + if (H5FD_mpi_self_initialized) { + comm = MPI_COMM_WORLD; + } + else { + /* Get the MPI communicator and info from the fapl */ + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI info object") + if (H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI communicator") + } /* Get the MPI rank of this process */ if (MPI_SUCCESS != (mpi_code = MPI_Comm_rank(comm, &mpi_rank))) diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index 0d1967d..3dcfa37 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -135,8 +135,13 @@ typedef struct H5FD_multi_dxpl_t { } H5FD_multi_dxpl_t; /* Private functions */ -static int compute_next(H5FD_multi_t *file); -static int open_members(H5FD_multi_t *file); +static herr_t H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, + hid_t raw_plist_id, hbool_t relax, H5FD_multi_fapl_t *fa_out); +static herr_t H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, + const char *const *memb_name, const haddr_t *memb_addr, + hbool_t relax, H5FD_multi_fapl_t *fa_out); +static int compute_next(H5FD_multi_t *file); +static int open_members(H5FD_multi_t *file); /* Callback prototypes */ static herr_t H5FD_multi_term(void); @@ -171,6 +176,7 @@ static herr_t H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, c /* The class struct */ static const H5FD_class_t H5FD_multi_g = { + H5_VFD_MULTI, /* value */ "multi", /* name */ HADDR_MAX, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -274,74 +280,19 @@ herr_t H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, hid_t raw_plist_id) { - H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; - hid_t memb_fapl[H5FD_MEM_NTYPES]; - const char *memb_name[H5FD_MEM_NTYPES]; - char meta_name[H5FD_MULT_MAX_FILE_NAME_LEN]; - char raw_name[H5FD_MULT_MAX_FILE_NAME_LEN]; - haddr_t memb_addr[H5FD_MEM_NTYPES]; + H5FD_multi_fapl_t fa; + static const char *func = "H5Pset_fapl_split"; /* Function Name for error reporting */ /*NO TRACE*/ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); - /* Initialize */ - ALL_MEMBERS (mt) { - /* Treat global heap as raw data, not metadata */ - memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER); - memb_fapl[mt] = -1; - memb_name[mt] = NULL; - memb_addr[mt] = HADDR_UNDEF; - } - END_MEMBERS; - - /* The file access properties */ - memb_fapl[H5FD_MEM_SUPER] = meta_plist_id; - memb_fapl[H5FD_MEM_DRAW] = raw_plist_id; - - /* The names */ - /* process meta filename */ - if (meta_ext) { - if (strstr(meta_ext, "%s")) { - /* Note: this doesn't accommodate for when the '%s' in the user's - * string is at a position >sizeof(meta_name) - QK & JK - 2013/01/17 - */ - strncpy(meta_name, meta_ext, sizeof(meta_name)); - meta_name[sizeof(meta_name) - 1] = '\0'; - } - else - sprintf(meta_name, "%%s%s", meta_ext); - } - else { - strncpy(meta_name, "%s.meta", sizeof(meta_name)); - meta_name[sizeof(meta_name) - 1] = '\0'; - } - memb_name[H5FD_MEM_SUPER] = meta_name; - - /* process raw filename */ - if (raw_ext) { - if (strstr(raw_ext, "%s")) { - /* Note: this doesn't accommodate for when the '%s' in the user's - * string is at a position >sizeof(raw_name) - QK & JK - 2013/01/17 - */ - strncpy(raw_name, raw_ext, sizeof(raw_name)); - raw_name[sizeof(raw_name) - 1] = '\0'; - } - else - sprintf(raw_name, "%%s%s", raw_ext); - } - else { - strncpy(raw_name, "%s.raw", sizeof(raw_name)); - raw_name[sizeof(raw_name) - 1] = '\0'; - } - memb_name[H5FD_MEM_DRAW] = raw_name; - - /* The sizes */ - memb_addr[H5FD_MEM_SUPER] = 0; - memb_addr[H5FD_MEM_DRAW] = HADDR_MAX / 2; + if (H5FD_split_populate_config(meta_ext, meta_plist_id, raw_ext, raw_plist_id, TRUE, &fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "can't setup split driver configuration", + -1); - return H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, TRUE); + return H5Pset_driver(fapl, H5FD_MULTI, &fa); } /*------------------------------------------------------------------------- @@ -425,14 +376,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_f const char *const *memb_name, const haddr_t *memb_addr, hbool_t relax) { H5FD_multi_fapl_t fa; - H5FD_mem_t mt, mmt; - H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; - hid_t _memb_fapl[H5FD_MEM_NTYPES]; - char _memb_name[H5FD_MEM_NTYPES][16]; - const char * _memb_name_ptrs[H5FD_MEM_NTYPES]; - haddr_t _memb_addr[H5FD_MEM_NTYPES]; - static const char *letters = "Xsbrglo"; - static const char *func = "H5FDset_fapl_multi"; /* Function Name for error reporting */ + static const char *func = "H5FDset_fapl_multi"; /* Function Name for error reporting */ /*NO TRACE*/ @@ -442,66 +386,9 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_f /* Check arguments and supply default values */ if (H5I_GENPROP_LST != H5Iget_type(fapl_id) || TRUE != H5Pisa_class(fapl_id, H5P_FILE_ACCESS)) H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "not an access list", -1); - if (!memb_map) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_map[mt] = H5FD_MEM_DEFAULT; - memb_map = _memb_map; - } - if (!memb_fapl) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); - memb_fapl = _memb_fapl; - } - if (!memb_name) { - assert(strlen(letters) == H5FD_MEM_NTYPES); - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - sprintf(_memb_name[mt], "%%s-%c.h5", letters[mt]); - _memb_name_ptrs[mt] = _memb_name[mt]; - } - memb_name = _memb_name_ptrs; - } - if (!memb_addr) { - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) - _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES - 1)); - memb_addr = _memb_addr; - } - - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - /* Map usage type */ - mmt = memb_map[mt]; - if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); - if (H5FD_MEM_DEFAULT == mmt) - mmt = mt; + if (H5FD_multi_populate_config(memb_map, memb_fapl, memb_name, memb_addr, relax, &fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "can't setup driver configuration", -1); - /* - * All members of MEMB_FAPL must be either defaults or actual file - * access property lists. - */ - if (H5P_DEFAULT != memb_fapl[mmt] && TRUE != H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS)) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); - - /* All names must be defined */ - if (!memb_name[mmt] || !memb_name[mmt][0]) - H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); - } - - /* - * Initialize driver specific information. No need to copy it into the FA - * struct since all members will be copied by H5Pset_driver(). - */ - memset(&fa, 0, sizeof(H5FD_multi_fapl_t)); - memcpy(fa.memb_map, memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); - memcpy(fa.memb_fapl, memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); - memcpy(fa.memb_name, memb_name, H5FD_MEM_NTYPES * sizeof(char *)); - memcpy(fa.memb_addr, memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); - fa.relax = relax; - - /* Patch up H5P_DEFAULT property lists for members */ - for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { - if (fa.memb_fapl[mt] == H5P_DEFAULT) - fa.memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); - } return H5Pset_driver(fapl_id, H5FD_MULTI, &fa); } @@ -526,6 +413,7 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl char **memb_name /*out*/, haddr_t *memb_addr /*out*/, hbool_t *relax) { const H5FD_multi_fapl_t *fa; + H5FD_multi_fapl_t default_fa; H5FD_mem_t mt; static const char * func = "H5FDget_fapl_multi"; /* Function Name for error reporting */ @@ -538,8 +426,17 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not an access list", -1); if (H5FD_MULTI != H5Pget_driver(fapl_id)) H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1); - if (NULL == (fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id))) - H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "bad VFL driver info", -1); + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id)) { + if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup default driver configuration", + -1); + fa = &default_fa; + } if (memb_map) memcpy(memb_map, fa->memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); @@ -568,6 +465,231 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl } /*------------------------------------------------------------------------- + * Function: H5FD_split_populate_config + * + * Purpose: Populates a H5FD_multi_fapl_t structure with the provided + * split driver values, supplying defaults where values are not + * provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, hid_t raw_plist_id, + hbool_t relax, H5FD_multi_fapl_t *fa_out) +{ + static const char *func = "H5FD_split_populate_config"; /* Function Name for error reporting */ + static char + meta_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store metadata member name */ + static char + raw_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store raw data member name */ + const char *_memb_name[H5FD_MEM_NTYPES]; + H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; + hid_t _memb_fapl[H5FD_MEM_NTYPES]; + haddr_t _memb_addr[H5FD_MEM_NTYPES]; + herr_t ret_value = 0; + + assert(fa_out); + + /* Initialize */ + ALL_MEMBERS (mt) { + /* Treat global heap as raw data, not metadata */ + _memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER); + _memb_fapl[mt] = H5P_DEFAULT; + _memb_name[mt] = NULL; + _memb_addr[mt] = HADDR_UNDEF; + } + END_MEMBERS; + + /* The file access properties */ + _memb_fapl[H5FD_MEM_SUPER] = meta_plist_id; + _memb_fapl[H5FD_MEM_DRAW] = raw_plist_id; + + /* The names */ + /* process meta filename */ + if (meta_ext) { + if (strstr(meta_ext, "%s")) { + /* Note: this doesn't accommodate for when the '%s' in the user's + * string is at a position >sizeof(meta_name) - QK & JK - 2013/01/17 + */ + strncpy(meta_name_g, meta_ext, sizeof(meta_name_g)); + meta_name_g[sizeof(meta_name_g) - 1] = '\0'; + } + else + sprintf(meta_name_g, "%%s%s", meta_ext); + } + else { + strncpy(meta_name_g, "%s.meta", sizeof(meta_name_g)); + meta_name_g[sizeof(meta_name_g) - 1] = '\0'; + } + _memb_name[H5FD_MEM_SUPER] = meta_name_g; + + /* process raw filename */ + if (raw_ext) { + if (strstr(raw_ext, "%s")) { + /* Note: this doesn't accommodate for when the '%s' in the user's + * string is at a position >sizeof(raw_name) - QK & JK - 2013/01/17 + */ + strncpy(raw_name_g, raw_ext, sizeof(raw_name_g)); + raw_name_g[sizeof(raw_name_g) - 1] = '\0'; + } + else + sprintf(raw_name_g, "%%s%s", raw_ext); + } + else { + strncpy(raw_name_g, "%s.raw", sizeof(raw_name_g)); + raw_name_g[sizeof(raw_name_g) - 1] = '\0'; + } + _memb_name[H5FD_MEM_DRAW] = raw_name_g; + + /* The sizes */ + _memb_addr[H5FD_MEM_SUPER] = 0; + _memb_addr[H5FD_MEM_DRAW] = HADDR_MAX / 2; + + ALL_MEMBERS (mt) { + /* Map usage type */ + H5FD_mem_t mmt = _memb_map[mt]; + if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); + + /* + * All members of MEMB_FAPL must be either defaults or actual file + * access property lists. + */ + if (H5P_DEFAULT != _memb_fapl[mmt] && TRUE != H5Pisa_class(_memb_fapl[mmt], H5P_FILE_ACCESS)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); + + /* All names must be defined */ + if (!_memb_name[mmt] || !_memb_name[mmt][0]) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); + } + END_MEMBERS; + + /* + * Initialize driver specific information. No need to copy it into the FA + * struct since all members will be copied by H5Pset_driver(). + */ + memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); + memcpy(fa_out->memb_map, _memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); + memcpy(fa_out->memb_fapl, _memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); + memcpy(fa_out->memb_name, _memb_name, H5FD_MEM_NTYPES * sizeof(char *)); + memcpy(fa_out->memb_addr, _memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); + fa_out->relax = relax; + + /* Patch up H5P_DEFAULT property lists for members */ + ALL_MEMBERS (mt) { + if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { + fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + } + END_MEMBERS; + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: H5FD_multi_populate_config + * + * Purpose: Populates a H5FD_multi_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, const char *const *memb_name, + const haddr_t *memb_addr, hbool_t relax, H5FD_multi_fapl_t *fa_out) +{ + static const char *func = "H5FD_multi_populate_config"; /* Function Name for error reporting */ + static const char *letters = "Xsbrglo"; + static char _memb_name_g[H5FD_MEM_NTYPES][16]; /* Static scratch buffer to store member names */ + H5FD_mem_t mt, mmt; + H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; + hid_t _memb_fapl[H5FD_MEM_NTYPES]; + const char * _memb_name_ptrs[H5FD_MEM_NTYPES]; + haddr_t _memb_addr[H5FD_MEM_NTYPES]; + herr_t ret_value = 0; + + assert(fa_out); + + if (!memb_map) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) + _memb_map[mt] = H5FD_MEM_DEFAULT; + memb_map = _memb_map; + } + if (!memb_fapl) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + _memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(_memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + memb_fapl = _memb_fapl; + } + if (!memb_name) { + assert(strlen(letters) == H5FD_MEM_NTYPES); + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + sprintf(_memb_name_g[mt], "%%s-%c.h5", letters[mt]); + _memb_name_ptrs[mt] = _memb_name_g[mt]; + } + memb_name = _memb_name_ptrs; + } + if (!memb_addr) { + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) + _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES - 1)); + memb_addr = _memb_addr; + } + + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + /* Map usage type */ + mmt = memb_map[mt]; + if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1); + if (H5FD_MEM_DEFAULT == mmt) + mmt = mt; + + /* + * All members of MEMB_FAPL must be either defaults or actual file + * access property lists. + */ + if (H5P_DEFAULT != memb_fapl[mmt] && TRUE != H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1); + + /* All names must be defined */ + if (!memb_name[mmt] || !memb_name[mmt][0]) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); + } + + /* + * Initialize driver specific information. No need to copy it into the FA + * struct since all members will be copied by H5Pset_driver(). + */ + memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); + memcpy(fa_out->memb_map, memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); + memcpy(fa_out->memb_fapl, memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); + memcpy(fa_out->memb_name, memb_name, H5FD_MEM_NTYPES * sizeof(char *)); + memcpy(fa_out->memb_addr, memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); + fa_out->relax = relax; + + /* Patch up H5P_DEFAULT property lists for members */ + for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { + fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); + if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, + "can't set sec2 driver on member FAPL", -1); + } + } + + return ret_value; +} /* end H5FD_multi_populate_config() */ + +/*------------------------------------------------------------------------- * Function: H5FD_multi_sb_size * * Purpose: Returns the size of the private information to be stored in @@ -1012,12 +1134,26 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr */ if (NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t)))) H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL); - if (H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MULTI != H5Pget_driver(fapl_id)) { + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id) || (H5FD_MULTI != H5Pget_driver(fapl_id))) { + char *env = getenv(HDF5_DRIVER); + close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS); - if (H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0) - H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + if (env && !strcmp(env, "split")) { + if (H5Pset_fapl_split(fapl_id, NULL, H5P_DEFAULT, NULL, H5P_DEFAULT) < 0) + H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + } + else { + if (H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0) + H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error) + } + + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); } - fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); assert(fa); ALL_MEMBERS (mt) { file->fa.memb_map[mt] = fa->memb_map[mt]; @@ -2040,6 +2176,7 @@ H5FD_multi_delete(const char *filename, hid_t fapl_id) char full_filename[H5FD_MULT_MAX_FILE_NAME_LEN]; int nchars; const H5FD_multi_fapl_t *fa; + H5FD_multi_fapl_t default_fa; static const char * func = "H5FD_multi_delete"; /* Function Name for error reporting */ /* Clear the error stack */ @@ -2047,11 +2184,26 @@ H5FD_multi_delete(const char *filename, hid_t fapl_id) assert(filename); - /* Quiet compiler */ - (void)fapl_id; - /* Get the driver info */ - fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + H5E_BEGIN_TRY + { + fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); + } + H5E_END_TRY; + if (!fa) { + char *env = getenv(HDF5_DRIVER); + + if (env && !strcmp(env, "split")) { + if (H5FD_split_populate_config(NULL, H5P_DEFAULT, NULL, H5P_DEFAULT, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", -1); + } + else { + if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, TRUE, &default_fa) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", -1); + } + + fa = &default_fa; + } assert(fa); /* Delete each member file using the underlying fapl */ diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 6dbd483..fa562f9 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -81,12 +81,19 @@ typedef struct { } \ } -/* Define structure to hold driver ID & info for FAPLs */ +/* Define structure to hold driver ID, info & configuration string for FAPLs */ typedef struct { - hid_t driver_id; /* Driver's ID */ - const void *driver_info; /* Driver info, for open callbacks */ + hid_t driver_id; /* Driver's ID */ + const void *driver_info; /* Driver info, for open callbacks */ + const char *driver_config_str; /* Driver configuration string */ } H5FD_driver_prop_t; +/* Which kind of VFD field to use for searching */ +typedef enum H5FD_get_driver_kind_t { + H5FD_GET_DRIVER_BY_NAME, /* Name field is set */ + H5FD_GET_DRIVER_BY_VALUE /* Value field is set */ +} H5FD_get_driver_kind_t; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -97,6 +104,7 @@ typedef struct { /* Forward declarations for prototype arguments */ struct H5F_t; +union H5PL_key_t; H5_DLL int H5FD_term_interface(void); H5_DLL herr_t H5FD_locate_signature(H5FD_t *file, haddr_t *sig_addr); @@ -107,10 +115,17 @@ H5_DLL herr_t H5FD_sb_load(H5FD_t *file, const char *name, const uint8_t H5_DLL void * H5FD_fapl_get(H5FD_t *file); H5_DLL herr_t H5FD_free_driver_info(hid_t driver_id, const void *driver_info); H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref); +H5_DLL hid_t H5FD_register_driver_by_name(const char *name, hbool_t app_ref); +H5_DLL hid_t H5FD_register_driver_by_value(H5FD_class_value_t value, hbool_t app_ref); +H5_DLL htri_t H5FD_is_driver_registered_by_name(const char *driver_name, hid_t *registered_id); +H5_DLL htri_t H5FD_is_driver_registered_by_value(H5FD_class_value_t driver_value, hid_t *registered_id); +H5_DLL hid_t H5FD_get_driver_id_by_name(const char *name, hbool_t is_api); +H5_DLL hid_t H5FD_get_driver_id_by_value(H5FD_class_value_t value, hbool_t is_api); H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FD_close(H5FD_t *file); H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2); H5_DLL herr_t H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/); +H5_DLL herr_t H5FD_check_plugin_load(const H5FD_class_t *cls, const union H5PL_key_t *key, hbool_t *success); H5_DLL haddr_t H5FD_alloc(H5FD_t *file, H5FD_mem_t type, struct H5F_t *f, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size); H5_DLL herr_t H5FD_free(H5FD_t *file, H5FD_mem_t type, struct H5F_t *f, haddr_t addr, hsize_t size); diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index b8f4f12..a72dc80 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -28,6 +28,39 @@ #define H5FD_VFD_DEFAULT 0 /* Default VFL driver value */ +/* VFD identifier values + * These are H5FD_class_value_t values, NOT hid_t values! + */ +#define H5_VFD_INVALID ((H5FD_class_value_t)(-1)) +#define H5_VFD_SEC2 ((H5FD_class_value_t)(0)) +#define H5_VFD_CORE ((H5FD_class_value_t)(1)) +#define H5_VFD_LOG ((H5FD_class_value_t)(2)) +#define H5_VFD_FAMILY ((H5FD_class_value_t)(3)) +#define H5_VFD_MULTI ((H5FD_class_value_t)(4)) +#define H5_VFD_STDIO ((H5FD_class_value_t)(5)) +#define H5_VFD_SPLITTER ((H5FD_class_value_t)(6)) +#ifdef H5_HAVE_PARALLEL +#define H5_VFD_MPIO ((H5FD_class_value_t)(7)) +#endif +#ifdef H5_HAVE_DIRECT +#define H5_VFD_DIRECT ((H5FD_class_value_t)(8)) +#endif +#ifdef H5_HAVE_MIRROR_VFD +#define H5_VFD_MIRROR ((H5FD_class_value_t)(9)) +#endif +#ifdef H5_HAVE_LIBHDFS +#define H5_VFD_HDFS ((H5FD_class_value_t)(10)) +#endif +#ifdef H5_HAVE_ROS3_VFD +#define H5_VFD_ROS3 ((H5FD_class_value_t)(11)) +#endif + +/* VFD IDs below this value are reserved for library use. */ +#define H5_VFD_RESERVED 256 + +/* Maximum VFD ID */ +#define H5_VFD_MAX 65535 + /* Define VFL driver features that can be enabled on a per-driver basis */ /* These are returned with the 'query' function pointer in H5FD_class_t */ /* @@ -213,6 +246,16 @@ /* Public Typedefs */ /*******************/ +/* + * File driver identifiers. + * + * Values 0 through 255 are for drivers defined by the HDF5 library. + * Values 256 through 511 are available for testing new drivers. + * Subsequent values should be obtained from the HDF5 development + * team at mailto:help@hdfgroup.org. + */ +typedef int H5FD_class_value_t; + /* Types of allocation requests: see H5Fpublic.h */ typedef enum H5F_mem_t H5FD_mem_t; diff --git a/src/H5FDros3.c b/src/H5FDros3.c index a32d65e..2ffee17 100644 --- a/src/H5FDros3.c +++ b/src/H5FDros3.c @@ -237,6 +237,7 @@ static herr_t H5FD__ros3_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing static herr_t H5FD__ros3_validate_config(const H5FD_ros3_fapl_t *fa); static const H5FD_class_t H5FD_ros3_g = { + H5FD_ROS3_VALUE, /* value */ "ros3", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -411,7 +412,7 @@ H5Pset_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa) if (FAIL == H5FD__ros3_validate_config(fa)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid ros3 config") - ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa); + ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDros3.h b/src/H5FDros3.h index 8e42ca2..d69ebe4 100644 --- a/src/H5FDros3.h +++ b/src/H5FDros3.h @@ -22,9 +22,11 @@ #define H5FDros3_H #ifdef H5_HAVE_ROS3_VFD -#define H5FD_ROS3 (H5FD_ros3_init()) +#define H5FD_ROS3 (H5FD_ros3_init()) +#define H5FD_ROS3_VALUE H5_VFD_ROS3 #else -#define H5FD_ROS3 (H5I_INVALID_HID) +#define H5FD_ROS3 (H5I_INVALID_HID) +#define H5FD_ROS3_VALUE H5_VFD_INVALID #endif /* H5_HAVE_ROS3_VFD */ #ifdef H5_HAVE_ROS3_VFD diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index 15103da..2dbdd6f 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -143,6 +143,7 @@ static herr_t H5FD__sec2_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, c void **output); static const H5FD_class_t H5FD_sec2_g = { + H5FD_SEC2_VALUE, /* value */ "sec2", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -200,7 +201,7 @@ H5FD__init_package(void) FUNC_ENTER_STATIC /* Check the use disabled file locks environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !HDstrcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = TRUE; /* Override: Ignore disabled locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "1"))) @@ -295,7 +296,7 @@ H5Pset_fapl_sec2(hid_t fapl_id) if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_SEC2, NULL); + ret_value = H5P_set_driver(plist, H5FD_SEC2, NULL, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5FDsec2.h b/src/H5FDsec2.h index 541ac71..5c35677 100644 --- a/src/H5FDsec2.h +++ b/src/H5FDsec2.h @@ -20,7 +20,8 @@ #ifndef H5FDsec2_H #define H5FDsec2_H -#define H5FD_SEC2 (H5FD_sec2_init()) +#define H5FD_SEC2 (H5FD_sec2_init()) +#define H5FD_SEC2_VALUE H5_VFD_SEC2 #ifdef __cplusplus extern "C" { diff --git a/src/H5FDsplitter.c b/src/H5FDsplitter.c index 3113e8b..321973e 100644 --- a/src/H5FDsplitter.c +++ b/src/H5FDsplitter.c @@ -104,6 +104,10 @@ static int H5FD__copy_plist(hid_t fapl_id, hid_t *id_out_ptr); /* Prototypes */ static herr_t H5FD__splitter_term(void); +static herr_t H5FD__splitter_populate_config(H5FD_splitter_vfd_config_t *vfd_config, + H5FD_splitter_fapl_t * fapl_out); +static herr_t H5FD__splitter_get_default_wo_path(char *new_path, size_t new_path_len, + const char *base_filename); static hsize_t H5FD__splitter_sb_size(H5FD_t *_file); static herr_t H5FD__splitter_sb_encode(H5FD_t *_file, char *name /*out*/, unsigned char *buf /*out*/); static herr_t H5FD__splitter_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf); @@ -129,10 +133,12 @@ static herr_t H5FD__splitter_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closin static herr_t H5FD__splitter_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static herr_t H5FD__splitter_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD__splitter_unlock(H5FD_t *_file); +static herr_t H5FD__splitter_delete(const char *filename, hid_t fapl_id); static herr_t H5FD__splitter_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, void **output); static const H5FD_class_t H5FD_splitter_g = { + H5FD_SPLITTER_VALUE, /* value */ "splitter", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -140,7 +146,7 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_sb_size, /* sb_size */ H5FD__splitter_sb_encode, /* sb_encode */ H5FD__splitter_sb_decode, /* sb_decode */ - sizeof(H5FD_splitter_fapl_t), /* fapl_size */ + sizeof(H5FD_splitter_fapl_t), /* fapl_size */ H5FD__splitter_fapl_get, /* fapl_get */ H5FD__splitter_fapl_copy, /* fapl_copy */ H5FD__splitter_fapl_free, /* fapl_free */ @@ -151,7 +157,7 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_close, /* close */ H5FD__splitter_cmp, /* cmp */ H5FD__splitter_query, /* query */ - H5FD__splitter_get_type_map, /* get_type_map */ + H5FD__splitter_get_type_map, /* get_type_map */ H5FD__splitter_alloc, /* alloc */ H5FD__splitter_free, /* free */ H5FD__splitter_get_eoa, /* get_eoa */ @@ -164,7 +170,7 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_truncate, /* truncate */ H5FD__splitter_lock, /* lock */ H5FD__splitter_unlock, /* unlock */ - NULL, /* del */ + H5FD__splitter_delete, /* del */ H5FD__splitter_ctl, /* ctl */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; @@ -312,57 +318,14 @@ H5Pset_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *vfd_config) if (NULL == (plist_ptr = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid property list") - /* Make sure that the W/O channel supports write-only capability. - * Some drivers (e.g. family or multi) do revision of the superblock - * in-memory, causing problems in that channel. - * Uses the feature flag H5FD_FEAT_DEFAULT_VFD_COMPATIBLE as the - * determining attribute. - */ - if (H5P_DEFAULT != vfd_config->wo_fapl_id) { - H5FD_class_t * wo_driver = NULL; - H5FD_driver_prop_t wo_driver_prop; - H5P_genplist_t * wo_plist_ptr = NULL; - unsigned long wo_driver_flags = 0; - - wo_plist_ptr = (H5P_genplist_t *)H5I_object(vfd_config->wo_fapl_id); - if (NULL == wo_plist_ptr) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - if (H5P_peek(wo_plist_ptr, H5F_ACS_FILE_DRV_NAME, &wo_driver_prop) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID & info") - wo_driver = (H5FD_class_t *)H5I_object(wo_driver_prop.driver_id); - if (NULL == wo_driver) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid driver ID in file access property list") - if (H5FD_driver_query(wo_driver, &wo_driver_flags) < 0) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't query VFD flags") - if (0 == (H5FD_FEAT_DEFAULT_VFD_COMPATIBLE & wo_driver_flags)) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unsuitable W/O driver") - } /* end if W/O VFD is non-default */ - info = H5FL_CALLOC(H5FD_splitter_fapl_t); if (NULL == info) HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") - info->ignore_wo_errs = vfd_config->ignore_wo_errs; - HDstrncpy(info->wo_path, vfd_config->wo_path, H5FD_SPLITTER_PATH_MAX + 1); - info->wo_path[H5FD_SPLITTER_PATH_MAX] = '\0'; - HDstrncpy(info->log_file_path, vfd_config->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); - info->log_file_path[H5FD_SPLITTER_PATH_MAX] = '\0'; - info->rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ - info->wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ - - /* Set non-default channel FAPL IDs in splitter configuration info */ - if (H5P_DEFAULT != vfd_config->rw_fapl_id) { - if (FALSE == H5P_isa_class(vfd_config->rw_fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") - info->rw_fapl_id = vfd_config->rw_fapl_id; - } - if (H5P_DEFAULT != vfd_config->wo_fapl_id) { - if (FALSE == H5P_isa_class(vfd_config->wo_fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") - info->wo_fapl_id = vfd_config->wo_fapl_id; - } + if (H5FD__splitter_populate_config(vfd_config, info) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't setup driver configuration") - ret_value = H5P_set_driver(plist_ptr, H5FD_SPLITTER, info); + ret_value = H5P_set_driver(plist_ptr, H5FD_SPLITTER, info, NULL); done: if (info) @@ -386,9 +349,10 @@ done: herr_t H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) { - const H5FD_splitter_fapl_t *fapl_ptr = NULL; - H5P_genplist_t * plist_ptr = NULL; - herr_t ret_value = SUCCEED; + const H5FD_splitter_fapl_t *fapl_ptr = NULL; + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist_ptr = NULL; + herr_t ret_value = SUCCEED; FUNC_ENTER_API(FAIL) H5TRACE2("e", "ix", fapl_id, config); @@ -414,8 +378,14 @@ H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") if (H5FD_SPLITTER != H5P_peek_driver(plist_ptr)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") - if (NULL == (fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr))) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to get specific-driver info") + fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr); + if (NULL == fapl_ptr) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + fapl_ptr = default_fapl; + } HDstrncpy(config->wo_path, fapl_ptr->wo_path, H5FD_SPLITTER_PATH_MAX + 1); HDstrncpy(config->log_file_path, fapl_ptr->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); @@ -428,10 +398,188 @@ H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config /*out*/) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't copy W/O FAPL"); done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + FUNC_LEAVE_API(ret_value) } /* end H5Pget_fapl_splitter() */ /*------------------------------------------------------------------------- + * Function: H5FD__splitter_populate_config + * + * Purpose: Populates a H5FD_splitter_fapl_t structure with the provided + * values, supplying defaults where values are not provided. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_populate_config(H5FD_splitter_vfd_config_t *vfd_config, H5FD_splitter_fapl_t *fapl_out) +{ + H5P_genplist_t *def_plist; + H5P_genplist_t *plist; + hbool_t free_config = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(fapl_out); + + HDmemset(fapl_out, 0, sizeof(H5FD_splitter_fapl_t)); + + if (!vfd_config) { + vfd_config = H5MM_calloc(sizeof(H5FD_splitter_vfd_config_t)); + if (NULL == vfd_config) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->rw_fapl_id = H5P_DEFAULT; + vfd_config->wo_fapl_id = H5P_DEFAULT; + + free_config = TRUE; + } + + /* Make sure that the W/O channel supports write-only capability. + * Some drivers (e.g. family or multi) do revision of the superblock + * in-memory, causing problems in that channel. + * Uses the feature flag H5FD_FEAT_DEFAULT_VFD_COMPATIBLE as the + * determining attribute. + */ + if (H5P_DEFAULT != vfd_config->wo_fapl_id) { + H5FD_class_t * wo_driver = NULL; + H5FD_driver_prop_t wo_driver_prop; + H5P_genplist_t * wo_plist_ptr = NULL; + unsigned long wo_driver_flags = 0; + + wo_plist_ptr = (H5P_genplist_t *)H5I_object(vfd_config->wo_fapl_id); + if (NULL == wo_plist_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_peek(wo_plist_ptr, H5F_ACS_FILE_DRV_NAME, &wo_driver_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID & info") + wo_driver = (H5FD_class_t *)H5I_object(wo_driver_prop.driver_id); + if (NULL == wo_driver) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid driver ID in file access property list") + if (H5FD_driver_query(wo_driver, &wo_driver_flags) < 0) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't query VFD flags") + if (0 == (H5FD_FEAT_DEFAULT_VFD_COMPATIBLE & wo_driver_flags)) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unsuitable W/O driver") + } /* end if W/O VFD is non-default */ + + fapl_out->ignore_wo_errs = vfd_config->ignore_wo_errs; + HDstrncpy(fapl_out->wo_path, vfd_config->wo_path, H5FD_SPLITTER_PATH_MAX + 1); + fapl_out->wo_path[H5FD_SPLITTER_PATH_MAX] = '\0'; + HDstrncpy(fapl_out->log_file_path, vfd_config->log_file_path, H5FD_SPLITTER_PATH_MAX + 1); + fapl_out->log_file_path[H5FD_SPLITTER_PATH_MAX] = '\0'; + fapl_out->rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ + fapl_out->wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; /* pre-set value */ + + if (NULL == (def_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + + /* Set non-default channel FAPL IDs in splitter configuration info */ + if (H5P_DEFAULT != vfd_config->rw_fapl_id) { + if (FALSE == H5P_isa_class(vfd_config->rw_fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") + fapl_out->rw_fapl_id = vfd_config->rw_fapl_id; + } + else { + /* Use copy of default file access property list for R/W channel FAPL ID. + * The Sec2 driver is explicitly set on the FAPL ID, as the default + * driver might have been replaced with the Splitter VFD, which + * would cause recursion badness. + */ + if ((fapl_out->rw_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_out->rw_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on R/W channel FAPL") + } + if (H5P_DEFAULT != vfd_config->wo_fapl_id) { + if (FALSE == H5P_isa_class(vfd_config->wo_fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") + fapl_out->wo_fapl_id = vfd_config->wo_fapl_id; + } + else { + /* Use copy of default file access property list for W/O channel FAPL ID. + * The Sec2 driver is explicitly set on the FAPL ID, as the default + * driver might have been replaced with the Splitter VFD, which + * would cause recursion badness. + */ + if ((fapl_out->wo_fapl_id = H5P_copy_plist(def_plist, FALSE)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTCOPY, FAIL, "can't copy property list") + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_out->wo_fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (H5P_set_driver_by_value(plist, H5_VFD_SEC2, NULL, TRUE) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't set default driver on R/W channel FAPL") + } + +done: + if (free_config && vfd_config) + H5MM_free(vfd_config); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__splitter_populate_config() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__splitter_get_default_wo_path + * + * Purpose: Given a base filename, returns a default filename for the + * W/O channel file by appending '_wo' to the base file name. + * + * Return: Non-negative on Success/Negative on Failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_get_default_wo_path(char *new_path, size_t new_path_len, const char *base_filename) +{ + const char *suffix = "_wo"; + size_t old_filename_len = 0; + char * file_extension = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(new_path); + HDassert(base_filename); + + /* Check that output buffer can hold base filename + `_wo` suffix */ + old_filename_len = HDstrlen(base_filename); + if (old_filename_len > H5FD_SPLITTER_PATH_MAX - HDstrlen(suffix) - 1) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "filename exceeds max length") + + /* Determine if filename contains a ".h5" extension. */ + if ((file_extension = strstr(base_filename, ".h5"))) { + /* Insert the suffix between the filename and ".h5" extension. */ + HDstrcpy(new_path, base_filename); + file_extension = strstr(new_path, ".h5"); + HDsprintf(file_extension, "%s%s", suffix, ".h5"); + } + else if ((file_extension = strrchr(base_filename, '.'))) { + char *new_extension_loc = NULL; + + /* If the filename doesn't contain a ".h5" extension, but contains + * AN extension, just insert the suffix before that extension. + */ + HDstrcpy(new_path, base_filename); + new_extension_loc = strrchr(new_path, '.'); + HDsprintf(new_extension_loc, "%s%s", suffix, file_extension); + } + else { + /* If the filename doesn't contain an extension at all, just insert + * the suffix at the end of the filename. + */ + HDsnprintf(new_path, new_path_len, "%s%s", base_filename, suffix); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD__splitter_get_default_wo_path() */ + +/*------------------------------------------------------------------------- * Function: H5FD__splitter_flush * * Purpose: Flushes all data to disk for both channels. @@ -658,10 +806,11 @@ done: static H5FD_t * H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, haddr_t maxaddr) { - H5FD_splitter_t * file_ptr = NULL; /* Splitter VFD info */ - const H5FD_splitter_fapl_t *fapl_ptr = NULL; /* Driver-specific property list */ - H5P_genplist_t * plist_ptr = NULL; - H5FD_t * ret_value = NULL; + H5FD_splitter_t * file_ptr = NULL; /* Splitter VFD info */ + const H5FD_splitter_fapl_t *fapl_ptr = NULL; /* Driver-specific property list */ + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist_ptr = NULL; + H5FD_t * ret_value = NULL; FUNC_ENTER_STATIC @@ -674,8 +823,7 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr") if (ADDR_OVERFLOW(maxaddr)) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr") - if ((H5P_FILE_ACCESS_DEFAULT == splitter_fapl_id) || (H5FD_SPLITTER != H5Pget_driver(splitter_fapl_id))) - /* presupposes that H5P_FILE_ACCESS_DEFAULT is not a splitter */ + if (H5FD_SPLITTER != H5Pget_driver(splitter_fapl_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "driver is not splitter") file_ptr = (H5FD_splitter_t *)H5FL_CALLOC(H5FD_splitter_t); @@ -689,8 +837,20 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha if (NULL == plist_ptr) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist_ptr); - if (NULL == fapl_ptr) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get VFL driver info") + if (NULL == fapl_ptr) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, name) < + 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, NULL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } /* Copy simpler info */ HDstrncpy(file_ptr->fa.wo_path, fapl_ptr->wo_path, H5FD_SPLITTER_PATH_MAX + 1); @@ -726,6 +886,9 @@ H5FD__splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, ha ret_value = (H5FD_t *)file_ptr; done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + if (NULL == ret_value) { if (file_ptr) { if (H5I_INVALID_HID != file_ptr->fa.rw_fapl_id) @@ -1339,6 +1502,74 @@ done: } /* end H5FD__splitter_free() */ /*------------------------------------------------------------------------- + * Function: H5FD__splitter_delete + * + * Purpose: Delete a file + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__splitter_delete(const char *filename, hid_t fapl_id) +{ + const H5FD_splitter_fapl_t *fapl_ptr = NULL; + H5FD_splitter_fapl_t * default_fapl = NULL; + H5P_genplist_t * plist; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + HDassert(filename); + + /* Get the driver info */ + if (H5P_FILE_ACCESS_DEFAULT == fapl_id) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, + filename) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } + else { + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + if (NULL == (fapl_ptr = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist))) { + if (NULL == (default_fapl = H5FL_CALLOC(H5FD_splitter_fapl_t))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, + "unable to allocate file access property list struct") + if (H5FD__splitter_populate_config(NULL, default_fapl) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't initialize driver configuration info") + + /* If W/O path is not set, use base filename with '_wo' suffix */ + if (*default_fapl->wo_path == '\0') + if (H5FD__splitter_get_default_wo_path(default_fapl->wo_path, H5FD_SPLITTER_PATH_MAX + 1, + filename) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't generate default filename for W/O channel") + + fapl_ptr = default_fapl; + } + } + + if (H5FDdelete(filename, fapl_ptr->rw_fapl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "unable to delete file") + if (H5FDdelete(fapl_ptr->wo_path, fapl_ptr->wo_fapl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTDELETEFILE, FAIL, "unable to delete W/O channel file") + +done: + if (default_fapl) + H5FL_FREE(H5FD_splitter_fapl_t, default_fapl); + + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- * Function: H5FD__splitter_log_error * * Purpose: Log an error from the W/O channel appropriately. diff --git a/src/H5FDsplitter.h b/src/H5FDsplitter.h index ee6e7c5..3a743e4 100644 --- a/src/H5FDsplitter.h +++ b/src/H5FDsplitter.h @@ -17,7 +17,8 @@ #ifndef H5FDsplitter_H #define H5FDsplitter_H -#define H5FD_SPLITTER (H5FD_splitter_init()) +#define H5FD_SPLITTER (H5FD_splitter_init()) +#define H5FD_SPLITTER_VALUE H5_VFD_SPLITTER /* The version of the H5FD_splitter_vfd_config_t structure used */ #define H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION 1 diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 312263c..122379a 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -183,6 +183,7 @@ static herr_t H5FD_stdio_unlock(H5FD_t *_file); static herr_t H5FD_stdio_delete(const char *filename, hid_t fapl_id); static const H5FD_class_t H5FD_stdio_g = { + H5_VFD_STDIO, /* value */ "stdio", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ @@ -243,7 +244,7 @@ H5FD_stdio_init(void) H5Eclear2(H5E_DEFAULT); /* Check the use disabled file locks environment variable */ - lock_env_var = getenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = getenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && !strcmp(lock_env_var, "BEST_EFFORT")) ignore_disabled_file_locks_s = 1; /* Override: Ignore disabled locks */ else if (lock_env_var && (!strcmp(lock_env_var, "TRUE") || !strcmp(lock_env_var, "1"))) diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c index 6ce33a7..fa3c05f 100644 --- a/src/H5FDwindows.c +++ b/src/H5FDwindows.c @@ -56,7 +56,7 @@ H5Pset_fapl_windows(hid_t fapl_id) if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") - ret_value = H5P_set_driver(plist, H5FD_WINDOWS, NULL); + ret_value = H5P_set_driver(plist, H5FD_WINDOWS, NULL, NULL); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5Fint.c b/src/H5Fint.c index c2d3e77..d772088 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -277,7 +277,7 @@ H5F__parse_file_lock_env_var(htri_t *use_locks) FUNC_ENTER_PACKAGE_NOERR /* Check the file locking environment variable */ - lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING"); + lock_env_var = HDgetenv(HDF5_USE_FILE_LOCKING); if (lock_env_var && (!HDstrcmp(lock_env_var, "FALSE") || !HDstrcmp(lock_env_var, "0"))) *use_locks = FALSE; /* Override: Never use locks */ else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "BEST_EFFORT") || @@ -454,9 +454,10 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref) HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.") /* Prepare the driver property */ - driver_prop.driver_id = f->shared->lf->driver_id; - driver_prop.driver_info = H5FD_fapl_get(f->shared->lf); - driver_prop_copied = TRUE; + driver_prop.driver_id = f->shared->lf->driver_id; + driver_prop.driver_info = H5FD_fapl_get(f->shared->lf); + driver_prop.driver_config_str = H5P_peek_driver_config_str(old_plist); + driver_prop_copied = TRUE; /* Set the driver property */ if (H5P_set(new_plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0) @@ -1828,7 +1829,13 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) else tent_flags = flags; - if (NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { + H5E_BEGIN_TRY + { + lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF); + } + H5E_END_TRY; + + if (NULL == lf) { if (tent_flags == flags) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags) diff --git a/src/H5PLint.c b/src/H5PLint.c index d20401e..848bd1d 100644 --- a/src/H5PLint.c +++ b/src/H5PLint.c @@ -144,7 +144,7 @@ H5PL__init_package(void) * to ignore plugins. The special symbol H5PL_NO_PLUGIN (defined in * H5PLpublic.h) means we don't want to load plugins. */ - if (NULL != (env_var = HDgetenv("HDF5_PLUGIN_PRELOAD"))) + if (NULL != (env_var = HDgetenv(HDF5_PLUGIN_PRELOAD))) if (!HDstrcmp(env_var, H5PL_NO_PLUGIN)) { H5PL_plugin_control_mask_g = 0; H5PL_allow_plugins_g = FALSE; @@ -243,6 +243,11 @@ H5PL_load(H5PL_type_t type, const H5PL_key_t *key) "Virtual Object Layer (VOL) driver plugins disabled") break; + case H5PL_TYPE_VFD: + if ((H5PL_plugin_control_mask_g & H5PL_VFD_PLUGIN) == 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Virtual File Driver (VFD) plugins disabled") + break; + case H5PL_TYPE_ERROR: case H5PL_TYPE_NONE: default: @@ -275,9 +280,31 @@ done: * * Purpose: Opens a plugin. * - * The success parameter will be set to TRUE and the plugin_info - * parameter will be filled in on success. Otherwise, they - * will be FALSE and NULL, respectively. + * `path` specifies the path to the plugin library file. + * + * `type` specifies the type of plugin being searched for and + * will be used to verify that a loaded plugin matches the + * type requested. H5PL_TYPE_NONE may be passed, in which case + * no plugin type verification is performed. This is most + * useful when iterating over available plugins without regard + * to their types. + * + * `key` specifies the information that will be used to find a + * specific plugin. For filter plugins, this is typically an + * integer identifier. For VOL connector and VFD plugins, this + * is typically either an integer identifier or a name string. + * After a plugin has been opened, this information will be + * compared against the relevant information provided by the + * plugin to ensure that the plugin is a match. If + * H5PL_TYPE_NONE is provided for `type`, then `key` should be + * NULL. + * + * On successful open of a plugin, the `success` parameter + * will be set to TRUE and the `plugin_type` and `plugin_info` + * parameters will be filled appropriately. On failure, the + * `success` parameter will be set to FALSE, the `plugin_type` + * parameter will be set to H5PL_TYPE_ERROR and the + * `plugin_info` parameter will be set to NULL. * * Return: SUCCEED/FAIL * @@ -308,6 +335,8 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s /* Check args - Just assert on package functions */ HDassert(path); + if (type == H5PL_TYPE_NONE) + HDassert(!key); HDassert(success); HDassert(plugin_info); @@ -396,6 +425,34 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s break; } + case H5PL_TYPE_VFD: { + const void *cls; + + /* Get the plugin info */ + if (NULL == (cls = (const void *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VFD info from plugin") + + /* Setup temporary plugin key if one wasn't supplied */ + if (!key) { + tmp_key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; + tmp_key.vfd.u.name = ((const H5FD_class_t *)cls)->name; + key = &tmp_key; + } + + /* Ask VFD interface if this class is the one we are looking for and is compatible, etc */ + if (H5FD_check_plugin_load(cls, key, success) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VFD compatibility check failed") + + /* Check for finding the correct plugin */ + if (*success) { + if (plugin_type) + *plugin_type = H5PL_TYPE_VFD; + *plugin_info = cls; + } + + break; + } + case H5PL_TYPE_ERROR: case H5PL_TYPE_NONE: default: diff --git a/src/H5PLpath.c b/src/H5PLpath.c index 39a7d0d..9aecad1 100644 --- a/src/H5PLpath.c +++ b/src/H5PLpath.c @@ -248,7 +248,7 @@ H5PL__create_path_table(void) /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it * or from the default paths if it isn't set. */ - env_var = HDgetenv("HDF5_PLUGIN_PATH"); + env_var = HDgetenv(HDF5_PLUGIN_PATH); if (NULL == env_var) paths = H5MM_strdup(H5PL_DEFAULT_PATH); else @@ -571,12 +571,12 @@ H5PL__path_table_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, FUNC_ENTER_PACKAGE - for (u = 0; (u < H5PL_num_paths_g) && (ret_value == H5_ITER_CONT); u++) - ret_value = H5PL__path_table_iterate_process_path(H5PL_paths_g[u], iter_type, iter_op, op_data); - - if (ret_value < 0) - HGOTO_ERROR(H5E_PLUGIN, H5E_BADITER, H5_ITER_ERROR, "can't iterate over plugins in plugin path '%s'", - H5PL_paths_g[u]); + for (u = 0; (u < H5PL_num_paths_g) && (ret_value == H5_ITER_CONT); u++) { + if ((ret_value = + H5PL__path_table_iterate_process_path(H5PL_paths_g[u], iter_type, iter_op, op_data)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_BADITER, H5_ITER_ERROR, + "can't iterate over plugins in plugin path '%s'", H5PL_paths_g[u]); + } done: FUNC_LEAVE_NOAPI(ret_value); @@ -615,9 +615,9 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type HDassert(plugin_path); HDassert(iter_op); - /* Open the directory */ + /* Open the directory - skip the path if the directory can't be opened */ if (!(dirp = HDopendir(plugin_path))) - HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory: %s", plugin_path) + HGOTO_DONE(H5_ITER_CONT) /* Iterate through all entries in the directory */ while (NULL != (dp = HDreaddir(dirp))) { @@ -663,7 +663,8 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type /* Determine if we should process this plugin */ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) || ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) || - ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)); + ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)) || + ((iter_type == H5PL_ITER_TYPE_VFD) && (plugin_type == H5PL_TYPE_VFD)); /* If the plugin was successfully loaded, call supplied callback function on plugin */ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data))) @@ -706,10 +707,11 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type HDassert(plugin_path); HDassert(iter_op); - /* Specify a file mask. *.* = We want everything! */ + /* Specify a file mask. *.* = We want everything! - + * skip the path if the directory can't be opened */ HDsprintf(service, "%s\\*.dll", plugin_path); if ((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE) - HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory") + HGOTO_DONE(H5_ITER_CONT) /* Loop over all the files */ do { @@ -740,7 +742,8 @@ H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type /* Determine if we should process this plugin */ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) || ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) || - ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)); + ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL)) || + ((iter_type == H5PL_ITER_TYPE_VFD) && (plugin_type == H5PL_TYPE_VFD)); /* If the plugin was successfully loaded, call supplied callback function on plugin */ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data))) diff --git a/src/H5PLplugin_cache.c b/src/H5PLplugin_cache.c index b7cdac0..25e373f 100644 --- a/src/H5PLplugin_cache.c +++ b/src/H5PLplugin_cache.c @@ -263,59 +263,99 @@ H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *f /* Loop over all the plugins, looking for one that matches */ for (u = 0; u < H5PL_num_plugins_g; u++) { - /* If the plugin type (filter, VOL connector, etc.) match, proceed */ - if (search_params->type == H5PL_cache_g[u].type) { - hbool_t matched = FALSE; /* Whether cached plugin info matches */ + hbool_t matched = FALSE; /* Whether cached plugin info matches */ - switch (search_params->type) { - case H5PL_TYPE_FILTER: - if (search_params->key->id == H5PL_cache_g[u].key.id) + /* Determine if the plugin types match */ + if (search_params->type != H5PL_cache_g[u].type) + continue; + + /* Determine if cache entry matches based on type-specific information */ + switch (search_params->type) { + case H5PL_TYPE_FILTER: + /* Check if specified filter plugin ID matches cache entry's ID */ + if (search_params->key->id == H5PL_cache_g[u].key.id) + matched = TRUE; + + break; + + case H5PL_TYPE_VOL: + if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) { + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vol.kind != H5VL_GET_CONNECTOR_BY_NAME) + continue; + + /* Check if specified VOL connector name matches cache entry's name */ + if (!HDstrcmp(search_params->key->vol.u.name, H5PL_cache_g[u].key.vol.u.name)) + matched = TRUE; + } + else { + HDassert(search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE); + + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vol.kind != H5VL_GET_CONNECTOR_BY_VALUE) + continue; + + /* Check if specified VOL connector ID matches cache entry's ID */ + if (search_params->key->vol.u.value == H5PL_cache_g[u].key.vol.u.value) + matched = TRUE; + } + + break; + + case H5PL_TYPE_VFD: + if (search_params->key->vfd.kind == H5FD_GET_DRIVER_BY_NAME) { + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vfd.kind != H5FD_GET_DRIVER_BY_NAME) + continue; + + /* Check if specified VFD name matches cache entry's name */ + if (!HDstrcmp(search_params->key->vfd.u.name, H5PL_cache_g[u].key.vfd.u.name)) matched = TRUE; - break; - - case H5PL_TYPE_VOL: - if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE) { - if (search_params->key->vol.u.value == H5PL_cache_g[u].key.vol.u.value) - matched = TRUE; - } /* end if */ - else if (search_params->key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) { - if (0 == HDstrcmp(search_params->key->vol.u.name, H5PL_cache_g[u].key.vol.u.name)) - matched = TRUE; - } /* end else-if */ - else - HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, FAIL, "bad VOL plugin search key type") - break; - - case H5PL_TYPE_ERROR: - case H5PL_TYPE_NONE: - default: - HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, FAIL, "bad plugin type") - } /* end switch */ - - /* If the plugin type (filter, VOL connector, etc.) and key match, query the plugin for its info - */ - if (matched) { - H5PL_get_plugin_info_t get_plugin_info_function; - const void * info; - - /* Get the "get plugin info" function from the plugin. */ - if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC( - (H5PL_cache_g[u]).handle, "H5PLget_plugin_info"))) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info") - - /* Call the "get plugin info" function */ - if (NULL == (info = (*get_plugin_info_function)())) - HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info") - - /* Set output parameters */ - *found = TRUE; - *plugin_info = info; - - /* No need to continue processing */ + } + else { + HDassert(search_params->key->vfd.kind == H5FD_GET_DRIVER_BY_VALUE); + + /* Make sure the plugin cache entry key type matches our search key type */ + if (H5PL_cache_g[u].key.vfd.kind != H5FD_GET_DRIVER_BY_VALUE) + continue; + + /* Check if specified VFD ID matches cache entry's ID */ + if (search_params->key->vfd.u.value == H5PL_cache_g[u].key.vfd.u.value) + matched = TRUE; + } + break; - } /* end if */ - } /* end if */ - } /* end for */ + + case H5PL_TYPE_ERROR: + case H5PL_TYPE_NONE: + default: + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "Invalid plugin type specified") + } + + /* If the plugin type (filter, VOL connector, VFD plugin, etc.) and key match, + * query the plugin for its info. + */ + if (matched) { + H5PL_get_plugin_info_t get_plugin_info_function; + const void * info; + + /* Get the "get plugin info" function from the plugin. */ + if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC( + H5PL_cache_g[u].handle, "H5PLget_plugin_info"))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info") + + /* Call the "get plugin info" function */ + if (NULL == (info = (*get_plugin_info_function)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info") + + /* Set output parameters */ + *found = TRUE; + *plugin_info = info; + + /* No need to continue processing */ + break; + } + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h index 7eae513..7ff5c1a 100644 --- a/src/H5PLprivate.h +++ b/src/H5PLprivate.h @@ -22,6 +22,7 @@ /* Private headers needed by this file */ #include "H5private.h" /* Generic Functions */ +#include "H5FDprivate.h" /* File Drivers */ #include "H5VLprivate.h" /* Virtual Object Layer */ /**************************/ @@ -32,16 +33,29 @@ /* Library Private Typedefs */ /****************************/ +/* Key used to find VOL connector plugins */ +typedef struct H5PL_vol_key_t { + H5VL_get_connector_kind_t kind; /* Kind of VOL lookup to do */ + union { + H5VL_class_value_t value; /* VOL connector value */ + const char * name; /* VOL connector name */ + } u; +} H5PL_vol_key_t; + +/* Key used to find VFD plugins */ +typedef struct H5PL_vfd_key_t { + H5FD_get_driver_kind_t kind; /* Kind of VFD lookup to do */ + union { + H5FD_class_value_t value; /* VFD value */ + const char * name; /* VFD name */ + } u; +} H5PL_vfd_key_t; + /* The key that will be used to find the plugin */ typedef union H5PL_key_t { - int id; /* I/O filters */ - struct { - H5VL_get_connector_kind_t kind; /* Kind of VOL lookup to do */ - union { - H5VL_class_value_t value; /* VOL connector value */ - const char * name; /* VOL connector name */ - } u; - } vol; + int id; /* I/O filters */ + H5PL_vol_key_t vol; + H5PL_vfd_key_t vfd; } H5PL_key_t; /* Enum dictating the type of plugins to process @@ -50,6 +64,7 @@ typedef union H5PL_key_t { typedef enum { H5PL_ITER_TYPE_FILTER, H5PL_ITER_TYPE_VOL, + H5PL_ITER_TYPE_VFD, H5PL_ITER_TYPE_ALL, } H5PL_iterate_type_t; diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h index 55ff594..ab24bd5 100644 --- a/src/H5PLpublic.h +++ b/src/H5PLpublic.h @@ -35,14 +35,16 @@ typedef enum H5PL_type_t { H5PL_TYPE_ERROR = -1, /**< Error */ H5PL_TYPE_FILTER = 0, /**< Filter */ - H5PL_TYPE_VOL = 1, /**< VOL driver */ - H5PL_TYPE_NONE = 2 /**< Sentinel: This must be last! */ + H5PL_TYPE_VOL = 1, /**< VOL connector */ + H5PL_TYPE_VFD = 2, /**< VFD */ + H5PL_TYPE_NONE = 3 /**< Sentinel: This must be last! */ } H5PL_type_t; //! <!-- [H5PL_type_t_snip] --> /* Common dynamic plugin type flags used by the set/get_loading_state functions */ #define H5PL_FILTER_PLUGIN 0x0001 #define H5PL_VOL_PLUGIN 0x0002 +#define H5PL_VFD_PLUGIN 0x0004 #define H5PL_ALL_PLUGIN 0xFFFF #ifdef __cplusplus 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() */ diff --git a/src/H5Pint.c b/src/H5Pint.c index 9530d87..9206d4c 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -412,20 +412,22 @@ static const H5I_class_t H5I_GENPROPLST_CLS[1] = {{ }}; /*------------------------------------------------------------------------- - * Function: H5P_init + * Function: H5P_init_phase1 * - * Purpose: Initialize the interface from some other layer. + * Purpose: Initialize the interface from some other layer. This should + * be followed with a call to H5P_init_phase2 after the H5P + * interface is completely setup. * - * Return: Success: non-negative - * Failure: negative + * Return: Success: non-negative + * Failure: negative * - * Programmer: Quincey Koziol + * Programmer: Quincey Koziol * Saturday, March 4, 2000 * *------------------------------------------------------------------------- */ herr_t -H5P_init(void) +H5P_init_phase1(void) { herr_t ret_value = SUCCEED; /* Return value */ @@ -434,7 +436,36 @@ H5P_init(void) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5P_init() */ +} /* end H5P_init_phase1() */ + +/*------------------------------------------------------------------------- + * Function: H5P_init_phase2 + * + * Purpose: Finish initializing the interface from some other package. + * + * Note: This is broken out as a separate routine so that the + * library's default VFL driver can be chosen and initialized + * after the entire H5P interface has been initialized. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_init_phase2(void) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Set up the default VFL driver */ + if (H5P__facc_set_def_driver() < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "unable to set default VFL driver") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_init_phase2() */ /*-------------------------------------------------------------------------- NAME @@ -449,8 +480,9 @@ DESCRIPTION herr_t H5P__init_package(void) { - size_t tot_init; /* Total # of classes initialized */ - size_t pass_init; /* # of classes initialized in each pass */ + size_t tot_init = 0; /* Total # of classes initialized */ + size_t pass_init; /* # of classes initialized in each pass */ + size_t u; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -472,8 +504,6 @@ H5P__init_package(void) */ tot_init = 0; do { - size_t u; /* Local index variable */ - /* Reset pass initialization counter */ pass_init = 0; @@ -523,6 +553,28 @@ H5P__init_package(void) HDassert(tot_init == NELMTS(init_class)); done: + if (ret_value < 0 && tot_init > 0) { + /* First uninitialize all default property lists */ + H5I_clear_type(H5I_GENPROP_LST, FALSE, FALSE); + + /* Then uninitialize any initialized libclass */ + for (u = 0; u < NELMTS(init_class); u++) { + H5P_libclass_t const *lib_class = init_class[u]; /* Current class to operate on */ + + HDassert(lib_class->class_id); + if (*lib_class->class_id >= 0) { + /* Close the class ID */ + if (H5I_dec_ref(*lib_class->class_id) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class ID") + } + else if (lib_class->pclass && *lib_class->pclass) { + /* Close a half-initialized pclass */ + if (H5P__close_class(*lib_class->pclass) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class") + } + } + } + FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__init_package() */ diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index dd43f76..2946931 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -188,6 +188,9 @@ H5_DLL herr_t H5P__decode_double(const void **_pp, void *value); H5_DLL herr_t H5P__encode_coll_md_read_flag_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__decode_coll_md_read_flag_t(const void **_pp, void *value); +/* Private FAPL routines */ +H5_DLL herr_t H5P__facc_set_def_driver(void); + /* Private OCPL routines */ H5_DLL herr_t H5P__get_filter(const struct H5Z_filter_info_t *filter, unsigned int *flags, size_t *cd_nelmts, unsigned cd_values[], size_t namelen, char name[], unsigned *filter_config); diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 6ebe5d3..7cbb397 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -156,8 +156,9 @@ struct H5O_fill_t; struct H5T_t; struct H5VL_connector_prop_t; -/* Package initialization routine */ -H5_DLL herr_t H5P_init(void); +/* Package initialization routines */ +H5_DLL herr_t H5P_init_phase1(void); +H5_DLL herr_t H5P_init_phase2(void); /* Internal versions of API routines */ H5_DLL herr_t H5P_close(H5P_genplist_t *plist); @@ -181,7 +182,13 @@ H5_DLL char * H5P_get_class_name(H5P_genclass_t *pclass); H5_DLL herr_t H5P_get_nprops_pclass(const H5P_genclass_t *pclass, size_t *nprops, hbool_t recurse); H5_DLL hid_t H5P_peek_driver(H5P_genplist_t *plist); H5_DLL const void *H5P_peek_driver_info(H5P_genplist_t *plist); -H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info); +H5_DLL const char *H5P_peek_driver_config_str(H5P_genplist_t *plist); +H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_driver_info, + const char *new_driver_config_str); +H5_DLL herr_t H5P_set_driver_by_name(H5P_genplist_t *plist, const char *driver_name, + const char *driver_config, hbool_t app_ref); +H5_DLL 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); H5_DLL herr_t H5P_set_vol(H5P_genplist_t *plist, hid_t vol_id, const void *vol_info); H5_DLL herr_t H5P_reset_vol_class(const H5P_genclass_t *pclass, const struct H5VL_connector_prop_t *vol_prop); H5_DLL herr_t H5P_set_vlen_mem_manager(H5P_genplist_t *plist, H5MM_allocate_t alloc_func, void *alloc_info, diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index a5c5c37..3fa7118 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -3448,6 +3448,34 @@ H5_DLL const void *H5Pget_driver_info(hid_t plist_id); /** * \ingroup FAPL * + * \brief 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. + * + * \fapl_id + * \param[out] config_buf Driver configuration string output buffer + * \param[in] buf_size Size of driver configuration string output buffer + * + * \return Returns the length of the driver configuration string on + * success (not including the NUL terminator). Returns negative + * on failure. + * + * \details H5Pget_driver_config_str() 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. + * + * If \p config_buf is NULL, 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. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL ssize_t H5Pget_driver_config_str(hid_t fapl_id, char *config_buf, size_t buf_size); +/** + * \ingroup FAPL + * * \brief Retrieves the size of the external link open file cache * * \fapl_id{plist_id} @@ -4287,6 +4315,57 @@ H5_DLL herr_t H5Pset_driver(hid_t plist_id, hid_t driver_id, const void *driver_ /** * \ingroup FAPL * + * \brief Sets a file driver according to a given driver name + * + * \plist_id + * \param[in] driver_name The new driver name + * \param[in] driver_config Optional string containing driver properties + * + * \return \herr_t + * + * \details H5Pset_driver_by_name() sets the file driver, by the name + * driver_name, for a file access or data transfer property list, + * \p plist_id, and supplies an optional string containing the + * driver-specific properties, \p driver_config. The driver + * properties string will be copied into the property list. + * + * If the driver specified by \p driver_name is not currently + * registered, an attempt will be made to load the driver as a + * plugin. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL herr_t H5Pset_driver_by_name(hid_t plist_id, const char *driver_name, const char *driver_config); +/** + * \ingroup FAPL + * + * \brief Sets a file driver according to a given driver value (ID). + * + * \plist_id + * \param[in] driver_value The new driver value (ID) + * \param[in] driver_config Optional string containing driver properties + * + * \return \herr_t + * + * \details H5Pset_driver_by_value() sets the file driver, by the value + * driver_value, for a file access or data transfer property list, + * \p plist_id, and supplies an optional string containing the + * driver-specific properties, \p driver_config. The driver + * properties string will be copied into the property list. + * + * If the driver specified by \p driver_value is not currently + * registered, an attempt will be made to load the driver as a + * plugin. + * + * \version 1.12.1 Function publicized in this release. + * + */ +H5_DLL herr_t H5Pset_driver_by_value(hid_t plist_id, H5FD_class_value_t driver_value, + const char *driver_config); +/** + * \ingroup FAPL + * * \brief Sets the number of files that can be held open in an external * link open file cache * diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index a61b003..2369be5 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -3527,6 +3527,7 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in H5P_genplist_t * fapl_plist; H5P_genplist_t * fapl_plist_copy; hbool_t is_accessible = FALSE; /* Whether file is accessible */ + ssize_t num_errors = 0; herr_t status; hid_t connector_id = H5I_INVALID_HID; hid_t fapl_id = H5I_INVALID_HID; @@ -3565,6 +3566,10 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in vol_cb_args.args.is_accessible.fapl_id = fapl_id; vol_cb_args.args.is_accessible.accessible = &is_accessible; + /* Store current error stack size */ + if ((num_errors = H5Eget_num(H5E_DEFAULT)) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, H5_ITER_ERROR, "can't get current error stack size") + /* Check if file is accessible with given VOL connector */ H5E_BEGIN_TRY { @@ -3572,11 +3577,23 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in } H5E_END_TRY; - /* If the file was accessible with the current VOL connector, return - * the FAPL with that VOL connector set on it. Errors are ignored here - * as some VOL connectors may not support H5Fis_accessible. - */ - if (status == SUCCEED && is_accessible) { + if (status < 0) { + ssize_t new_num_errors = 0; + + /* Pop any errors generated by the above call */ + if ((new_num_errors = H5Eget_num(H5E_DEFAULT)) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, H5_ITER_ERROR, "can't get current error stack size") + if (new_num_errors > num_errors) { + new_num_errors -= num_errors; + if (H5Epop(H5E_DEFAULT, (size_t)new_num_errors) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't sanitize error stack") + } + } + else if (status == SUCCEED && is_accessible) { + /* If the file was accessible with the current VOL connector, return + * the FAPL with that VOL connector set on it. + */ + /* Modify 'connector_prop' to point to the VOL connector that * was actually used to open the file, rather than the original * VOL connector that was requested. @@ -3586,7 +3603,7 @@ H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_in udata->fapl_id = fapl_id; ret_value = H5_ITER_STOP; - } /* end if */ + } done: if (ret_value != H5_ITER_STOP) { diff --git a/src/H5VLint.c b/src/H5VLint.c index b4432d0..936614f 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -69,11 +69,7 @@ typedef struct H5VL_wrap_ctx_t { */ typedef struct { /* IN */ - H5VL_get_connector_kind_t kind; /* Which kind of connector search to make */ - union { - const char * name; /* The name of the VOL connector to check */ - H5VL_class_value_t value; /* The value of the VOL connector to check */ - } u; + H5PL_vol_key_t key; /* OUT */ hid_t found_id; /* The connector ID, if we found a match */ @@ -341,15 +337,15 @@ H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data) FUNC_ENTER_STATIC_NOERR - if (H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) { - if (0 == HDstrcmp(cls->name, op_data->u.name)) { + if (H5VL_GET_CONNECTOR_BY_NAME == op_data->key.kind) { + if (0 == HDstrcmp(cls->name, op_data->key.u.name)) { op_data->found_id = id; ret_value = H5_ITER_STOP; } /* end if */ } /* end if */ else { - HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind); - if (cls->value == op_data->u.value) { + HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->key.kind); + if (cls->value == op_data->key.u.value) { op_data->found_id = id; ret_value = H5_ITER_STOP; } /* end if */ @@ -398,7 +394,7 @@ H5VL__set_def_conn(void) } /* end if */ /* Check for environment variable set */ - env_var = HDgetenv("HDF5_VOL_CONNECTOR"); + env_var = HDgetenv(HDF5_VOL_CONNECTOR); /* Only parse the string if it's set */ if (env_var && *env_var) { @@ -1299,9 +1295,9 @@ H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_ "callback is provided") /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = cls->name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = cls->name; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1350,9 +1346,9 @@ H5VL__register_connector_by_name(const char *name, hbool_t app_ref, hid_t vipl_i FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, app_ref) < 0) @@ -1410,12 +1406,12 @@ H5VL__register_connector_by_value(H5VL_class_value_t value, hbool_t app_ref, hid FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Check if connector is already registered */ - if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) + if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, app_ref) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids") /* If connector alread registered, increment ref count on ID and return ID */ @@ -1449,8 +1445,9 @@ done: * * Purpose: Checks if a connector with a particular name is registered. * - * Return: Success: 0 - * Failure: -1 + * Return: >0 if a VOL connector with that name has been registered + * 0 if a VOL connector with that name has NOT been registered + * <0 on errors * * Programmer: Dana Robinson * June 17, 2017 @@ -1466,9 +1463,9 @@ H5VL__is_connector_registered_by_name(const char *name) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Find connector with name */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1488,8 +1485,9 @@ done: * Purpose: Checks if a connector with a particular value (ID) is * registered. * - * Return: Success: 0 - * Failure: -1 + * Return: >0 if a VOL connector with that value has been registered + * 0 if a VOL connector with that value hasn't been registered + * <0 on errors * *------------------------------------------------------------------------- */ @@ -1502,9 +1500,9 @@ H5VL__is_connector_registered_by_value(H5VL_class_value_t value) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Find connector with value */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1635,9 +1633,9 @@ H5VL__peek_connector_id_by_name(const char *name) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_NAME; - op_data.u.name = name; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_NAME; + op_data.key.u.name = name; + op_data.found_id = H5I_INVALID_HID; /* Find connector with name */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) @@ -1671,9 +1669,9 @@ H5VL__peek_connector_id_by_value(H5VL_class_value_t value) FUNC_ENTER_PACKAGE /* Set up op data for iteration */ - op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE; - op_data.u.value = value; - op_data.found_id = H5I_INVALID_HID; + op_data.key.kind = H5VL_GET_CONNECTOR_BY_VALUE; + op_data.key.u.value = value; + op_data.found_id = H5I_INVALID_HID; /* Find connector with value */ if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0) diff --git a/src/H5public.h b/src/H5public.h index c9430dc..3e59e24 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -168,6 +168,58 @@ (((H5_VERS_MAJOR == Maj) && (H5_VERS_MINOR == Min) && (H5_VERS_RELEASE <= Rel)) || \ ((H5_VERS_MAJOR == Maj) && (H5_VERS_MINOR < Min)) || (H5_VERS_MAJOR < Maj)) +/* Macros for various environment variables that HDF5 interprets */ +/** + * Used to specify the name of an HDF5 Virtual File Driver to use as + * the default file driver for file access. Setting this environment + * variable overrides the default file driver for File Access Property + * Lists. + */ +#define HDF5_DRIVER "HDF5_DRIVER" +/** + * Used to specify a configuration string for the HDF5 Virtual File + * Driver being used for file access. + */ +#define HDF5_DRIVER_CONFIG "HDF5_DRIVER_CONFIG" +/** + * Used to specify the name of an HDF5 Virtual Object Layer Connector + * to use as the default VOL connector for file access. Setting this + * environment variable overrides the default VOL connector for File + * Access Property Lists. + */ +#define HDF5_VOL_CONNECTOR "HDF5_VOL_CONNECTOR" +/** + * Used to specify a delimiter-separated (currently, ';' for Windows + * and ':' for other systems) list of paths that HDF5 should search + * when loading plugins. + */ +#define HDF5_PLUGIN_PATH "HDF5_PLUGIN_PATH" +/** + * Used to control the loading of HDF5 plugins at runtime. If this + * environment variable is set to the special string "::" (defined + * in H5PLpublic.h as H5PL_NO_PLUGIN), then dynamic loading of any + * HDF5 plugins will be disabled. No other values are valid for this + * environment variable. + */ +#define HDF5_PLUGIN_PRELOAD "HDF5_PLUGIN_PRELOAD" +/** + * Used to control whether HDF5 uses file locking when creating or + * opening a file. Valid values for this environment variable are + * as follows: + * + * "TRUE" or "1" - Request that file locks should be used + * "FALSE" or "0" - Request that file locks should NOT be used + * "BEST_EFFORT" - Request that file locks should be used and + * that any locking errors caused by file + * locking being disabled on the system + * should be ignored + */ +#define HDF5_USE_FILE_LOCKING "HDF5_USE_FILE_LOCKING" +/** + * Used to instruct HDF5 not to cleanup files created during testing. + */ +#define HDF5_NOCLEANUP "HDF5_NOCLEANUP" + /** * Status return values. Failed integer functions in HDF5 result almost * always in a negative value (unsigned failing functions sometimes return diff --git a/src/H5trace.c b/src/H5trace.c index 3a5d420..a735df3 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -1046,6 +1046,65 @@ H5_trace_args(H5RS_str_t *rs, const char *type, va_list ap) } /* end block */ break; + case 'V': /* H5FD_class_value_t */ + { + H5FD_class_value_t class_val = + (H5FD_class_value_t)HDva_arg(ap, H5FD_class_value_t); + + switch (class_val) { + case H5_VFD_INVALID: + H5RS_acat(rs, "H5_VFD_INVALID"); + break; + case H5_VFD_SEC2: + H5RS_acat(rs, "H5_VFD_SEC2"); + break; + case H5_VFD_CORE: + H5RS_acat(rs, "H5_VFD_CORE"); + break; + case H5_VFD_LOG: + H5RS_acat(rs, "H5_VFD_LOG"); + break; + case H5_VFD_FAMILY: + H5RS_acat(rs, "H5_VFD_FAMILY"); + break; + case H5_VFD_MULTI: + H5RS_acat(rs, "H5_VFD_MULTI"); + break; + case H5_VFD_STDIO: + H5RS_acat(rs, "H5_VFD_STDIO"); + break; +#ifdef H5_HAVE_PARALLEL + case H5_VFD_MPIO: + H5RS_acat(rs, "H5_VFD_MPIO"); + break; +#endif +#ifdef H5_HAVE_DIRECT + case H5_VFD_DIRECT: + H5RS_acat(rs, "H5_VFD_DIRECT"); + break; +#endif +#ifdef H5_HAVE_MIRROR_VFD + case H5_HAVE_MIRROR_VFD: + H5RS_acat(rs, "H5_HAVE_MIRROR_VFD"); + break; +#endif +#ifdef H5_HAVE_LIBHDFS + case H5_HAVE_LIBHDFS: + H5RS_acat(rs, "H5_HAVE_LIBHDFS"); + break; +#endif +#ifdef H5_HAVE_ROS3_VFD + case H5_HAVE_ROS3_VFD: + H5RS_acat(rs, "H5_HAVE_ROS3_VFD"); + break; +#endif + default: + H5RS_asprintf_cat(rs, "%ld", (long)class_val); + break; + } + } /* end block */ + break; + default: H5RS_asprintf_cat(rs, "BADTYPE(D%c)", type[1]); goto error; |