From ff490b4a69029fa75a39258bbab67784e9743de9 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 21 Aug 2019 13:14:06 -0500 Subject: Add 'blob' callbacks to VOL, along with a native implementation to store them in the global heap, and changed the VL datatype conversion code to use blobs. Move encode/decode of sequence lengths into VL datatype callbacks, from native VOL blob routines. --- MANIFEST | 1 + src/CMakeLists.txt | 1 + src/H5Dio.c | 36 +- src/H5Fint.c | 17 +- src/H5Fpkg.h | 4 +- src/H5Fprivate.h | 12 +- src/H5Fquery.c | 25 ++ src/H5Odtype.c | 30 +- src/H5Tconv.c | 74 +++-- src/H5Tpkg.h | 39 ++- src/H5Tvlen.c | 757 +++++++++++++++++++++++-------------------- src/H5VLcallback.c | 119 +++++++ src/H5VLconnector.h | 22 +- src/H5VLconnector_passthru.h | 6 +- src/H5VLint.c | 29 +- src/H5VLnative.c | 10 +- src/H5VLnative.h | 3 + src/H5VLnative_blob.c | 260 +++++++++++++++ src/H5VLnative_private.h | 29 +- src/H5VLpassthru.c | 14 +- src/H5VLprivate.h | 8 + src/Makefile.am | 5 +- 22 files changed, 1033 insertions(+), 468 deletions(-) create mode 100644 src/H5VLnative_blob.c diff --git a/MANIFEST b/MANIFEST index 723bae7..5e7caff 100644 --- a/MANIFEST +++ b/MANIFEST @@ -925,6 +925,7 @@ ./src/H5VLnative.c ./src/H5VLnative.h ./src/H5VLnative_attr.c +./src/H5VLnative_blob.c ./src/H5VLnative_dataset.c ./src/H5VLnative_datatype.c ./src/H5VLnative_file.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6df8af3..b50fa71 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -649,6 +649,7 @@ set (H5VL_SOURCES ${HDF5_SRC_DIR}/H5VLint.c ${HDF5_SRC_DIR}/H5VLnative.c ${HDF5_SRC_DIR}/H5VLnative_attr.c + ${HDF5_SRC_DIR}/H5VLnative_blob.c ${HDF5_SRC_DIR}/H5VLnative_dataset.c ${HDF5_SRC_DIR}/H5VLnative_datatype.c ${HDF5_SRC_DIR}/H5VLnative_file.c diff --git a/src/H5Dio.c b/src/H5Dio.c index 1e6e70d..5160de8 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -478,33 +478,33 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set") /* H5S_select_shape_same() has been modified to accept topologically identical - * selections with different rank as having the same shape (if the most - * rapidly changing coordinates match up), but the I/O code still has + * selections with different rank as having the same shape (if the most + * rapidly changing coordinates match up), but the I/O code still has * difficulties with the notion. * - * To solve this, we check to see if H5S_select_shape_same() returns true, - * and if the ranks of the mem and file spaces are different. If the are, - * construct a new mem space that is equivalent to the old mem space, and + * To solve this, we check to see if H5S_select_shape_same() returns true, + * and if the ranks of the mem and file spaces are different. If the are, + * construct a new mem space that is equivalent to the old mem space, and * use that instead. * - * Note that in general, this requires us to touch up the memory buffer as + * Note that in general, this requires us to touch up the memory buffer as * well. */ if(TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) && H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) { - void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ + const void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ /* to the beginning of the projected mem space. */ /* Attempt to construct projected dataspace for memory dataspace */ if(H5S_select_construct_projection(mem_space, &projected_mem_space, - (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, (const void **)&adj_buf, type_info.dst_type_size) < 0) + (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.dst_type_size) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace") HDassert(projected_mem_space); HDassert(adj_buf); /* Switch to using projected memory dataspace & adjusted buffer */ mem_space = projected_mem_space; - buf = adj_buf; + buf = (void *)adj_buf; /* Casting away 'const' OK -QAK */ } /* end if */ @@ -712,27 +712,27 @@ H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, if(!(H5S_has_extent(mem_space))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set") - /* H5S_select_shape_same() has been modified to accept topologically - * identical selections with different rank as having the same shape - * (if the most rapidly changing coordinates match up), but the I/O + /* H5S_select_shape_same() has been modified to accept topologically + * identical selections with different rank as having the same shape + * (if the most rapidly changing coordinates match up), but the I/O * code still has difficulties with the notion. * - * To solve this, we check to see if H5S_select_shape_same() returns - * true, and if the ranks of the mem and file spaces are different. - * If the are, construct a new mem space that is equivalent to the + * To solve this, we check to see if H5S_select_shape_same() returns + * true, and if the ranks of the mem and file spaces are different. + * If the are, construct a new mem space that is equivalent to the * old mem space, and use that instead. * - * Note that in general, this requires us to touch up the memory buffer + * Note that in general, this requires us to touch up the memory buffer * as well. */ if(TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) && H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) { - void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ + const void *adj_buf = NULL; /* Pointer to the location in buf corresponding */ /* to the beginning of the projected mem space. */ /* Attempt to construct projected dataspace for memory dataspace */ if(H5S_select_construct_projection(mem_space, &projected_mem_space, - (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, (const void **)&adj_buf, type_info.src_type_size) < 0) + (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.src_type_size) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace") HDassert(projected_mem_space); HDassert(adj_buf); diff --git a/src/H5Fint.c b/src/H5Fint.c index 5e2cf26..2ebcd94 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -139,18 +139,14 @@ H5F__set_vol_conn(H5F_t *file) /* Sanity check */ HDassert(0 != connector_prop.connector_id); - /* Copy connector info, if it exists */ - if(connector_prop.connector_info) { - H5VL_class_t *connector; /* Pointer to connector */ + /* Retrieve the connector for the ID */ + if(NULL == (file->shared->vol_cls = (H5VL_class_t *)H5I_object(connector_prop.connector_id))) + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a VOL connector ID") - /* Retrieve the connector for the ID */ - if(NULL == (connector = (H5VL_class_t *)H5I_object(connector_prop.connector_id))) - HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a VOL connector ID") - - /* Allocate and copy connector info */ - if(H5VL_copy_connector_info(connector, &new_connector_info, connector_prop.connector_info) < 0) + /* Allocate and copy connector info, if it exists */ + if(connector_prop.connector_info) + if(H5VL_copy_connector_info(file->shared->vol_cls, &new_connector_info, connector_prop.connector_info) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "connector info copy failed") - } /* end if */ /* Cache the connector ID & info for the container */ file->shared->vol_id = connector_prop.connector_id; @@ -1377,6 +1373,7 @@ H5F__dest(H5F_t *f, hbool_t flush) if(H5I_dec_ref(f->shared->vol_id) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close VOL connector ID") + f->shared->vol_cls = NULL; /* Close the file */ if(H5FD_close(f->shared->lf) < 0) diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 6cd2d3c..6a5c62f 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -29,9 +29,6 @@ /* Get package's private header */ #include "H5Fprivate.h" -/* Other public headers needed by this file */ -#include "H5VLpublic.h" /* Virtual Object Layer */ - /* Other private headers needed by this file */ #include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ @@ -313,6 +310,7 @@ struct H5F_shared_t { /* Cached VOL connector ID & info */ hid_t vol_id; /* ID of VOL connector for the container */ + const H5VL_class_t *vol_cls; /* Pointer to VOL connector class for the container */ void *vol_info; /* Copy of VOL connector info for container */ /* File space allocation information */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 8c70663..e15025b 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -25,14 +25,15 @@ typedef struct H5F_t H5F_t; #include "H5Fpublic.h" /* Public headers needed by this file */ -#include "H5FDpublic.h" /* File drivers */ +#include "H5FDpublic.h" /* File drivers */ +#include "H5VLpublic.h" /* Virtual Object Layer */ /* Private headers needed by this file */ -#include "H5MMprivate.h" /* Memory management */ +#include "H5MMprivate.h" /* Memory management */ #ifdef H5_HAVE_PARALLEL -#include "H5Pprivate.h" /* Property lists */ +#include "H5Pprivate.h" /* Property lists */ #endif /* H5_HAVE_PARALLEL */ -#include "H5VMprivate.h" /* Vectors and arrays */ +#include "H5VMprivate.h" /* Vectors and arrays */ /**************************/ @@ -335,6 +336,7 @@ typedef struct H5F_t H5F_t; #define H5F_NULL_FSM_ADDR(F) ((F)->shared->null_fsm_addr) #define H5F_GET_MIN_DSET_OHDR(F) ((F)->shared->crt_dset_min_ohdr_flag) #define H5F_SET_MIN_DSET_OHDR(F, V) ((F)->shared->crt_dset_min_ohdr_flag = (V)) +#define H5F_VOL_CLS(F) ((F)->shared->vol_cls) #else /* H5F_MODULE */ #define H5F_LOW_BOUND(F) (H5F_get_low_bound(F)) #define H5F_HIGH_BOUND(F) (H5F_get_high_bound(F)) @@ -395,6 +397,7 @@ typedef struct H5F_t H5F_t; #define H5F_NULL_FSM_ADDR(F) (H5F_get_null_fsm_addr(F)) #define H5F_GET_MIN_DSET_OHDR(F) (H5F_get_min_dset_ohdr(F)) #define H5F_SET_MIN_DSET_OHDR(F, V) (H5F_set_min_dset_ohdr((F), (V))) +#define H5F_VOL_CLS(F) (H5F_get_vol_cls(F)) #endif /* H5F_MODULE */ @@ -755,6 +758,7 @@ H5_DLL hbool_t H5F_get_point_of_no_return(const H5F_t *f); H5_DLL hbool_t H5F_get_null_fsm_addr(const H5F_t *f); H5_DLL hbool_t H5F_get_min_dset_ohdr(const H5F_t *f); H5_DLL herr_t H5F_set_min_dset_ohdr(H5F_t *f, hbool_t minimize); +H5_DLL const H5VL_class_t *H5F_get_vol_cls(const H5F_t *f); /* Functions than retrieve values set/cached from the superblock/FCPL */ H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f); diff --git a/src/H5Fquery.c b/src/H5Fquery.c index f36f348..69b042d 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -1279,3 +1279,28 @@ H5F_get_null_fsm_addr(const H5F_t *f) FUNC_LEAVE_NOAPI(f->shared->null_fsm_addr) } /* end H5F_get_null_fsm_addr() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_vol_cls + * + * Purpose: Get the VOL class for the file + * + * Return: VOL class pointer for file, can't fail + * + * Programmer: Quincey Koziol + * Saturday, August 17, 2019 + * + *------------------------------------------------------------------------- + */ +const H5VL_class_t * +H5F_get_vol_cls(const H5F_t *f) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->vol_cls) +} /* end H5F_get_vol_cls */ + diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 8f301af..0523e7c 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -129,7 +129,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ *------------------------------------------------------------------------- */ static htri_t -H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt) +H5O_dtype_decode_helper(unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt) { unsigned flags, version; unsigned i; @@ -331,7 +331,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Decode the field's datatype information */ - if((can_upgrade = H5O_dtype_decode_helper(f, ioflags, pp, temp_type)) < 0) { + if((can_upgrade = H5O_dtype_decode_helper(ioflags, pp, temp_type)) < 0) { for(j = 0; j <= i; j++) H5MM_xfree(dt->shared->u.compnd.memb[j].name); H5MM_xfree(dt->shared->u.compnd.memb); @@ -457,7 +457,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p dt->shared->u.enumer.nmembs = dt->shared->u.enumer.nalloc = flags & 0xffff; if(NULL == (dt->shared->parent = H5T__alloc())) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) + if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype") /* Check if the parent of this enum has a version greater than the @@ -499,7 +499,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p /* Decode base type of VL information */ if(NULL == (dt->shared->parent = H5T__alloc())) HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) + if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type") /* Check if the parent of this vlen has a version greater than the @@ -511,7 +511,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p /* Mark location this type as undefined for now. The caller function should * decide the location. */ - if(H5T_set_loc(dt, f, H5T_LOC_BADLOC) < 0) + if(H5T_set_loc(dt, NULL, H5T_LOC_BADLOC) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") break; @@ -540,7 +540,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p /* Decode base type of array */ if(NULL == (dt->shared->parent = H5T__alloc())) HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) + if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode array parent type") /* Check if the parent of this array has a version greater than the @@ -596,7 +596,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) +H5O_dtype_encode_helper(uint8_t **pp, const H5T_t *dt) { unsigned flags = 0; uint8_t *hdr = (uint8_t *)*pp; @@ -956,7 +956,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) } /* end if */ /* Subtype */ - if(H5O_dtype_encode_helper(f, pp, dt->shared->u.compnd.memb[i].type) < 0) + if(H5O_dtype_encode_helper(pp, dt->shared->u.compnd.memb[i].type) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode member type") } /* end for */ } @@ -976,7 +976,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) flags = dt->shared->u.enumer.nmembs & 0xffff; /* Parent type */ - if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0) + if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode parent datatype") /* Names, each a multiple of eight bytes */ @@ -1012,7 +1012,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) } /* end if */ /* Encode base type of VL information */ - if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0) + if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode VL parent type") break; @@ -1050,7 +1050,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) } /* end if */ /* Encode base type of array's information */ - if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0) + if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode VL parent type") break; @@ -1091,7 +1091,7 @@ done: function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * -H5O_dtype_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, +H5O_dtype_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned *ioflags/*in,out*/, size_t H5_ATTR_UNUSED p_size, const uint8_t *p) { H5T_t *dt = NULL; @@ -1107,7 +1107,7 @@ H5O_dtype_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSE HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Perform actual decode of message */ - if(H5O_dtype_decode_helper(f, ioflags, &p, dt) < 0) + if(H5O_dtype_decode_helper(ioflags, &p, dt) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type") /* Set return value */ @@ -1136,7 +1136,7 @@ done: message in the "raw" disk form. --------------------------------------------------------------------------*/ static herr_t -H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg) +H5O_dtype_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *mesg) { const H5T_t *dt = (const H5T_t *) mesg; herr_t ret_value = SUCCEED; /* Return value */ @@ -1149,7 +1149,7 @@ H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg) HDassert(dt); /* encode */ - if(H5O_dtype_encode_helper(f, &p, dt) < 0) + if(H5O_dtype_encode_helper(&p, dt) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode type") done: diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 48c3282..723b9f2 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -30,7 +30,6 @@ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ -#include "H5HGprivate.h" /* Global Heaps */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ @@ -3020,17 +3019,16 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, hbool_t noop_conv = FALSE; /* Flag to indicate a noop conversion */ hbool_t write_to_file = FALSE; /* Flag to indicate writing to file */ htri_t parent_is_vlen; /* Flag to indicate parent is vlen datatyp */ + size_t bg_seq_len = 0; /* The number of elements in the background sequence */ hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */ H5T_t *src = NULL; /*source datatype */ H5T_t *dst = NULL; /*destination datatype */ - H5HG_t bg_hobjid, parent_hobjid; uint8_t *s = NULL; /*source buffer */ uint8_t *d = NULL; /*destination buffer */ uint8_t *b = NULL; /*background buffer */ ssize_t s_stride, d_stride; /*src and dst strides */ ssize_t b_stride; /*bkg stride */ size_t safe; /*how many elements are safe to process in each pass */ - size_t bg_seq_len = 0; size_t src_base_size, dst_base_size;/*source & destination base size*/ void *conv_buf = NULL; /*temporary conversion buffer */ size_t conv_buf_size = 0; /*size of conversion buffer in bytes */ @@ -3055,13 +3053,13 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype") if(H5T_VLEN != src->shared->type) HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_VLEN datatype") - if(H5T_VLEN != dst->shared->type) + if(H5T_VLEN != dst->shared->type) HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_VLEN datatype") if(H5T_VLEN_STRING == src->shared->u.vlen.type && H5T_VLEN_STRING == dst->shared->u.vlen.type) { if((H5T_CSET_ASCII == src->shared->u.vlen.cset && H5T_CSET_UTF8 == dst->shared->u.vlen.cset) - || (H5T_CSET_ASCII == dst->shared->u.vlen.cset && H5T_CSET_UTF8 == src->shared->u.vlen.cset)) + || (H5T_CSET_ASCII == dst->shared->u.vlen.cset && H5T_CSET_UTF8 == src->shared->u.vlen.cset)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "The library doesn't convert between strings of ASCII and UTF") - } + } /* end if */ /* Variable-length types don't need a background buffer */ cdata->need_bkg = H5T_BKG_NO; @@ -3179,25 +3177,27 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, } /* end else */ for(elmtno = 0; elmtno < safe; elmtno++) { + hbool_t is_nil; /* Whether sequence is "nil" */ + /* Check for "nil" source sequence */ - if((*(src->shared->u.vlen.isnull))(src->shared->u.vlen.f, s)) { + if((*(src->shared->u.vlen.cls->isnull))(src->shared->u.vlen.f, s, &is_nil) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't check if VL data is 'nil'") + else if(is_nil) { /* Write "nil" sequence to destination location */ - if((*(dst->shared->u.vlen.setnull))(dst->shared->u.vlen.f, d, b) < 0) + if((*(dst->shared->u.vlen.cls->setnull))(dst->shared->u.vlen.f, d, b) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't set VL data to 'nil'") - } /* end if */ + } /* end else-if */ else { - ssize_t sseq_len; /* (signed) The number of elements in the current sequence*/ - size_t seq_len; /* The number of elements in the current sequence*/ + size_t seq_len; /* The number of elements in the current sequence */ /* Get length of element sequences */ - if((sseq_len = (*(src->shared->u.vlen.getlen))(s)) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length") - seq_len = (size_t)sseq_len; + if((*(src->shared->u.vlen.cls->getlen))(src->shared->u.vlen.f, s, &seq_len) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "bad sequence length") /* If we are reading from memory and there is no conversion, just get the pointer to sequence */ if(write_to_file && noop_conv) { /* Get direct pointer to sequence */ - if(NULL == (conv_buf = (*(src->shared->u.vlen.getptr))(s))) + if(NULL == (conv_buf = (*(src->shared->u.vlen.cls->getptr))(s))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid source pointer") } /* end if */ else { @@ -3213,17 +3213,17 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, conv_buf_size = ((1 / H5T_VLEN_MIN_CONF_BUF_SIZE) + 1) * H5T_VLEN_MIN_CONF_BUF_SIZE; if(NULL == (conv_buf = H5FL_BLK_CALLOC(vlen_seq, conv_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion") - } + } /* end if */ else if(conv_buf_size < MAX(src_size, dst_size)) { /* Only allocate conversion buffer in H5T_VLEN_MIN_CONF_BUF_SIZE increments */ conv_buf_size = ((MAX(src_size, dst_size) / H5T_VLEN_MIN_CONF_BUF_SIZE) + 1) * H5T_VLEN_MIN_CONF_BUF_SIZE; if(NULL == (conv_buf = H5FL_BLK_REALLOC(vlen_seq, conv_buf, conv_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion") HDmemset(conv_buf, 0, conv_buf_size); - } /* end if */ + } /* end else-if */ /* Read in VL sequence */ - if((*(src->shared->u.vlen.read))(src->shared->u.vlen.f, s, conv_buf, src_size) < 0) + if((*(src->shared->u.vlen.cls->read))(src->shared->u.vlen.f, s, conv_buf, src_size) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data") } /* end else */ @@ -3241,9 +3241,14 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, /* If we are writing and there is a nested VL type, read * the sequence into the background buffer */ if(nested) { - const uint8_t *tmp = b; + /* Sanity check */ + HDassert(write_to_file); + + /* Get length of background element sequence */ + if((*(dst->shared->u.vlen.cls->getlen))(dst->shared->u.vlen.f, b, &bg_seq_len) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "bad sequence length") - UINT32DECODE(tmp, bg_seq_len); + /* Read sequence if length > 0 */ if(bg_seq_len > 0) { if(tmp_buf_size < (bg_seq_len * MAX(src_base_size, dst_base_size))) { tmp_buf_size = (bg_seq_len * MAX(src_base_size, dst_base_size)); @@ -3251,10 +3256,10 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion") HDmemset(tmp_buf, 0, tmp_buf_size); } /* end if */ - H5F_addr_decode(dst->shared->u.vlen.f, &tmp, &(bg_hobjid.addr)); - UINT32DECODE(tmp, bg_hobjid.idx); - if(NULL == H5HG_read(dst->shared->u.vlen.f, &bg_hobjid, tmp_buf, NULL)) - HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL sequence into background buffer") + + /* Read in background VL sequence */ + if((*(dst->shared->u.vlen.cls->read))(dst->shared->u.vlen.f, b, tmp_buf, bg_seq_len) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data") } /* end if */ /* If the sequence gets shorter, pad out the original sequence with zeros */ @@ -3268,26 +3273,23 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, } /* end if */ /* Write sequence to destination location */ - if((*(dst->shared->u.vlen.write))(dst->shared->u.vlen.f, &vl_alloc_info, d, conv_buf, b, seq_len, dst_base_size) < 0) + if((*(dst->shared->u.vlen.cls->write))(dst->shared->u.vlen.f, &vl_alloc_info, d, conv_buf, b, seq_len, dst_base_size) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data") if(!noop_conv) { /* For nested VL case, free leftover heap objects from the deeper level if the length of new data elements is shorter than the old data elements.*/ if(nested && seq_len < bg_seq_len) { - size_t parent_seq_len; const uint8_t *tmp; size_t u; - /* TMP_P is reset each time in the loop because DST_BASE_SIZE may include some data in addition to VL info. - SLU */ - for(u = seq_len; u < bg_seq_len; u++) { - tmp = (uint8_t *)tmp_buf + u * dst_base_size; - UINT32DECODE(tmp, parent_seq_len); - if(parent_seq_len > 0) { - H5F_addr_decode(dst->shared->u.vlen.f, &tmp, &(parent_hobjid.addr)); - UINT32DECODE(tmp, parent_hobjid.idx); - if(H5HG_remove(dst->shared->u.vlen.f, &parent_hobjid) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") - } /* end if */ + /* Sanity check */ + HDassert(write_to_file); + + tmp = (uint8_t *)tmp_buf + seq_len * dst_base_size; + for(u = seq_len; u < bg_seq_len; u++, tmp += dst_base_size) { + /* Delete sequence in destination location */ + if((*(dst->shared->u.vlen.cls->del))(dst->shared->u.vlen.f, tmp) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove heap object") } /* end for */ } /* end if */ } /* end if */ diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 7798e37..281026c 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -243,14 +243,6 @@ typedef struct H5T_enum_t { char **name; /*array of symbol names */ } H5T_enum_t; -/* VL function pointers */ -typedef ssize_t (*H5T_vlen_getlenfunc_t)(const void *vl_addr); -typedef void * (*H5T_vlen_getptrfunc_t)(void *vl_addr); -typedef htri_t (*H5T_vlen_isnullfunc_t)(const H5F_t *f, void *vl_addr); -typedef herr_t (*H5T_vlen_readfunc_t)(H5F_t *f, void *_vl, void *buf, size_t len); -typedef herr_t (*H5T_vlen_writefunc_t)(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size); -typedef herr_t (*H5T_vlen_setnullfunc_t)(H5F_t *f, void *_vl, void *_bg); - /* VL types */ typedef enum { H5T_VLEN_BADTYPE = -1, /* invalid VL Type */ @@ -259,20 +251,35 @@ typedef enum { H5T_VLEN_MAXTYPE /* highest type (Invalid as true type) */ } H5T_vlen_type_t; +/* VL function pointers */ +typedef herr_t (*H5T_vlen_getlen_func_t)(H5F_t *f, const void *vl_addr, size_t *len); +typedef void * (*H5T_vlen_getptr_func_t)(void *vl_addr); +typedef herr_t (*H5T_vlen_isnull_func_t)(const H5F_t *f, void *vl_addr, hbool_t *isnull); +typedef herr_t (*H5T_vlen_setnull_func_t)(H5F_t *f, void *_vl, void *_bg); +typedef herr_t (*H5T_vlen_read_func_t)(H5F_t *f, void *_vl, void *buf, size_t len); +typedef herr_t (*H5T_vlen_write_func_t)(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size); +typedef herr_t (*H5T_vlen_delete_func_t)(H5F_t *f, const void *_vl); + +/* VL datatype callbacks */ +typedef struct H5T_vlen_class_t { + H5T_vlen_getlen_func_t getlen; /* Function to get VL sequence size (in element units, not bytes) */ + H5T_vlen_getptr_func_t getptr; /* Function to get VL sequence pointer */ + H5T_vlen_isnull_func_t isnull; /* Function to check if VL value is NIL */ + H5T_vlen_setnull_func_t setnull;/* Function to set a VL value to NIL */ + H5T_vlen_read_func_t read; /* Function to read VL sequence into buffer */ + H5T_vlen_write_func_t write; /* Function to write VL sequence from buffer */ + H5T_vlen_delete_func_t del; /* Function to delete VL sequence */ +} H5T_vlen_class_t; + /* A VL datatype */ typedef struct H5T_vlen_t { H5T_vlen_type_t type; /* Type of VL data in buffer */ H5T_loc_t loc; /* Location of VL data in buffer */ - H5T_cset_t cset; /* For VL string. character set */ - H5T_str_t pad; /* For VL string. space or null padding of + H5T_cset_t cset; /* For VL string: character set */ + H5T_str_t pad; /* For VL string: space or null padding of * extra bytes */ H5F_t *f; /* File ID (if VL data is on disk) */ - H5T_vlen_getptrfunc_t getptr; /* Function to get VL sequence pointer */ - H5T_vlen_getlenfunc_t getlen; /* Function to get VL sequence size (in element units, not bytes) */ - H5T_vlen_isnullfunc_t isnull; /* Function to check if VL value is NIL */ - H5T_vlen_readfunc_t read; /* Function to read VL sequence into buffer */ - H5T_vlen_writefunc_t write; /* Function to write VL sequence from buffer */ - H5T_vlen_setnullfunc_t setnull; /* Function to set a VL value to NIL */ + const H5T_vlen_class_t *cls; /* Pointer to VL class callbacks */ } H5T_vlen_t; /* An opaque datatype */ diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index bafb47f..e14bd27 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -16,41 +16,121 @@ * datatypes in the H5T interface. */ +/****************/ +/* Module Setup */ +/****************/ + #include "H5Tmodule.h" /* This source code file is part of the H5T module */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ -#include "H5Dprivate.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ -#include "H5HGprivate.h" /* Global Heaps */ +#include "H5Fprivate.h" /* File access */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ -#include "H5Pprivate.h" /* Property lists */ #include "H5Tpkg.h" /* Datatypes */ -/* Local functions */ -static herr_t H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info); -static ssize_t H5T_vlen_seq_mem_getlen(const void *_vl); -static void * H5T_vlen_seq_mem_getptr(void *_vl); -static htri_t H5T_vlen_seq_mem_isnull(const H5F_t *f, void *_vl); -static herr_t H5T_vlen_seq_mem_read(H5F_t *f, void *_vl, void *_buf, size_t len); -static herr_t H5T_vlen_seq_mem_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); -static herr_t H5T_vlen_seq_mem_setnull(H5F_t *f, void *_vl, void *_bg); -static ssize_t H5T_vlen_str_mem_getlen(const void *_vl); -static void * H5T_vlen_str_mem_getptr(void *_vl); -static htri_t H5T_vlen_str_mem_isnull(const H5F_t *f, void *_vl); -static herr_t H5T_vlen_str_mem_read(H5F_t *f, void *_vl, void *_buf, size_t len); -static herr_t H5T_vlen_str_mem_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); -static herr_t H5T_vlen_str_mem_setnull(H5F_t *f, void *_vl, void *_bg); -static ssize_t H5T_vlen_disk_getlen(const void *_vl); -static void * H5T_vlen_disk_getptr(void *_vl); -static htri_t H5T_vlen_disk_isnull(const H5F_t *f, void *_vl); -static herr_t H5T_vlen_disk_read(H5F_t *f, void *_vl, void *_buf, size_t len); -static herr_t H5T_vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); -static herr_t H5T_vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg); - -/* Local variables */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5T__vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info); + +/* Memory-based VL sequence callbacks */ +static herr_t H5T__vlen_mem_seq_getlen(H5F_t *f, const void *_vl, size_t *len); +static void * H5T__vlen_mem_seq_getptr(void *_vl); +static herr_t H5T__vlen_mem_seq_isnull(const H5F_t *f, void *_vl, hbool_t *isnull); +static herr_t H5T__vlen_mem_seq_setnull(H5F_t *f, void *_vl, void *_bg); +static herr_t H5T__vlen_mem_seq_read(H5F_t *f, void *_vl, void *_buf, size_t len); +static herr_t H5T__vlen_mem_seq_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); + +/* Memory-based VL string callbacks */ +static herr_t H5T__vlen_mem_str_getlen(H5F_t *f, const void *_vl, size_t *len); +static void * H5T__vlen_mem_str_getptr(void *_vl); +static herr_t H5T__vlen_mem_str_isnull(const H5F_t *f, void *_vl, hbool_t *isnull); +static herr_t H5T__vlen_mem_str_setnull(H5F_t *f, void *_vl, void *_bg); +static herr_t H5T__vlen_mem_str_read(H5F_t *f, void *_vl, void *_buf, size_t len); +static herr_t H5T__vlen_mem_str_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); + +/* Disk-based VL sequence (and string) callbacks */ +static herr_t H5T__vlen_disk_getlen(H5F_t *f, const void *_vl, size_t *len); +static herr_t H5T__vlen_disk_isnull(const H5F_t *f, void *_vl, hbool_t *isnull); +static herr_t H5T__vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg); +static herr_t H5T__vlen_disk_read(H5F_t *f, void *_vl, void *_buf, size_t len); +static herr_t H5T__vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); +static herr_t H5T__vlen_disk_delete(H5F_t *f, const void *_vl); + + +/*********************/ +/* Public Variables */ +/*********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Class for VL seqences in memory */ +static const H5T_vlen_class_t H5T_vlen_mem_seq_g = { + H5T__vlen_mem_seq_getlen, /* 'getlen' */ + H5T__vlen_mem_seq_getptr, /* 'getptr' */ + H5T__vlen_mem_seq_isnull, /* 'isnull' */ + H5T__vlen_mem_seq_setnull, /* 'setnull' */ + H5T__vlen_mem_seq_read, /* 'read' */ + H5T__vlen_mem_seq_write, /* 'write' */ + NULL /* 'delete' */ +}; + +/* Class for VL strings in memory */ +static const H5T_vlen_class_t H5T_vlen_mem_str_g = { + H5T__vlen_mem_str_getlen, /* 'getlen' */ + H5T__vlen_mem_str_getptr, /* 'getptr' */ + H5T__vlen_mem_str_isnull, /* 'isnull' */ + H5T__vlen_mem_str_setnull, /* 'setnull' */ + H5T__vlen_mem_str_read, /* 'read' */ + H5T__vlen_mem_str_write, /* 'write' */ + NULL /* 'delete' */ +}; + +/* Class for both VL strings and seqences in file */ +static const H5T_vlen_class_t H5T_vlen_disk_g = { + H5T__vlen_disk_getlen, /* 'getlen' */ + NULL, /* 'getptr' */ + H5T__vlen_disk_isnull, /* 'isnull' */ + H5T__vlen_disk_setnull, /* 'setnull' */ + H5T__vlen_disk_read, /* 'read' */ + H5T__vlen_disk_write, /* 'write' */ + H5T__vlen_disk_delete /* 'delete' */ +}; @@ -194,32 +274,21 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) dt->shared->u.vlen.loc = H5T_LOC_MEMORY; if(dt->shared->u.vlen.type == H5T_VLEN_SEQUENCE) { - /* size in memory, disk size is different */ + /* Size in memory, disk size is different */ dt->shared->size = sizeof(hvl_t); /* Set up the function pointers to access the VL sequence in memory */ - dt->shared->u.vlen.getlen = H5T_vlen_seq_mem_getlen; - dt->shared->u.vlen.getptr = H5T_vlen_seq_mem_getptr; - dt->shared->u.vlen.isnull = H5T_vlen_seq_mem_isnull; - dt->shared->u.vlen.read = H5T_vlen_seq_mem_read; - dt->shared->u.vlen.write = H5T_vlen_seq_mem_write; - dt->shared->u.vlen.setnull = H5T_vlen_seq_mem_setnull; - } + dt->shared->u.vlen.cls = &H5T_vlen_mem_seq_g; + } /* end if */ else if(dt->shared->u.vlen.type == H5T_VLEN_STRING) { - /* size in memory, disk size is different */ + /* Size in memory, disk size is different */ dt->shared->size = sizeof(char *); /* Set up the function pointers to access the VL string in memory */ - dt->shared->u.vlen.getlen = H5T_vlen_str_mem_getlen; - dt->shared->u.vlen.getptr = H5T_vlen_str_mem_getptr; - dt->shared->u.vlen.isnull = H5T_vlen_str_mem_isnull; - dt->shared->u.vlen.read = H5T_vlen_str_mem_read; - dt->shared->u.vlen.write = H5T_vlen_str_mem_write; - dt->shared->u.vlen.setnull = H5T_vlen_str_mem_setnull; - } - else { + dt->shared->u.vlen.cls = &H5T_vlen_mem_str_g; + } /* end else-if */ + else HDassert(0 && "Invalid VL type"); - } /* Reset file ID (since this VL is in memory) */ dt->shared->u.vlen.f = NULL; @@ -234,18 +303,13 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* * Size of element on disk is 4 bytes for the length, plus the size * of an address in this file, plus 4 bytes for the size of a heap - * ID. Memory size is different + * ID. Memory size is different. */ dt->shared->size = 4 + (size_t)H5F_SIZEOF_ADDR(f) + 4; /* Set up the function pointers to access the VL information on disk */ /* VL sequences and VL strings are stored identically on disk, so use the same functions */ - dt->shared->u.vlen.getlen = H5T_vlen_disk_getlen; - dt->shared->u.vlen.getptr = H5T_vlen_disk_getptr; - dt->shared->u.vlen.isnull = H5T_vlen_disk_isnull; - dt->shared->u.vlen.read = H5T_vlen_disk_read; - dt->shared->u.vlen.write = H5T_vlen_disk_write; - dt->shared->u.vlen.setnull = H5T_vlen_disk_setnull; + dt->shared->u.vlen.cls = &H5T_vlen_disk_g; /* Set file ID (since this VL is on disk) */ dt->shared->u.vlen.f = f; @@ -255,6 +319,13 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Allow undefined location. In H5Odtype.c, H5O_dtype_decode sets undefined * location for VL type and leaves it for the caller to decide. */ + dt->shared->u.vlen.loc = H5T_LOC_BADLOC; + + /* Reset the function pointers to access the VL information */ + dt->shared->u.vlen.cls = NULL; + + /* Reset file pointer */ + dt->shared->u.vlen.f = NULL; break; case H5T_LOC_MAXLOC: @@ -269,11 +340,11 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__vlen_set_loc() */ +} /* end H5T__vlen_set_loc() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_getlen + * Function: H5T__vlen_mem_seq_getlen * * Purpose: Retrieves the length of a memory based VL element. * @@ -284,33 +355,35 @@ done: * *------------------------------------------------------------------------- */ -static ssize_t -H5T_vlen_seq_mem_getlen(const void *_vl) +static herr_t +H5T__vlen_mem_seq_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *len) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ #else hvl_t vl; /* User's hvl_t information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR - /* check parameters, return result */ -#ifdef H5_NO_ALIGNMENT_RESTRICTIONS - HDassert(vl); + /* Check parameter */ + HDassert(_vl); + HDassert(len); - FUNC_LEAVE_NOAPI((ssize_t)vl->len) +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + *len = vl->len; #else - HDassert(_vl); H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); - FUNC_LEAVE_NOAPI((ssize_t)vl.len) + *len = vl.len; #endif -} /* end H5T_vlen_seq_mem_getlen() */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T__vlen_mem_seq_getlen() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_getptr + * Function: H5T__vlen_mem_seq_getptr * * Purpose: Retrieves the pointer for a memory based VL element. * @@ -322,15 +395,15 @@ H5T_vlen_seq_mem_getlen(const void *_vl) *------------------------------------------------------------------------- */ static void * -H5T_vlen_seq_mem_getptr(void *_vl) +H5T__vlen_mem_seq_getptr(void *_vl) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ #else hvl_t vl; /* User's hvl_t information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* check parameters, return result */ #ifdef H5_NO_ALIGNMENT_RESTRICTIONS @@ -343,48 +416,82 @@ H5T_vlen_seq_mem_getptr(void *_vl) FUNC_LEAVE_NOAPI(vl.p) #endif -} /* end H5T_vlen_seq_mem_getptr() */ +} /* end H5T__vlen_mem_seq_getptr() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_isnull + * Function: H5T__vlen_mem_seq_isnull * * Purpose: Checks if a memory sequence is the "null" sequence * - * Return: TRUE/FALSE on success/Negative on failure + * Return: Non-negative on success / Negative on failure * * Programmer: Quincey Koziol * Saturday, November 8, 2003 * *------------------------------------------------------------------------- */ -static htri_t -H5T_vlen_seq_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl) +static herr_t +H5T__vlen_mem_seq_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl, hbool_t *isnull) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ #else hvl_t vl; /* User's hvl_t information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR - /* check parameters, return result */ -#ifdef H5_NO_ALIGNMENT_RESTRICTIONS - HDassert(vl); + /* Check parameters */ + HDassert(_vl); - FUNC_LEAVE_NOAPI((vl->len==0 || vl->p==NULL) ? TRUE : FALSE) +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + *isnull = ((vl->len == 0 || vl->p == NULL) ? TRUE : FALSE); #else - HDassert(_vl); H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); - FUNC_LEAVE_NOAPI((vl.len==0 || vl.p==NULL) ? TRUE : FALSE) + *isnull = ((vl.len == 0 || vl.p == NULL) ? TRUE : FALSE); #endif -} /* end H5T_vlen_seq_mem_isnull() */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T__vlen_mem_seq_isnull() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_read + * Function: H5T__vlen_mem_seq_setnull + * + * Purpose: Sets a VL info object in memory to the "nil" value + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__vlen_mem_seq_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg) +{ + hvl_t vl; /* Temporary hvl_t to use during operation */ + + FUNC_ENTER_STATIC_NOERR + + /* check parameters */ + HDassert(_vl); + + /* Set the "nil" hvl_t */ + vl.len = 0; + vl.p = NULL; + + /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ + H5MM_memcpy(_vl, &vl, sizeof(hvl_t)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T__vlen_mem_seq_setnull() */ + + +/*------------------------------------------------------------------------- + * Function: H5T__vlen_mem_seq_read * * Purpose: "Reads" the memory based VL sequence into a buffer * @@ -396,36 +503,36 @@ H5T_vlen_seq_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl) *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_seq_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) +H5T__vlen_mem_seq_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */ #else hvl_t vl; /* User's hvl_t information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* check parameters, copy data */ HDassert(buf); #ifdef H5_NO_ALIGNMENT_RESTRICTIONS HDassert(vl && vl->p); - H5MM_memcpy(buf,vl->p,len); + H5MM_memcpy(buf, vl->p, len); #else HDassert(_vl); H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); HDassert(vl.p); - H5MM_memcpy(buf,vl.p,len); + H5MM_memcpy(buf, vl.p, len); #endif FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5T_vlen_seq_mem_read() */ +} /* end H5T__vlen_mem_seq_read() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_write + * Function: H5T__vlen_mem_seq_write * * Purpose: "Writes" the memory based VL sequence from a buffer * @@ -437,104 +544,104 @@ H5T_vlen_seq_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_seq_mem_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size) +H5T__vlen_mem_seq_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size) { hvl_t vl; /* Temporary hvl_t to use during operation */ - size_t len; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* check parameters */ HDassert(_vl); HDassert(buf); - if(seq_len!=0) { - len=seq_len*base_size; + if(seq_len) { + size_t len = seq_len * base_size; /* Sequence size */ /* Use the user's memory allocation routine is one is defined */ - if(vl_alloc_info->alloc_func!=NULL) { - if(NULL==(vl.p=(vl_alloc_info->alloc_func)(len,vl_alloc_info->alloc_info))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data") + if(vl_alloc_info->alloc_func != NULL) { + if(NULL == (vl.p = (vl_alloc_info->alloc_func)(len, vl_alloc_info->alloc_info))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "application memory allocation routine failed for VL data") } /* end if */ - else { /* Default to system malloc */ + else /* Default to system malloc */ if(NULL == (vl.p = HDmalloc(len))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data") - } /* end else */ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data") /* Copy the data into the newly allocated buffer */ - H5MM_memcpy(vl.p,buf,len); - + H5MM_memcpy(vl.p, buf, len); } /* end if */ else - vl.p=NULL; + vl.p = NULL; /* Set the sequence length */ - vl.len=seq_len; + vl.len = seq_len; /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - H5MM_memcpy(_vl,&vl,sizeof(hvl_t)); + H5MM_memcpy(_vl, &vl, sizeof(hvl_t)); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_seq_mem_write() */ +} /* end H5T__vlen_mem_seq_write() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_seq_mem_setnull + * Function: H5T__vlen_mem_str_getlen * - * Purpose: Sets a VL info object in memory to the "nil" value + * Purpose: Retrieves the length of a memory based VL string. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Saturday, November 8, 2003 + * Wednesday, June 2, 1999 * *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_seq_mem_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg) +H5T__vlen_mem_str_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *len) { - hvl_t vl; /* Temporary hvl_t to use during operation */ +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + const char *s = *(const char * const *)_vl; /* Pointer to the user's string information */ +#else + const char *s = NULL; /* Pointer to the user's string information */ +#endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* check parameters */ HDassert(_vl); - /* Set the "nil" hvl_t */ - vl.len=0; - vl.p=NULL; +#ifndef H5_NO_ALIGNMENT_RESTRICTIONS + H5MM_memcpy(&s, _vl, sizeof(char *)); +#endif - /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - H5MM_memcpy(_vl,&vl,sizeof(hvl_t)); + *len = HDstrlen(s); FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5T_vlen_seq_mem_setnull() */ +} /* end H5T__vlen_mem_str_getlen() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_getlen + * Function: H5T__vlen_mem_str_getptr * - * Purpose: Retrieves the length of a memory based VL string. + * Purpose: Retrieves the pointer for a memory based VL string. * - * Return: Non-negative on success/Negative on failure + * Return: Non-NULL on success/NULL on failure * * Programmer: Quincey Koziol - * Wednesday, June 2, 1999 + * Saturday, June 12, 2004 * *------------------------------------------------------------------------- */ -static ssize_t -H5T_vlen_str_mem_getlen(const void *_vl) +static void * +H5T__vlen_mem_str_getptr(void *_vl) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const char *s=*(const char * const *)_vl; /* Pointer to the user's string information */ + char *s = *(char **)_vl; /* Pointer to the user's string information */ #else - const char *s = NULL; /* Pointer to the user's string information */ + char *s = NULL; /* Pointer to the user's string information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* check parameters */ #ifdef H5_NO_ALIGNMENT_RESTRICTIONS @@ -544,78 +651,71 @@ H5T_vlen_str_mem_getlen(const void *_vl) H5MM_memcpy(&s, _vl, sizeof(char *)); #endif - FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(s)) -} /* end H5T_vlen_str_mem_getlen() */ + FUNC_LEAVE_NOAPI(s) +} /* end H5T__vlen_mem_str_getptr() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_getptr + * Function: H5T__vlen_mem_str_isnull * - * Purpose: Retrieves the pointer for a memory based VL string. + * Purpose: Checks if a memory string is a NULL pointer * - * Return: Non-NULL on success/NULL on failure + * Return: Non-negative on success / Negative on failure * * Programmer: Quincey Koziol - * Saturday, June 12, 2004 + * Saturday, November 8, 2003 * *------------------------------------------------------------------------- */ -static void * -H5T_vlen_str_mem_getptr(void *_vl) +static herr_t +H5T__vlen_mem_str_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl, hbool_t *isnull) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - char *s=*(char **)_vl; /* Pointer to the user's string information */ + char *s = *(char **)_vl; /* Pointer to the user's string information */ #else char *s = NULL; /* Pointer to the user's string information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR - /* check parameters */ -#ifdef H5_NO_ALIGNMENT_RESTRICTIONS - HDassert(s); -#else - HDassert(_vl); +#ifndef H5_NO_ALIGNMENT_RESTRICTIONS H5MM_memcpy(&s, _vl, sizeof(char *)); #endif - FUNC_LEAVE_NOAPI(s) -} /* end H5T_vlen_str_mem_getptr() */ + *isnull = (s == NULL ? TRUE : FALSE); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T__vlen_mem_str_isnull() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_isnull + * Function: H5T__vlen_mem_str_setnull * - * Purpose: Checks if a memory string is a NULL pointer + * Purpose: Sets a VL info object in memory to the "null" value * - * Return: TRUE/FALSE on success/Negative on failure + * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Saturday, November 8, 2003 * *------------------------------------------------------------------------- */ -static htri_t -H5T_vlen_str_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl) +static herr_t +H5T__vlen_mem_str_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg) { -#ifdef H5_NO_ALIGNMENT_RESTRICTIONS - char *s=*(char **)_vl; /* Pointer to the user's string information */ -#else - char *s = NULL; /* Pointer to the user's string information */ -#endif + char *t = NULL; /* Pointer to temporary buffer allocated */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR -#ifndef H5_NO_ALIGNMENT_RESTRICTIONS - H5MM_memcpy(&s, _vl, sizeof(char *)); -#endif + /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ + H5MM_memcpy(_vl, &t, sizeof(char *)); - FUNC_LEAVE_NOAPI(s==NULL ? TRUE : FALSE) -} /* end H5T_vlen_str_mem_isnull() */ + FUNC_LEAVE_NOAPI(SUCCEED) /*lint !e429 The pointer in 't' has been copied */ +} /* end H5T__vlen_mem_str_setnull() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_read + * Function: H5T__vlen_mem_str_read * * Purpose: "Reads" the memory based VL string into a buffer * @@ -627,17 +727,17 @@ H5T_vlen_str_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl) *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_str_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) +H5T__vlen_mem_str_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - char *s=*(char **)_vl; /* Pointer to the user's string information */ + char *s = *(char **)_vl; /* Pointer to the user's string information */ #else char *s; /* Pointer to the user's string information */ #endif - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR - if(len>0) { + if(len > 0) { /* check parameters */ HDassert(buf); #ifdef H5_NO_ALIGNMENT_RESTRICTIONS @@ -647,15 +747,15 @@ H5T_vlen_str_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) H5MM_memcpy(&s, _vl, sizeof(char *)); #endif - H5MM_memcpy(buf,s,len); + H5MM_memcpy(buf, s, len); } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5T_vlen_str_mem_read() */ +} /* end H5T__vlen_mem_str_read() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_write + * Function: H5T__vlen_mem_str_write * * Purpose: "Writes" the memory based VL string from a buffer * @@ -667,68 +767,42 @@ H5T_vlen_str_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len) *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_str_mem_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, +H5T__vlen_mem_str_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size) { char *t; /* Pointer to temporary buffer allocated */ size_t len; /* Maximum length of the string to copy */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* check parameters */ HDassert(buf); /* Use the user's memory allocation routine if one is defined */ - if(vl_alloc_info->alloc_func!=NULL) { - if(NULL==(t = (char *)(vl_alloc_info->alloc_func)((seq_len+1)*base_size,vl_alloc_info->alloc_info))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data") - } /* end if */ - else { /* Default to system malloc */ + if(vl_alloc_info->alloc_func != NULL) { + if(NULL == (t = (char *)(vl_alloc_info->alloc_func)((seq_len + 1) * base_size, vl_alloc_info->alloc_info))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "application memory allocation routine failed for VL data") + } /* end if */ + else /* Default to system malloc */ if(NULL == (t = (char *)HDmalloc((seq_len + 1) * base_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data") - } /* end else */ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data") - len=(seq_len*base_size); - H5MM_memcpy(t,buf,len); - t[len]='\0'; + /* 'write' the string into the buffer, with memcpy() */ + len = (seq_len * base_size); + H5MM_memcpy(t, buf, len); + t[len] = '\0'; /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - H5MM_memcpy(_vl,&t,sizeof(char *)); + H5MM_memcpy(_vl, &t, sizeof(char *)); done: FUNC_LEAVE_NOAPI(ret_value) /*lint !e429 The pointer in 't' has been copied */ -} /* end H5T_vlen_str_mem_write() */ +} /* end H5T__vlen_mem_str_write() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_str_mem_setnull - * - * Purpose: Sets a VL info object in memory to the "null" value - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Saturday, November 8, 2003 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5T_vlen_str_mem_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg) -{ - char *t=NULL; /* Pointer to temporary buffer allocated */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - H5MM_memcpy(_vl,&t,sizeof(char *)); - - FUNC_LEAVE_NOAPI(SUCCEED) /*lint !e429 The pointer in 't' has been copied */ -} /* end H5T_vlen_str_mem_setnull() */ - - -/*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_getlen + * Function: H5T__vlen_disk_getlen * * Purpose: Retrieves the length of a disk based VL element. * @@ -739,82 +813,108 @@ H5T_vlen_str_mem_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED * *------------------------------------------------------------------------- */ -static ssize_t -H5T_vlen_disk_getlen(const void *_vl) +static herr_t +H5T__vlen_disk_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *seq_len) { - const uint8_t *vl=(const uint8_t *)_vl; /* Pointer to the disk VL information */ - size_t seq_len = 0; /* Sequence length */ + const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC - /* check parameters */ + /* Check parameters */ + HDassert(f); HDassert(vl); + HDassert(seq_len); - UINT32DECODE(vl, seq_len); + /* Get length of sequence (different from blob size) */ + UINT32DECODE(vl, *seq_len); - FUNC_LEAVE_NOAPI((ssize_t)seq_len) -} /* end H5T_vlen_disk_getlen() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__vlen_disk_getlen() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_getptr + * Function: H5T__vlen_disk_isnull * - * Purpose: Retrieves the pointer to a disk based VL element. + * Purpose: Checks if a disk VL info object is the "nil" object * - * Return: Non-NULL on success/NULL on failure + * Return: Non-negative on success / Negative on failure * * Programmer: Quincey Koziol - * Saturday, June 12, 2004 + * Saturday, November 8, 2003 * *------------------------------------------------------------------------- */ -static void * -H5T_vlen_disk_getptr(void H5_ATTR_UNUSED *vl) +static herr_t +H5T__vlen_disk_isnull(const H5F_t *f, void *_vl, hbool_t *isnull) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + herr_t ret_value = SUCCEED; /* Return value */ - /* check parameters */ + FUNC_ENTER_STATIC + + /* Check parameters */ + HDassert(f); HDassert(vl); + HDassert(isnull); + + /* Skip the sequence's length */ + vl += 4; - FUNC_LEAVE_NOAPI(NULL) -} /* end H5T_vlen_disk_getptr() */ + /* Check if blob ID is "nil" */ + if(H5VL_blob_specific(H5F_VOL_CLS(f), vl, H5VL_BLOB_ISNULL, f, isnull) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to check if a blob ID is 'nil'") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__vlen_disk_isnull() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_isnull + * Function: H5T__vlen_disk_setnull * - * Purpose: Checks if a disk VL info object is the "nil" object + * Purpose: Sets a VL info object on disk to the "nil" value * - * Return: TRUE/FALSE on success/Negative on failure + * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Saturday, November 8, 2003 * *------------------------------------------------------------------------- */ -static htri_t -H5T_vlen_disk_isnull(const H5F_t *f, void *_vl) +static herr_t +H5T__vlen_disk_setnull(H5F_t *f, void *_vl, void *bg) { - uint8_t *vl = (uint8_t *)_vl; /* Pointer to the disk VL information */ - haddr_t addr; /* Sequence's heap address */ + uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC /* check parameters */ + HDassert(f); HDassert(vl); - /* Skip the sequence's length */ - vl += 4; + /* Free heap object for old data */ + if(bg != NULL) + /* Delete sequence in destination location */ + if(H5T__vlen_disk_delete(f, bg) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object") - /* Get the heap address */ - H5F_addr_decode(f, (const uint8_t **)&vl, &addr); + /* Set the length of the sequence */ + UINT32ENCODE(vl, 0); - FUNC_LEAVE_NOAPI(addr == 0 ? TRUE : FALSE) -} /* end H5T_vlen_disk_isnull() */ + /* Set blob ID to "nil" */ + if(H5VL_blob_specific(H5F_VOL_CLS(f), vl, H5VL_BLOB_SETNULL, f) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set a blob ID to 'nil'") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__vlen_disk_setnull() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_read + * Function: H5T__vlen_disk_read * * Purpose: Reads the disk based VL element into a buffer * @@ -826,40 +926,32 @@ H5T_vlen_disk_isnull(const H5F_t *f, void *_vl) *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_disk_read(H5F_t *f, void *_vl, void *buf, size_t H5_ATTR_UNUSED len) +H5T__vlen_disk_read(H5F_t *f, void *_vl, void *buf, size_t H5_ATTR_UNUSED len) { - uint8_t *vl=(uint8_t *)_vl; /* Pointer to the user's hvl_t information */ - H5HG_t hobjid; - herr_t ret_value=SUCCEED; /* Return value */ + const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC - /* check parameters */ + /* Check parameters */ + HDassert(f); HDassert(vl); HDassert(buf); - HDassert(f); /* Skip the length of the sequence */ vl += 4; - /* Get the heap information */ - H5F_addr_decode(f, (const uint8_t **)&vl, &(hobjid.addr)); - UINT32DECODE(vl, hobjid.idx); - - /* Check if this sequence actually has any data */ - if(hobjid.addr > 0) { - /* Read the VL information from disk */ - if(NULL == H5HG_read(f, &hobjid, buf, NULL)) - HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read VL information") - } + /* Retrieve blob */ + if(H5VL_blob_get(H5F_VOL_CLS(f), vl, f, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_disk_read() */ +} /* end H5T__vlen_disk_read() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_write + * Function: H5T__vlen_disk_write * * Purpose: Writes the disk based VL element from a buffer * @@ -871,122 +963,85 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t H5_ATTR_UNUSED *vl_alloc_info, +H5T__vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t H5_ATTR_UNUSED *vl_alloc_info, void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size) { - uint8_t *vl = (uint8_t *)_vl; /*Pointer to the user's hvl_t information*/ - uint8_t *bg = (uint8_t *)_bg; /*Pointer to the old data hvl_t */ - H5HG_t hobjid; /* New VL sequence's heap ID */ - size_t len; /* Size of new sequence on disk (in bytes) */ - herr_t ret_value = SUCCEED; /* Return value */ + uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + const uint8_t *bg = (const uint8_t *)_bg; /* Pointer to the old data hvl_t */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* check parameters */ HDassert(vl); HDassert(seq_len == 0 || buf); HDassert(f); - /* Free heap object for old data. */ - if(bg!=NULL) { - H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */ - - /* Skip the length of the sequence and heap object ID from background data. */ - bg += 4; - - /* Get heap information */ - H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr)); - UINT32DECODE(bg, bg_hobjid.idx); - - /* Free heap object for old data */ - if(bg_hobjid.addr > 0) { - /* Free heap object */ - if(H5HG_remove(f, &bg_hobjid) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") - } - } /* end if */ + /* Free heap object for old data, if non-NULL */ + if(bg != NULL) + if(H5T__vlen_disk_delete(f, bg) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object") /* Set the length of the sequence */ UINT32ENCODE(vl, seq_len); - /* Write the VL information to disk (allocates space also) */ - len = (seq_len*base_size); - if(H5HG_insert(f, len, buf, &hobjid) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write VL information") - - /* Encode the heap information */ - H5F_addr_encode(f, &vl, hobjid.addr); - UINT32ENCODE(vl, hobjid.idx); + /* Store blob */ + if(H5VL_blob_put(H5F_VOL_CLS(f), buf, (seq_len * base_size), f, vl) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_disk_write() */ +} /* end H5T__vlen_disk_write() */ /*------------------------------------------------------------------------- - * Function: H5T_vlen_disk_setnull + * Function: H5T__vlen_disk_delete * - * Purpose: Sets a VL info object on disk to the "nil" value + * Purpose: Deletes a disk-based VL element * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success / Negative on failure * * Programmer: Quincey Koziol - * Saturday, November 8, 2003 + * Friday, August 15, 2019 * *------------------------------------------------------------------------- */ static herr_t -H5T_vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg) +H5T__vlen_disk_delete(H5F_t *f, const void *_vl) { - uint8_t *vl = (uint8_t *)_vl; /*Pointer to the user's hvl_t information*/ - uint8_t *bg = (uint8_t *)_bg; /*Pointer to the old data hvl_t */ - uint32_t seq_len = 0; /* Sequence length */ - herr_t ret_value = SUCCEED; /* Return value */ + const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC - /* check parameters */ + /* Check parameters */ HDassert(f); - HDassert(vl); - - /* Free heap object for old data. */ - if(bg != NULL) { - H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */ - /* Skip the length of the sequence and heap object ID from background data. */ - bg += 4; + /* Free heap object for old data */ + if(vl != NULL) { + size_t seq_len; /* VL sequence's length */ - /* Get heap information */ - H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr)); - UINT32DECODE(bg, bg_hobjid.idx); + /* Get length of sequence */ + UINT32DECODE(vl, seq_len); - /* Free heap object for old data */ - if(bg_hobjid.addr > 0) { - /* Free heap object */ - if(H5HG_remove(f, &bg_hobjid) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") - } /* end if */ + /* Delete object, if length > 0 */ + if(seq_len > 0) + if(H5VL_blob_specific(H5F_VOL_CLS(f), (void *)vl, H5VL_BLOB_DELETE, f) < 0) /* Casting away 'const' OK -QAK */ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob") } /* end if */ - /* Set the length of the sequence */ - UINT32ENCODE(vl, seq_len); - - /* Encode the "nil" heap pointer information */ - H5F_addr_encode(f, &vl, (haddr_t)0); - UINT32ENCODE(vl, 0); - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_disk_setnull() */ +} /* end H5T__vlen_disk_delete() */ /*-------------------------------------------------------------------------- NAME - H5T_vlen_reclaim_recurse + H5T__vlen_reclaim_recurse PURPOSE Internal recursive routine to free VL datatypes USAGE - herr_t H5T_vlen_reclaim_recurse(elem,dt) + herr_t H5T__vlen_reclaim_recurse(elem,dt) void *elem; IN/OUT: Pointer to the dataset element H5T_t *dt; IN: Datatype of dataset element @@ -1002,13 +1057,14 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info) +H5T__vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info) { unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC + /* Sanity checks */ HDassert(elem); HDassert(dt); @@ -1022,8 +1078,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi /* Calculate the offset member and recurse on it */ for(u = 0; u < dt->shared->u.array.nelem; u++) { off = ((uint8_t *)elem) + u * (dt->shared->parent->shared->size); - if(H5T_vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free array element") + if(H5T__vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free array element") } /* end for */ } /* end if */ break; @@ -1037,8 +1093,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi /* Calculate the offset member and recurse on it */ off = ((uint8_t *)elem) + dt->shared->u.compnd.memb[u].offset; - if(H5T_vlen_reclaim_recurse(off, dt->shared->u.compnd.memb[u].type, free_func, free_info) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free compound field") + if(H5T__vlen_reclaim_recurse(off, dt->shared->u.compnd.memb[u].type, free_func, free_info) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free compound field") } /* end if */ } /* end for */ break; @@ -1057,8 +1113,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi /* Calculate the offset of each array element and recurse on it */ while(vl->len > 0) { off = ((uint8_t *)vl->p) + (vl->len - 1) * dt->shared->parent->shared->size; - if(H5T_vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free VL element") + if(H5T__vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free VL element") vl->len--; } /* end while */ } /* end if */ @@ -1102,7 +1158,7 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_reclaim_recurse() */ +} /* end H5T__vlen_reclaim_recurse() */ /*-------------------------------------------------------------------------- @@ -1139,6 +1195,7 @@ H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned H5_ATTR_UNUSED ndim, FUNC_ENTER_NOAPI(FAIL) + /* Sanity check */ HDassert(elem); HDassert(vl_alloc_info); HDassert(H5I_DATATYPE == H5I_get_type(type_id)); @@ -1148,20 +1205,20 @@ H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned H5_ATTR_UNUSED ndim, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") /* Pull the free function and free info pointer out of the op_data and call the recurse datatype free function */ - if(H5T_vlen_reclaim_recurse(elem, dt, vl_alloc_info->free_func, vl_alloc_info->free_info) < 0) + if(H5T__vlen_reclaim_recurse(elem, dt, vl_alloc_info->free_func, vl_alloc_info->free_info) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_vlen_reclaim() */ +} /* end H5T_vlen_reclaim() */ /*------------------------------------------------------------------------- * Function: H5T_vlen_reclaim_elmt * * Purpose: Alternative method to reclaim any VL data for a buffer element. - * - * Use this function when the datatype is already available, but + * + * Use this function when the datatype is already available, but * the allocation info is needed from the context before jumping * into recursion. * @@ -1188,10 +1245,10 @@ H5T_vlen_reclaim_elmt(void *elem, H5T_t *dt) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info") /* Recurse on buffer to free dynamic fields */ - if(H5T_vlen_reclaim_recurse(elem, dt, vl_alloc_info.free_func, vl_alloc_info.free_info) < 0) + if(H5T__vlen_reclaim_recurse(elem, dt, vl_alloc_info.free_func, vl_alloc_info.free_info) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5T_vlen_reclaim_elmt */ +} /* H5T_vlen_reclaim_elmt() */ diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index 0131f0e..43739a6 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -6564,6 +6564,125 @@ done: /*------------------------------------------------------------------------- + * Function: H5VL_blob_put + * + * Purpose: Put a blob through the VOL + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Wednesday, August 21, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_blob_put(const H5VL_class_t *cls, void *blob, size_t size, void *ctx, void *id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(cls); + HDassert(size == 0 || blob); + HDassert(id); + + /* Check if the corresponding VOL callback exists */ + if(NULL == cls->blob_cls.put) + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob put' method") + + /* Call the corresponding VOL callback */ + if((cls->blob_cls.put)(blob, size, ctx, id) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "blob put callback failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_blob_put() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_blob_get + * + * Purpose: Get a blob through the VOL + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, August 16, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_blob_get(const H5VL_class_t *cls, const void *id, void *ctx, void *buf) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(cls); + HDassert(id); + HDassert(buf); + + /* Check if the corresponding VOL callback exists */ + if(NULL == cls->blob_cls.get) + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob get' method") + + /* Call the corresponding VOL callback */ + if((cls->blob_cls.get)(id, ctx, buf) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "blob get callback failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_blob_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_blob_specific + * + * Purpose: Specific operation on blobs through the VOL + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Saturday, August 17, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_blob_specific(const H5VL_class_t *cls, void *id, + H5VL_blob_specific_t specific_type, ...) +{ + va_list arguments; /* Argument list passed from the API call */ + hbool_t arg_started = FALSE; /* Whether the va_list has been started */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(cls); + HDassert(id); + + /* Check if the corresponding VOL callback exists */ + if(NULL == cls->blob_cls.specific) + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob specific' method") + + /* Call the corresponding VOL callback */ + HDva_start(arguments, specific_type); + arg_started = TRUE; + if((cls->blob_cls.specific)(id, specific_type, arguments) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute blob specific callback") + +done: + /* End access to the va_list, if we started it */ + if(arg_started) + HDva_end(arguments); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_blob_get() */ + + +/*------------------------------------------------------------------------- * Function: H5VL__optional * * Purpose: Optional operation specific to connectors. diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h index 98bc521..c554dab 100644 --- a/src/H5VLconnector.h +++ b/src/H5VLconnector.h @@ -169,6 +169,14 @@ typedef enum H5VL_request_specific_t { H5VL_REQUEST_WAITALL /* Wait until all requests complete */ } H5VL_request_specific_t; +/* types for 'blob' SPECIFIC callback */ +typedef enum H5VL_blob_specific_t { + H5VL_BLOB_DELETE, /* Delete a blob (by ID) */ + H5VL_BLOB_GETSIZE, /* Get size of blob */ + H5VL_BLOB_ISNULL, /* Check if a blob ID is "null" */ + H5VL_BLOB_SETNULL /* Set a blob ID to the connector's "null" blob ID value */ +} H5VL_blob_specific_t; + /* types for different ways that objects are located in an HDF5 container */ typedef enum H5VL_loc_type_t { H5VL_OBJECT_BY_SELF, @@ -201,7 +209,7 @@ struct H5VL_loc_by_ref { hid_t lapl_id; }; -/* Structure to hold parameters for object locations. +/* Structure to hold parameters for object locations. * either: BY_ADDR, BY_ID, BY_NAME, BY_IDX, BY_REF * * Note: Leave loc_by_addr as the first union member so we @@ -355,6 +363,14 @@ typedef struct H5VL_request_class_t { herr_t (*free)(void *req); } H5VL_request_class_t; +/* 'blob' routines */ +typedef struct H5VL_blob_class_t { + herr_t (*put)(void *blob, size_t size, void *ctx, void *id); + herr_t (*get)(const void *id, void *ctx, void *blob); + herr_t (*specific)(void *id, H5VL_blob_specific_t specific_type, va_list arguments); + herr_t (*optional)(void *id, va_list arguments); +} H5VL_blob_class_t; + /* * VOL connector identifiers. Values 0 through 255 are for connectors defined * by the HDF5 library. Values 256 through 511 are available for testing new @@ -386,8 +402,9 @@ typedef struct H5VL_class_t { H5VL_link_class_t link_cls; /* Link (H5L*) class callbacks */ H5VL_object_class_t object_cls; /* Object (H5O*) class callbacks */ - /* Services */ + /* Infrastructure / Services */ H5VL_request_class_t request_cls; /* Asynchronous request class callbacks */ + H5VL_blob_class_t blob_cls; /* 'blob' callbacks */ /* Catch-all */ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); /* Optional callback */ @@ -398,6 +415,7 @@ typedef struct H5VL_class_t { /* Public Variables */ /********************/ + /*********************/ /* Public Prototypes */ /*********************/ diff --git a/src/H5VLconnector_passthru.h b/src/H5VLconnector_passthru.h index 9a2bd52..65c9117 100644 --- a/src/H5VLconnector_passthru.h +++ b/src/H5VLconnector_passthru.h @@ -13,7 +13,7 @@ /* * This file contains public declarations for authoring VOL connectors * which act as "passthrough" connectors that forward their API calls to - * an underlying connector. + * an underlying connector. * * An example of this might be a logging connector, which creates log messages * and then passes the call on to an underlying VOL connector. @@ -158,6 +158,10 @@ H5_DLL herr_t H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_s H5_DLL herr_t H5VLrequest_optional(void *req, hid_t connector_id, va_list arguments); H5_DLL herr_t H5VLrequest_free(void *req, hid_t connector_id); +/* Public wrappers for generic 'optional' callback */ +H5_DLL herr_t H5VLoptional(void *obj, hid_t connector_id, hid_t dxpl_id, + void **req, va_list arguments); + #ifdef __cplusplus } #endif diff --git a/src/H5VLint.c b/src/H5VLint.c index f9262f4..09acb2a 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -543,6 +543,7 @@ static H5VL_object_t * H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t wrap_obj) { H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */ + hbool_t conn_rc_incr = FALSE; /* Whether the VOL connector refcount has been incremented */ H5VL_object_t *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC @@ -569,6 +570,7 @@ H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t /* Bump the reference count on the VOL connector */ H5VL__conn_inc_rc(vol_connector); + conn_rc_incr = TRUE; /* If this is a datatype, we have to hide the VOL object under the H5T_t pointer */ if(H5I_DATATYPE == type) { @@ -579,6 +581,12 @@ H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t ret_value = (H5VL_object_t *)new_vol_obj; done: + /* Cleanup on error */ + if(NULL == ret_value) { + if(conn_rc_incr && H5VL__conn_dec_rc(vol_connector) < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTDEC, NULL, "unable to decrement ref count on VOL connector") + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL__new_vol_obj() */ @@ -759,16 +767,17 @@ done: * get the connector information instead of it being passed in. * * Return: Success: A valid HDF5 ID - * Failure: H5I_INVALID_HID + * Failure: H5I_INVALID_HID * *------------------------------------------------------------------------- */ hid_t H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id, hbool_t app_ref) { - H5VL_class_t *cls = NULL; - H5VL_t *connector = NULL; /* VOL connector struct */ - hid_t ret_value = H5I_INVALID_HID; + H5VL_class_t *cls = NULL; /* VOL connector class */ + H5VL_t *connector = NULL; /* VOL connector struct */ + hbool_t conn_id_incr = FALSE; /* Whether the VOL connector ID has been incremented */ + hid_t ret_value = H5I_INVALID_HID;/* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -783,12 +792,24 @@ H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id, hbool connector->id = connector_id; if(H5I_inc_ref(connector->id, FALSE) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector") + conn_id_incr = TRUE; /* Get an ID for the VOL object */ if((ret_value = H5VL_register(type, obj, connector, app_ref)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle") done: + /* Clean up on error */ + if(ret_value < 0) { + /* Decrement VOL connector ID ref count on error */ + if(conn_id_incr && H5I_dec_ref(connector_id) < 0) + HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement ref count on VOL connector") + + /* Free VOL connector struct */ + if(NULL != connector) + connector = H5FL_FREE(H5VL_t, connector); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_register_using_vol_id() */ diff --git a/src/H5VLnative.c b/src/H5VLnative.c index 7848c5d..c705aad 100644 --- a/src/H5VLnative.c +++ b/src/H5VLnative.c @@ -11,8 +11,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Purpose: The native VOL connector where access is to a single HDF5 file - * using HDF5 VFDs. + * Purpose: The native VOL connector where access is to a single HDF5 file + * using HDF5 VFDs. */ #include "H5private.h" /* Generic Functions */ @@ -120,6 +120,12 @@ static H5VL_class_t H5VL_native_cls_g = { NULL, /* optional */ NULL /* free */ }, + { /* blob_cls */ + H5VL__native_blob_put, /* put */ + H5VL__native_blob_get, /* get */ + H5VL__native_blob_specific, /* specific */ + H5VL__native_blob_optional /* optional */ + }, NULL /* optional */ }; diff --git a/src/H5VLnative.h b/src/H5VLnative.h index a8d5720..ba45848 100644 --- a/src/H5VLnative.h +++ b/src/H5VLnative.h @@ -17,6 +17,9 @@ #ifndef _H5VLnative_H #define _H5VLnative_H +/* Private headers needed by this file */ +#include "H5VLprivate.h" /* Virtual Object Layer */ + /* Identifier for the native VOL connector */ #define H5VL_NATIVE (H5VL_native_register()) diff --git a/src/H5VLnative_blob.c b/src/H5VLnative_blob.c new file mode 100644 index 0000000..6f2fbe6 --- /dev/null +++ b/src/H5VLnative_blob.c @@ -0,0 +1,260 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Blob callbacks for the native VOL connector + */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5HGprivate.h" /* Global Heaps */ +#include "H5VLnative_private.h" /* Native VOL connector */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5VL__native_blob_put + * + * Purpose: Handles the blob 'put' callback + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, August 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__native_blob_put(void *blob, size_t size, void *_ctx, void *_id) +{ + uint8_t *id = (uint8_t *)_id; /* Pointer to blob ID */ + H5F_t *f = (H5F_t *)_ctx; /* Retrieve file pointer from context */ + H5HG_t hobjid; /* New VL sequence's heap ID */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check parameters */ + HDassert(id); + HDassert(size == 0 || blob); + HDassert(f); + + /* Write the VL information to disk (allocates space also) */ + if(H5HG_insert(f, size, blob, &hobjid) < 0) + HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "unable to write blob information") + + /* Encode the heap information */ + H5F_addr_encode(f, &id, hobjid.addr); + UINT32ENCODE(id, hobjid.idx); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__native_blob_put() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__native_blob_get + * + * Purpose: Handles the blob 'get' callback + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, August 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__native_blob_get(const void *_id, void *_ctx, void *buf) +{ + const uint8_t *id = (const uint8_t *)_id; /* Pointer to the disk blob ID */ + H5F_t *f = (H5F_t *)_ctx; /* Retrieve file pointer from context */ + H5HG_t hobjid; /* Global heap ID for sequence */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(id); + HDassert(f); + HDassert(buf); + + /* Get the heap information */ + H5F_addr_decode(f, &id, &hobjid.addr); + UINT32DECODE(id, hobjid.idx); + + /* Check if this sequence actually has any data */ + if(hobjid.addr > 0) + /* Read the VL information from disk */ + if(NULL == H5HG_read(f, &hobjid, buf, NULL)) + HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "unable to read VL information") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__native_blob_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__native_blob_specific + * + * Purpose: Handles the blob 'specific' callback + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, August 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__native_blob_specific(void *_id, H5VL_blob_specific_t specific_type, + va_list arguments) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + switch(specific_type) { + case H5VL_BLOB_GETSIZE: + { + const uint8_t *id = (const uint8_t *)_id; /* Pointer to the blob ID */ + H5F_t *f = HDva_arg(arguments, H5F_t *); + size_t *size = HDva_arg(arguments, size_t *); + H5HG_t hobjid; /* blob's heap ID */ + + /* Get heap information */ + H5F_addr_decode(f, &id, &(hobjid.addr)); + UINT32DECODE(id, hobjid.idx); + + /* Free heap object */ + if(hobjid.addr > 0) { + if(H5HG_get_obj_size(f, &hobjid, size) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTREMOVE, FAIL, "unable to remove heap object") + } /* end if */ + else + *size = 0; /* Return '0' size for 'nil' blob ID */ + + break; + } + + case H5VL_BLOB_ISNULL: + { + const uint8_t *id = (const uint8_t *)_id; /* Pointer to the blob ID */ + H5F_t *f = HDva_arg(arguments, H5F_t *); + hbool_t *isnull = HDva_arg(arguments, hbool_t *); + haddr_t addr; /* Sequence's heap address */ + + /* Get the heap address */ + H5F_addr_decode(f, &id, &addr); + + /* Check if heap address is 'nil' */ + *isnull = (addr == 0 ? TRUE : FALSE); + + break; + } + + case H5VL_BLOB_SETNULL: + { + uint8_t *id = (uint8_t *)_id; /* Pointer to the blob ID */ + H5F_t *f = HDva_arg(arguments, H5F_t *); + + /* Encode the "nil" heap pointer information */ + H5F_addr_encode(f, &id, (haddr_t)0); + UINT32ENCODE(id, 0); + + break; + } + + case H5VL_BLOB_DELETE: + { + const uint8_t *id = (const uint8_t *)_id; /* Pointer to the blob ID */ + H5F_t *f = HDva_arg(arguments, H5F_t *); + H5HG_t hobjid; /* VL sequence's heap ID */ + + /* Get heap information */ + H5F_addr_decode(f, &id, &hobjid.addr); + UINT32DECODE(id, hobjid.idx); + + /* Free heap object */ + if(hobjid.addr > 0) + if(H5HG_remove(f, &hobjid) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTREMOVE, FAIL, "unable to remove heap object") + + break; + } + + default: + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__native_blob_specific() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__native_blob_optional + * + * Purpose: Handles the blob 'optional' callback + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, August 15, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__native_blob_optional(void *id, va_list arguments) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__native_blob_optional() */ + diff --git a/src/H5VLnative_private.h b/src/H5VLnative_private.h index 714b73c..df3865b 100644 --- a/src/H5VLnative_private.h +++ b/src/H5VLnative_private.h @@ -17,13 +17,34 @@ #ifndef _H5VLnative_private_H #define _H5VLnative_private_H +/* Private headers needed by this file */ #include "H5VLnative.h" /* Native VOL connector */ + +/**************************/ +/* Library Private Macros */ +/**************************/ + + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/******************************/ +/* Library Private Prototypes */ +/******************************/ + #ifdef __cplusplus extern "C" { #endif -/* Atrribute callbacks */ +/* Attribute callbacks */ H5_DLL void *H5VL__native_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); void *H5VL__native_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t aapl_id, hid_t dxpl_id, void **req); H5_DLL herr_t H5VL__native_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req); @@ -80,6 +101,12 @@ H5_DLL herr_t H5VL__native_datatype_get(void *dt, H5VL_datatype_get_t get_type, H5_DLL herr_t H5VL__native_datatype_specific(void *dt, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); H5_DLL herr_t H5VL__native_datatype_close(void *dt, hid_t dxpl_id, void **req); +/* Blob callbacks */ +H5_DLL herr_t H5VL__native_blob_put(void *blob, size_t size, void *ctx, void *id); +H5_DLL herr_t H5VL__native_blob_get(const void *id, void *ctx, void *buf); +H5_DLL herr_t H5VL__native_blob_specific(void *id, H5VL_blob_specific_t specific_type, va_list arguments); +H5_DLL herr_t H5VL__native_blob_optional(void *id, va_list arguments); + #ifdef __cplusplus } #endif diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index 24070fa..48ef510 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -196,14 +196,14 @@ static const H5VL_class_t H5VL_pass_through_g = { H5VL_pass_through_info_cmp, /* compare */ H5VL_pass_through_info_free, /* free */ H5VL_pass_through_info_to_str, /* to_str */ - H5VL_pass_through_str_to_info, /* from_str */ + H5VL_pass_through_str_to_info /* from_str */ }, { /* wrap_cls */ H5VL_pass_through_get_object, /* get_object */ H5VL_pass_through_get_wrap_ctx, /* get_wrap_ctx */ H5VL_pass_through_wrap_object, /* wrap_object */ H5VL_pass_through_unwrap_object, /* unwrap_object */ - H5VL_pass_through_free_wrap_ctx, /* free_wrap_ctx */ + H5VL_pass_through_free_wrap_ctx /* free_wrap_ctx */ }, { /* attribute_cls */ H5VL_pass_through_attr_create, /* create */ @@ -255,14 +255,14 @@ static const H5VL_class_t H5VL_pass_through_g = { H5VL_pass_through_link_move, /* move */ H5VL_pass_through_link_get, /* get */ H5VL_pass_through_link_specific, /* specific */ - H5VL_pass_through_link_optional, /* optional */ + H5VL_pass_through_link_optional /* optional */ }, { /* object_cls */ H5VL_pass_through_object_open, /* open */ H5VL_pass_through_object_copy, /* copy */ H5VL_pass_through_object_get, /* get */ H5VL_pass_through_object_specific, /* specific */ - H5VL_pass_through_object_optional, /* optional */ + H5VL_pass_through_object_optional /* optional */ }, { /* request_cls */ H5VL_pass_through_request_wait, /* wait */ @@ -272,6 +272,12 @@ static const H5VL_class_t H5VL_pass_through_g = { H5VL_pass_through_request_optional, /* optional */ H5VL_pass_through_request_free /* free */ }, + { /* blob_cls */ + NULL, /* put */ + NULL, /* get */ + NULL, /* specific */ + NULL /* optional */ + }, NULL /* optional */ }; diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h index 1752b0c..4aeabfa 100644 --- a/src/H5VLprivate.h +++ b/src/H5VLprivate.h @@ -193,6 +193,14 @@ H5_DLL herr_t H5VL_request_specific(const H5VL_object_t *vol_obj, H5VL_request_s H5_DLL herr_t H5VL_request_optional(const H5VL_object_t *vol_obj, ...); H5_DLL herr_t H5VL_request_free(const H5VL_object_t *vol_obj); +/* Blob functions */ +H5_DLL herr_t H5VL_blob_put(const H5VL_class_t *cls, void *blob, size_t size, + void *ctx, void *id); +H5_DLL herr_t H5VL_blob_get(const H5VL_class_t *cls, const void *id, void *ctx, + void *blob); +H5_DLL herr_t H5VL_blob_specific(const H5VL_class_t *cls, void *id, + H5VL_blob_specific_t specific_type, ...); + /* Generic functions */ H5_DLL herr_t H5VL_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id,void **req, ...); diff --git a/src/Makefile.am b/src/Makefile.am index ccee69b..24dfe74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -116,8 +116,9 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Torder.c \ H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c \ H5VL.c H5VLcallback.c H5VLint.c H5VLnative.c \ - H5VLnative_attr.c H5VLnative_dataset.c H5VLnative_datatype.c \ - H5VLnative_file.c H5VLnative_group.c H5VLnative_link.c H5VLnative_object.c \ + H5VLnative_attr.c H5VLnative_blob.c H5VLnative_dataset.c \ + H5VLnative_datatype.c H5VLnative_file.c H5VLnative_group.c \ + H5VLnative_link.c H5VLnative_object.c \ H5VLpassthru.c \ H5VM.c H5WB.c H5Z.c \ H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \ -- cgit v0.12