diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2016-02-22 21:40:03 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2016-02-22 21:40:03 (GMT) |
commit | 19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf (patch) | |
tree | bf07b7366747d1519b628ea1c399bb5e8b654753 /src/H5Pdapl.c | |
parent | 7511d8b4691770a15f1ba9f7fcc242f038c79669 (diff) | |
download | hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.zip hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.tar.gz hdf5-19a8216bd52b6a495c4bc989b7d01e9a7ecd46bf.tar.bz2 |
[svn-r29182] Re-commit of HDFFV-8740 fix, which adds the ability to configure
external dataset storage path behavior.
This check-in fixes a bug in the original check-in where the
external path stored in the file struct was not copied on reopen
causing subsequent dataset operations to fail.
Tested on: 64-bit Ubuntu 15.10 (Linux 4.2.0 x86_64) gcc 5.2.1
autotools serial w/ fortran and C++
autotools parallel (MPICH 3.1.4) w/ fortran
Diffstat (limited to 'src/H5Pdapl.c')
-rw-r--r-- | src/H5Pdapl.c | 384 |
1 files changed, 381 insertions, 3 deletions
diff --git a/src/H5Pdapl.c b/src/H5Pdapl.c index eab9337..6407d4c 100644 --- a/src/H5Pdapl.c +++ b/src/H5Pdapl.c @@ -16,8 +16,8 @@ /*------------------------------------------------------------------------- * * Created: H5Pdapl.c - * October 27, 2008 - * Neil Fortner <nfortne2@hdfgroup.org> + * October 27, 2008 + * Neil Fortner <nfortne2@hdfgroup.org> * * Purpose: Dataset access property list class routines * @@ -39,7 +39,8 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* Files */ #include "H5Iprivate.h" /* IDs */ -#include "H5Ppkg.h" /* Property lists */ +#include "H5Ppkg.h" /* Property lists */ +#include "H5MMprivate.h" /* Memory management */ /****************/ @@ -72,6 +73,17 @@ #define H5D_ACS_VDS_PRINTF_GAP_DEF (hsize_t)0 #define H5D_ACS_VDS_PRINTF_GAP_ENC H5P__encode_hsize_t #define H5D_ACS_VDS_PRINTF_GAP_DEC H5P__decode_hsize_t +/* Definitions for external file prefix */ +#define H5D_ACS_EFILE_PREFIX_SIZE sizeof(char *) +#define H5D_ACS_EFILE_PREFIX_DEF NULL /*default is no prefix */ +#define H5D_ACS_EFILE_PREFIX_SET H5P__dapl_efile_pref_set +#define H5D_ACS_EFILE_PREFIX_GET H5P__dapl_efile_pref_get +#define H5D_ACS_EFILE_PREFIX_ENC H5P__dapl_efile_pref_enc +#define H5D_ACS_EFILE_PREFIX_DEC H5P__dapl_efile_pref_dec +#define H5D_ACS_EFILE_PREFIX_DEL H5P__dapl_efile_pref_del +#define H5D_ACS_EFILE_PREFIX_COPY H5P__dapl_efile_pref_copy +#define H5D_ACS_EFILE_PREFIX_CMP H5P__dapl_efile_pref_cmp +#define H5D_ACS_EFILE_PREFIX_CLOSE H5P__dapl_efile_pref_close /******************/ /* Local Typedefs */ @@ -100,6 +112,16 @@ static herr_t H5P__decode_chunk_cache_nbytes(const void **_pp, void *_value); static herr_t H5P__dacc_vds_view_enc(const void *value, void **pp, size_t *size); static herr_t H5P__dacc_vds_view_dec(const void **pp, void *value); +/* Property list callbacks */ +static herr_t H5P__dapl_efile_pref_set(hid_t prop_id, const char* name, size_t size, void* value); +static herr_t H5P__dapl_efile_pref_get(hid_t prop_id, const char* name, size_t size, void* value); +static herr_t H5P__dapl_efile_pref_enc(const void *value, void **_pp, size_t *size); +static herr_t H5P__dapl_efile_pref_dec(const void **_pp, void *value); +static herr_t H5P__dapl_efile_pref_del(hid_t prop_id, const char* name, size_t size, void* value); +static herr_t H5P__dapl_efile_pref_copy(const char* name, size_t size, void* value); +static int H5P__dapl_efile_pref_cmp(const void *value1, const void *value2, size_t size); +static herr_t H5P__dapl_efile_pref_close(const char* name, size_t size, void* value); + /*********************/ /* Package Variables */ @@ -134,6 +156,9 @@ const H5P_libclass_t H5P_CLS_DACC[1] = {{ /* Local Variables */ /*******************/ +/* Property value defaults */ +static const char *H5D_def_efile_prefix_g = H5D_ACS_EFILE_PREFIX_DEF; /* Default external file prefix string */ + /*------------------------------------------------------------------------- @@ -187,12 +212,274 @@ H5P__dacc_reg_prop(H5P_genclass_t *pclass) NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register property for external file prefix */ + if(H5P_register_real(pclass, H5D_ACS_EFILE_PREFIX_NAME, H5D_ACS_EFILE_PREFIX_SIZE, &H5D_def_efile_prefix_g, + NULL, H5D_ACS_EFILE_PREFIX_SET, H5D_ACS_EFILE_PREFIX_GET, H5D_ACS_EFILE_PREFIX_ENC, H5D_ACS_EFILE_PREFIX_DEC, + H5D_ACS_EFILE_PREFIX_DEL, H5D_ACS_EFILE_PREFIX_COPY, H5D_ACS_EFILE_PREFIX_CMP, H5D_ACS_EFILE_PREFIX_CLOSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__dacc_reg_prop() */ /*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_set + * + * Purpose: Copies an external file prefix property when it's set + * for a property list + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, + size_t H5_ATTR_UNUSED size, void *value) +{ + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(value); + + /* Copy the prefix */ + *(char **)value = H5MM_xstrdup(*(const char **)value); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_set() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_get + * + * Purpose: Copies an external file prefix property when it's retrieved + * from a property list + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, + size_t H5_ATTR_UNUSED size, void *value) +{ + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(value); + + /* Copy the prefix */ + *(char **)value = H5MM_xstrdup(*(const char **)value); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_enc + * + * Purpose: Callback routine which is called whenever the efile flags + * property in the dataset access property list is + * encoded. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_enc(const void *value, void **_pp, size_t *size) +{ + const char *efile_pref = *(const char * const *)value; + uint8_t **pp = (uint8_t **)_pp; + size_t len = 0; + uint64_t enc_value; + unsigned enc_size; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); + + /* calculate prefix length */ + if(NULL != efile_pref) + len = HDstrlen(efile_pref); + + enc_value = (uint64_t)len; + enc_size = H5VM_limit_enc_size(enc_value); + HDassert(enc_size < 256); + + if(NULL != *pp) { + /* encode the length of the prefix */ + *(*pp)++ = (uint8_t)enc_size; + UINT64ENCODE_VAR(*pp, enc_value, enc_size); + + /* encode the prefix */ + if(NULL != efile_pref) { + HDmemcpy(*(char **)pp, efile_pref, len); + *pp += len; + } /* end if */ + } /* end if */ + + *size += (1 + enc_size); + if(NULL != efile_pref) + *size += len; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_enc() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_dec + * + * Purpose: Callback routine which is called whenever the efile prefix + * property in the dataset access property list is + * decoded. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_dec(const void **_pp, void *_value) +{ + char **efile_pref = (char **)_value; + const uint8_t **pp = (const uint8_t **)_pp; + size_t len; + uint64_t enc_value; /* Decoded property value */ + unsigned enc_size; /* Size of encoded property */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(pp); + HDassert(*pp); + HDassert(efile_pref); + HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); + + /* Decode the size */ + enc_size = *(*pp)++; + HDassert(enc_size < 256); + + /* Decode the value */ + UINT64DECODE_VAR(*pp, enc_value, enc_size); + len = (size_t)enc_value; + + if(0 != len) { + /* Make a copy of the user's prefix string */ + if(NULL == (*efile_pref = (char *)H5MM_malloc(len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "memory allocation failed for prefix") + HDstrncpy(*efile_pref, *(const char **)pp, len); + (*efile_pref)[len] = '\0'; + + *pp += len; + } /* end if */ + else + *efile_pref = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__dapl_efile_pref_dec() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_del + * + * Purpose: Frees memory used to store the external file prefix string + * + * Return: SUCCEED (Can't fail) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, + size_t H5_ATTR_UNUSED size, void *value) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(value); + + H5MM_xfree(*(void **)value); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_del() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_copy + * + * Purpose: Creates a copy of the external file prefix string + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(value); + + *(char **)value = H5MM_xstrdup(*(const char **)value); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_cmp + * + * Purpose: Callback routine which is called whenever the efile prefix + * property in the dataset creation property list is + * compared. + * + * Return: zero if VALUE1 and VALUE2 are equal, non zero otherwise. + * + *------------------------------------------------------------------------- + */ +static int +H5P__dapl_efile_pref_cmp(const void *value1, const void *value2, size_t H5_ATTR_UNUSED size) +{ + const char *pref1 = *(const char * const *)value1; + const char *pref2 = *(const char * const *)value2; + int ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(NULL == pref1 && NULL != pref2) + HGOTO_DONE(1); + if(NULL != pref1 && NULL == pref2) + HGOTO_DONE(-1); + if(NULL != pref1 && NULL != pref2) + ret_value = HDstrcmp(pref1, pref2); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__dapl_efile_pref_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__dapl_efile_pref_close + * + * Purpose: Frees memory used to store the external file prefix string + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__dapl_efile_pref_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(value); + + H5MM_xfree(*(void **)value); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__dapl_efile_pref_close() */ + + +/*------------------------------------------------------------------------- * Function: H5Pset_chunk_cache * * Purpose: Set the number of objects in the meta data cache and the @@ -787,3 +1074,94 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_virtual_printf_gap() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_efile_prefix + * + * Purpose: Set a prefix to be used for any external files. + * + * If the prefix starts with ${ORIGIN}, this will be replaced by + * the absolute path of the directory of the HDF5 file containing + * the dataset. + * + * If the prefix is ".", no prefix will be applied. + * + * This property can be overwritten by the environment variable + * HDF5_EXTFILE_PREFIX. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_efile_prefix(hid_t plist_id, const char *prefix) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*s", plist_id, prefix); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Set prefix */ + if(H5P_set(plist, H5D_ACS_EFILE_PREFIX_NAME, &prefix) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set prefix info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_efile_prefix() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_efile_prefix + * + * Purpose: Gets the prefix to be used for any external files. + * + * If the pointer is not NULL, it points to a user-allocated + * buffer. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Pget_efile_prefix(hid_t plist_id, char *prefix, size_t size) +{ + H5P_genplist_t *plist; /* Property list pointer */ + char *my_prefix; /* Library's copy of the prefix */ + size_t len; /* Length of prefix string */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("Zs", "i*sz", plist_id, prefix, size); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get the current prefix */ + if(H5P_peek(plist, H5D_ACS_EFILE_PREFIX_NAME, &my_prefix) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file prefix") + + /* Check for prefix being set */ + if(my_prefix) { + /* Copy to user's buffer, if given */ + len = HDstrlen(my_prefix); + if(prefix) { + HDstrncpy(prefix, my_prefix, MIN(len + 1, size)); + if(len >= size) + prefix[size - 1] = '\0'; + } /* end if */ + } /* end if */ + else + len = 0; + + /* Set return value */ + ret_value = (ssize_t)len; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_efile_prefix() */ |