From 6ce8e4ba64133f8175fd6ec4fe039793a16751ed Mon Sep 17 00:00:00 2001 From: Jerome Soumagne Date: Thu, 24 Sep 2015 18:52:08 -0500 Subject: Add H5R_REGION reference type Add type/conversion routines to write/read H5R_REGION type H5Rcreate on H5R_REGION type no longer stores variable length type in global heap. The type is only stored in the heap if it is written to disk. --- src/CMakeLists.txt | 1 + src/H5R.c | 98 ++++++++++++-- src/H5Rpublic.h | 9 ++ src/H5T.c | 39 +++++- src/H5Tconv.c | 129 ++++++++++++++++++ src/H5Tnative.c | 18 ++- src/H5Tpkg.h | 23 +++- src/H5Tpublic.h | 2 + src/H5Tref.c | 374 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5detect.c | 4 +- src/Makefile.am | 1 + 11 files changed, 675 insertions(+), 23 deletions(-) create mode 100644 src/H5Tref.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 478680a..388ff28 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -588,6 +588,7 @@ set (H5T_SRCS ${HDF5_SRC_DIR}/H5Torder.c ${HDF5_SRC_DIR}/H5Tpad.c ${HDF5_SRC_DIR}/H5Tprecis.c + ${HDF5_SRC_DIR}/H5Tref.c ${HDF5_SRC_DIR}/H5Tstrpad.c ${HDF5_SRC_DIR}/H5Tvisit.c ${HDF5_SRC_DIR}/H5Tvlen.c diff --git a/src/H5R.c b/src/H5R.c index b8339a4..fbed9f1 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -51,7 +51,7 @@ /* Local Prototypes */ /********************/ -static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref); +static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref); static ssize_t H5R_get_name(H5F_t *file, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_type, const void *_ref, char *name, size_t size); @@ -360,6 +360,56 @@ H5R_create(void *_ref, H5R_type_t ref_type, ...) break; } + case H5R_REGION: + { + H5G_loc_t *loc; + const char *name; + hid_t dxpl_id; + hreg_ref_t *ref = (hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hssize_t buf_size; /* Size of buffer needed to serialize selection */ + uint8_t *p; /* Pointer to OID to store */ + H5S_t *space; + + /* Get arguments */ + loc = va_arg(ap, H5G_loc_t *); + name = va_arg(ap, const char *); + dxpl_id = va_arg(ap, hid_t); + space = va_arg(ap, H5S_t *); + + HDassert(ref); + HDassert(loc); + HDassert(name); + HDassert(space); + + /* Find the object */ + if(H5G_loc_find(loc, name, &obj_loc, H5P_DEFAULT, dxpl_id) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found") + obj_found = TRUE; + + /* Get the amount of space required to serialize the selection */ + if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection") + + /* Increase buffer size to allow for the dataset OID */ + buf_size += (hssize_t)sizeof(haddr_t); + + /* Allocate the space to store the serialized information */ + H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t); + + if(!ref->buf || ref->buf_size < (size_t) buf_size) { + ref->buf_size = (size_t)buf_size; + } else { + /* Serialize information for dataset OID into buffer */ + p = (uint8_t *)ref->buf; + H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr); + + /* Serialize the selection into buffer */ + if(H5S_SELECT_SERIALIZE(space, &p) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection") + } + } + break; + case H5R_ATTR: { H5G_loc_t *loc; @@ -531,6 +581,7 @@ H5Rcreate(void *ref, H5R_type_t ref_type, ...) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to create reference") } break; + case H5R_REGION: case H5R_DATASET_REGION: { hid_t loc_id; @@ -715,6 +766,17 @@ H5R_dereference(H5F_t *file, hid_t oapl_id, hid_t dxpl_id, H5R_type_t ref_type, } /* end case */ break; + case H5R_REGION: + { + const hreg_ref_t *ref = (const hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + const uint8_t *p; /* Pointer to OID to store */ + + /* Get the object oid for the dataset */ + p = (const uint8_t *)ref->buf; + H5F_addr_decode(oloc.file, &p, &(oloc.addr)); + } /* end case */ + break; + case H5R_BADTYPE: case H5R_MAXTYPE: default: @@ -881,9 +943,10 @@ done: PURPOSE Retrieves a dataspace with the region pointed to selected. USAGE - H5S_t *H5R_get_region(file, dxpl_id, ref) + H5S_t *H5R_get_region(file, dxpl_id, ref_type, ref) H5F_t *file; IN: File the object being dereferenced is within hid_t dxpl_id; IN: Property list ID + H5R_type_t ref_type; IN: Type of reference to get region of void *ref; IN: Reference to open. RETURNS @@ -898,7 +961,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5S_t * -H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref) +H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref) { H5O_loc_t oloc; /* Object location */ const uint8_t *p; /* Pointer to OID to store */ @@ -915,17 +978,26 @@ H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref) H5O_loc_reset(&oloc); oloc.file = file; - /* Get the heap ID for the dataset region */ - p = (const uint8_t *)_ref; - H5F_addr_decode(oloc.file, &p, &(hobjid.addr)); - UINT32DECODE(p, hobjid.idx); + if (ref_type == H5R_DATASET_REGION) { + /* Get the heap ID for the dataset region */ + p = (const uint8_t *)_ref; + H5F_addr_decode(oloc.file, &p, &(hobjid.addr)); + UINT32DECODE(p, hobjid.idx); + + /* Get the dataset region from the heap (allocate inside routine) */ + if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL) + HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information") - /* Get the dataset region from the heap (allocate inside routine) */ - if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL) - HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information") + /* Point to heap buffer now */ + p = buf; + } else { + const hreg_ref_t *ref = (const hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + + /* Point to reference buffer now */ + p = (const uint8_t *)ref->buf; + } /* Get the object oid for the dataset */ - p = buf; H5F_addr_decode(oloc.file, &p, &(oloc.addr)); /* Open and copy the dataset's dataspace */ @@ -980,13 +1052,13 @@ H5Rget_region(hid_t id, H5R_type_t ref_type, const void *ref) /* Check args */ if(H5G_loc(id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if(ref_type != H5R_DATASET_REGION) + if(ref_type != H5R_DATASET_REGION && ref_type != H5R_REGION) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type") if(ref == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer") /* Get the dataspace with the correct region selected */ - if((space = H5R_get_region(loc.oloc->file, H5AC_ind_dxpl_id, ref)) == NULL) + if((space = H5R_get_region(loc.oloc->file, H5AC_ind_dxpl_id, ref_type, ref)) == NULL) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create dataspace") /* Atomize */ diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h index 303059e..2ee47cf 100644 --- a/src/H5Rpublic.h +++ b/src/H5Rpublic.h @@ -31,6 +31,7 @@ typedef enum { H5R_BADTYPE = (-1), /*invalid Reference Type */ H5R_OBJECT, /*Object reference */ H5R_DATASET_REGION, /*Dataset Region Reference */ + H5R_REGION, /*Revised Dataset Region Reference */ H5R_ATTR, /*Attribute Reference */ H5R_MAXTYPE /*highest type (Invalid as true type) */ } H5R_type_t; @@ -52,6 +53,14 @@ typedef haddr_t hobj_ref_t; /* Needs to be large enough to store largest haddr_t typedef unsigned char hdset_reg_ref_t[H5R_DSET_REG_REF_BUF_SIZE];/* Buffer to store heap ID and index */ /* Needs to be large enough to store largest haddr_t in a worst case machine (ie. 8 bytes currently) plus an int */ +/* Variable length region reference struct in memory */ +typedef struct hreg_ref_t { + size_t buf_size;/* Size of serialized region reference */ + void *buf; /* Pointer to serialized region reference */ +} hreg_ref_t; + +#define H5R_REG_REF_INITIALIZER { 0, NULL } + #define H5R_ATTR_REF_BUF_SIZE (2 * (sizeof(haddr_t) + 4)) /* Attribute reference structure for user's code */ typedef unsigned char hattr_ref_t[H5R_ATTR_REF_BUF_SIZE];/* Buffer to store two heap IDs and indices */ diff --git a/src/H5T.c b/src/H5T.c index abdc5d6..54c3974 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -227,11 +227,18 @@ dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY; \ } -#define H5T_INIT_TYPE_REGREF_CORE { \ +#define H5T_INIT_TYPE_DSET_REGREF_CORE { \ H5T_INIT_TYPE_REF_COMMON \ dt->shared->u.atomic.u.r.rtype = H5R_DATASET_REGION; \ } +#define H5T_INIT_TYPE_REGREF_CORE { \ + H5T_INIT_TYPE_REF_COMMON \ + dt->shared->force_conv = TRUE; \ + dt->shared->u.atomic.u.r.rtype = H5R_REGION; \ + dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC; \ +} + #define H5T_INIT_TYPE_ATTRREF_CORE { \ H5T_INIT_TYPE_REF_COMMON \ dt->shared->u.atomic.u.r.rtype = H5R_ATTR; \ @@ -349,6 +356,7 @@ hid_t H5T_STD_B64BE_g = FAIL; hid_t H5T_STD_B64LE_g = FAIL; hid_t H5T_STD_REF_OBJ_g = FAIL; hid_t H5T_STD_REF_DSETREG_g = FAIL; +hid_t H5T_STD_REF_REG_g = FAIL; hid_t H5T_STD_REF_ATTR_g = FAIL; hid_t H5T_UNIX_D32BE_g = FAIL; @@ -440,6 +448,7 @@ size_t H5T_POINTER_COMP_ALIGN_g = 0; size_t H5T_HVL_COMP_ALIGN_g = 0; size_t H5T_HOBJREF_COMP_ALIGN_g = 0; size_t H5T_HDSETREGREF_COMP_ALIGN_g = 0; +size_t H5T_HREGREF_COMP_ALIGN_g = 0; size_t H5T_HATTRREF_COMP_ALIGN_g = 0; /* @@ -726,6 +735,7 @@ H5T__init_package(void) H5T_t *vlen=NULL; /* Datatype structure for vlen objects */ H5T_t *array=NULL; /* Datatype structure for array objects */ H5T_t *objref=NULL; /* Datatype structure for object reference objects */ + H5T_t *regref=NULL; /* Datatype structure for region reference objects */ hsize_t dim[1]={1}; /* Dimension info for array datatype */ herr_t status; unsigned copied_dtype=1; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */ @@ -982,7 +992,14 @@ H5T__init_package(void) objref = dt; /* Keep type for later */ /* Dataset Region reference (i.e. selection inside a dataset) */ - H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE) + H5T_INIT_TYPE(DSET_REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE) + + /* Dataset Region reference (i.e. selection inside a dataset) */ + H5T_INIT_TYPE(REGREF, H5T_STD_REF_REG_g, ALLOC, -, NOSET, -) + /* TODO put that in the macro */ + if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") + regref = dt; /* Keep type for later */ /* Attribute reference (i.e. object and attribute names in file) */ H5T_INIT_TYPE(ATTRREF, H5T_STD_REF_ATTR_g, ALLOC, -, SET, H5R_ATTR_REF_BUF_SIZE) @@ -1021,6 +1038,7 @@ H5T__init_package(void) status |= H5T_register(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T__conv_vlen, H5AC_ind_dxpl_id, FALSE); status |= H5T_register(H5T_PERS_SOFT, "array", array, array, H5T__conv_array, H5AC_ind_dxpl_id, FALSE); status |= H5T_register(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_order_opt, H5AC_ind_dxpl_id, FALSE); + status |= H5T_register(H5T_PERS_SOFT, "regref", regref, regref, H5T__conv_ref, H5AC_ind_dxpl_id, FALSE); /* * Native conversions should be listed last since we can use hardware to @@ -1451,6 +1469,7 @@ H5T_top_term_package(void) H5T_STD_B64LE_g = FAIL; H5T_STD_REF_OBJ_g = FAIL; H5T_STD_REF_DSETREG_g = FAIL; + H5T_STD_REF_REG_g = FAIL; H5T_STD_REF_ATTR_g = FAIL; H5T_UNIX_D32BE_g = FAIL; @@ -4335,7 +4354,12 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset) /*void */ break; - case H5R_ATTR: + case H5R_REGION: + /* Does this need more to distinguish it? -QAK 8/25/15 */ + /*void */ + break; + + case H5R_ATTR: /* Does this need more to distinguish it? -QAK 8/25/15 */ /*void */ break; @@ -5131,7 +5155,7 @@ done: htri_t H5T_set_loc(dt,f,loc) H5T_t *dt; IN/OUT: Pointer to the datatype to mark H5F_t *f; IN: Pointer to the file the datatype is in - H5T_vlen_type_t loc IN: location of type + H5T_loc_t loc IN: location of type RETURNS One of two values on success: @@ -5265,6 +5289,13 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) ret_value=TRUE; } /* end if */ } /* end if */ + if(dt->shared->u.atomic.u.r.rtype == H5R_REGION) { + /* Mark this reference */ + if((changed = H5T__ref_set_loc(dt, f, loc)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set reference location"); + if(changed > 0) + ret_value = changed; + } break; case H5T_NO_CLASS: diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 8b96d22..622d7a8 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -1025,6 +1025,9 @@ H5FL_BLK_DEFINE_STATIC(vlen_seq); /* Declare a free list to manage pieces of array data */ H5FL_BLK_DEFINE_STATIC(array_seq); +/* Declare a free list to manage pieces of reference data */ +H5FL_BLK_DEFINE_STATIC(ref_seq); + /*------------------------------------------------------------------------- * Function: H5T__conv_noop @@ -3560,6 +3563,132 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__conv_array() */ +/*------------------------------------------------------------------------- + * Function: H5T__conv_ref + * + * Purpose: Converts between region reference datatypes in memory and on disk. + * This is a soft conversion function. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, + size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dxpl_id) +{ + H5T_t *src = NULL; /* source datatype */ + H5T_t *dst = NULL; /* destination datatype */ + 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 */ + void *conv_buf = NULL; /* temporary conversion buffer */ + size_t conv_buf_size = 0; /* size of conversion buffer in bytes */ + size_t elmtno; /* element number counter */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_PACKAGE + + switch(cdata->command) { + case H5T_CONV_INIT: + /* + * First, determine if this conversion function applies to the + * conversion path SRC_ID-->DST_ID. If not, return failure; + * otherwise initialize the `priv' field of `cdata' with + * information that remains (almost) constant for this + * conversion path. + */ + if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype") + if(H5T_REFERENCE != src->shared->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype") + if(H5T_REFERENCE != dst->shared->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype") + + /* Reference types don't need a background buffer */ + cdata->need_bkg = H5T_BKG_NO; + break; + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + { + /* + * Conversion. + */ + if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + + /* Initialize source & destination strides */ + if(buf_stride) { + HDassert(buf_stride >= src->shared->size); + HDassert(buf_stride >= dst->shared->size); + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + s_stride = d_stride = (ssize_t)buf_stride; + } /* end if */ + else { + H5_CHECK_OVERFLOW(src->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst->shared->size, size_t, ssize_t); + s_stride = (ssize_t)src->shared->size; + d_stride = (ssize_t)dst->shared->size; + } /* end else */ + if(bkg) { + if(bkg_stride) + b_stride = (ssize_t)bkg_stride; + else + b_stride = d_stride; + } /* end if */ + else + b_stride = 0; + + /* Single forward pass over all data */ + s = d = (uint8_t *)buf; + b = (uint8_t *)bkg; + + for(elmtno = 0; elmtno < nelmts; elmtno++) { + size_t buf_size; + + /* Get size of references */ + if(0 == (buf_size = (*(src->shared->u.atomic.u.r.getsize))(s))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length") + + /* Check if conversion buffer is large enough, resize if necessary. */ + conv_buf_size = buf_size; + if(NULL == (conv_buf = H5FL_BLK_REALLOC(ref_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); + + /* Read reference */ + if((*(src->shared->u.atomic.u.r.read))(src->shared->u.atomic.u.r.f, dxpl_id, s, conv_buf, buf_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read reference data") + + /* Write reference to destination location */ + if((*(dst->shared->u.atomic.u.r.write))(dst->shared->u.atomic.u.r.f, dxpl_id, d, conv_buf, b, buf_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write reference data") + + /* Advance pointers */ + s += s_stride; + d += d_stride; + b += b_stride; + } /* end for */ + } /* end case */ + break; + + default: /* Some other command we don't know about yet.*/ + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command") + } /* end switch */ + +done: + /* Release the conversion buffer (always allocated, except on errors) */ + if(conv_buf) + conv_buf = H5FL_BLK_FREE(ref_seq, conv_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_ref() */ + /*------------------------------------------------------------------------- * Function: H5T__conv_i_i diff --git a/src/H5Tnative.c b/src/H5Tnative.c index 7860eca..7f536cf 100644 --- a/src/H5Tnative.c +++ b/src/H5Tnative.c @@ -234,7 +234,7 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig ref_size = sizeof(hobj_ref_t); } /* end if */ else { - /* Decide if the datatype is a dataset region or attribute reference. */ + /* Decide if the datatype is a dataset region reference. */ if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_DSETREG_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype") not_equal = H5T_cmp(ret_value, dt, FALSE); @@ -245,8 +245,20 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig ref_size = sizeof(hdset_reg_ref_t); } /* end if */ else { - align = H5T_HATTRREF_COMP_ALIGN_g; - ref_size = sizeof(hattr_ref_t); + /* Decide if the datatype is a dataset region reference. */ + if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_REG_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype") + not_equal = H5T_cmp(ret_value, dt, FALSE); + + /* Update size, offset and compound alignment for parent. */ + if(!not_equal) { + align = H5T_HREGREF_COMP_ALIGN_g; + ref_size = sizeof(hreg_ref_t); + } /* end if */ + else { + align = H5T_HATTRREF_COMP_ALIGN_g; + ref_size = sizeof(hattr_ref_t); + } /* end else */ } /* end else */ } /* end else */ diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index eb2f1e2..fdc3dd7 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -164,6 +164,13 @@ struct H5T_path_t { H5T_cdata_t cdata; /*data for this function */ }; +/* Reference function pointers */ +typedef size_t (*H5T_ref_getsizefunc_t)(const void *_ref); +typedef herr_t (*H5T_ref_readfunc_t)(H5F_t *f, hid_t dxpl_id, void *_ref, + void *buf, size_t buf_size); +typedef herr_t (*H5T_ref_writefunc_t)(H5F_t *f, hid_t dxpl_id, void *_ref, + void *buf, void *_bg, size_t buf_size); + typedef struct H5T_atomic_t { H5T_order_t order; /*byte order */ size_t prec; /*precision in bits */ @@ -192,8 +199,12 @@ typedef struct H5T_atomic_t { } s; /*string types */ struct { - H5R_type_t rtype; /*type of reference stored */ - H5T_loc_t loc; /* Location of data in buffer */ + H5R_type_t rtype; /*type of reference stored */ + H5T_loc_t loc; /*location of data in buffer */ + H5F_t *f; /*file ID (if data is on disk) */ + H5T_ref_getsizefunc_t getsize; /*function to get reference size (bytes) */ + H5T_ref_readfunc_t read; /*function to read reference into buffer */ + H5T_ref_writefunc_t write; /*function to write reference from buffer */ } r; /*reference types */ } u; } H5T_atomic_t; @@ -356,6 +367,7 @@ H5_DLLVAR size_t H5T_POINTER_COMP_ALIGN_g; H5_DLLVAR size_t H5T_HVL_COMP_ALIGN_g; H5_DLLVAR size_t H5T_HOBJREF_COMP_ALIGN_g; H5_DLLVAR size_t H5T_HDSETREGREF_COMP_ALIGN_g; +H5_DLLVAR size_t H5T_HREGREF_COMP_ALIGN_g; H5_DLLVAR size_t H5T_HATTRREF_COMP_ALIGN_g; /* @@ -474,6 +486,10 @@ H5_DLL herr_t H5T__conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dset_xfer_plist); +H5_DLL herr_t H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, + size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg, + hid_t dset_xfer_plist); H5_DLL herr_t H5T__conv_i_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, void *bkg, @@ -1302,6 +1318,9 @@ H5_DLL H5T_t *H5T__array_create(H5T_t *base, unsigned ndims, const hsize_t dim[/ H5_DLL int H5T__get_array_ndims(const H5T_t *dt); H5_DLL int H5T__get_array_dims(const H5T_t *dt, hsize_t dims[]); +/* Reference functions */ +H5_DLL htri_t H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc); + /* Compound functions */ H5_DLL herr_t H5T__insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 0fe7fcf..f27025c 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -266,6 +266,7 @@ H5_DLLVAR hid_t H5T_IEEE_F64LE_g; #define H5T_STD_B64LE (H5OPEN H5T_STD_B64LE_g) #define H5T_STD_REF_OBJ (H5OPEN H5T_STD_REF_OBJ_g) #define H5T_STD_REF_DSETREG (H5OPEN H5T_STD_REF_DSETREG_g) +#define H5T_STD_REF_REG (H5OPEN H5T_STD_REF_REG_g) #define H5T_STD_REF_ATTR (H5OPEN H5T_STD_REF_ATTR_g) H5_DLLVAR hid_t H5T_STD_I8BE_g; H5_DLLVAR hid_t H5T_STD_I8LE_g; @@ -293,6 +294,7 @@ H5_DLLVAR hid_t H5T_STD_B64BE_g; H5_DLLVAR hid_t H5T_STD_B64LE_g; H5_DLLVAR hid_t H5T_STD_REF_OBJ_g; H5_DLLVAR hid_t H5T_STD_REF_DSETREG_g; +H5_DLLVAR hid_t H5T_STD_REF_REG_g; H5_DLLVAR hid_t H5T_STD_REF_ATTR_g; /* diff --git a/src/H5Tref.c b/src/H5Tref.c new file mode 100644 index 0000000..def5cb1 --- /dev/null +++ b/src/H5Tref.c @@ -0,0 +1,374 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for reference + * datatypes in the H5T interface. + */ + +#include "H5Tmodule.h" /* This source code file is part of the H5T module */ + + +#include "H5private.h" /* Generic Functions */ +#include "H5Dprivate.h" /* Dataset functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HGprivate.h" /* Global Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Tpkg.h" /* Datatypes */ + +/* Local functions */ +static size_t H5T__ref_reg_mem_getsize(const void *_ref); +static herr_t H5T__ref_reg_mem_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, size_t buf_size); +static herr_t H5T__ref_reg_mem_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, void *_bg, size_t buf_size); + +static size_t H5T__ref_disk_getsize(const void *_ref); +static herr_t H5T__ref_disk_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, size_t buf_size); +static herr_t H5T__ref_disk_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, void *_bg, size_t buf_size); + +/* Local variables */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_set_loc + * + * Purpose: Sets the location of a reference datatype to be either on disk + * or in memory + * + * Return: + * One of two values on success: + * TRUE - If the location of any reference types changed + * FALSE - If the location of any reference types is the same + * Negative value is returned on failure + * + *------------------------------------------------------------------------- + */ +htri_t +H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) +{ + htri_t ret_value = FALSE; /* Indicate success, but no location change */ + + FUNC_ENTER_PACKAGE + + /* check parameters */ + HDassert(dt); + HDassert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC); + + /* Only change the location if it's different */ + if(loc != dt->shared->u.atomic.u.r.loc || f != dt->shared->u.atomic.u.r.f) { + switch(loc) { + case H5T_LOC_MEMORY: /* Memory based reference datatype */ + HDassert(NULL == f); + + /* Mark this type as being stored in memory */ + dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY; + + if(dt->shared->u.atomic.u.r.rtype == H5R_REGION) { + /* size in memory, disk size is different */ + dt->shared->size = sizeof(hreg_ref_t); + + /* Set up the function pointers to access the region + * reference in memory */ + dt->shared->u.atomic.u.r.getsize = H5T__ref_reg_mem_getsize; + dt->shared->u.atomic.u.r.read = H5T__ref_reg_mem_read; + dt->shared->u.atomic.u.r.write = H5T__ref_reg_mem_write; + } else { + HDassert(0 && "Invalid reference type"); + } + + /* Reset file ID (since this reference is in memory) */ + dt->shared->u.atomic.u.r.f = NULL; + break; + + case H5T_LOC_DISK: /* Disk based reference datatype */ + HDassert(f); + + /* Mark this type as being stored on disk */ + dt->shared->u.atomic.u.r.loc = H5T_LOC_DISK; + + /* + * 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 + */ + dt->shared->size = (size_t) (2 * H5_SIZEOF_UINT32_T) + H5F_SIZEOF_ADDR(f); + + /* + * Set up the function pointers to access the information on + * disk. Region and attribute references are stored identically + * on disk, so use the same functions + */ + dt->shared->u.atomic.u.r.getsize = H5T__ref_disk_getsize; + dt->shared->u.atomic.u.r.read = H5T__ref_disk_read; + dt->shared->u.atomic.u.r.write = H5T__ref_disk_write; + + /* Set file ID (since this reference is on disk) */ + dt->shared->u.atomic.u.r.f = f; + break; + + case H5T_LOC_BADLOC: + case H5T_LOC_MAXLOC: + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid reference datatype location") + } /* end switch */ + + /* Indicate that the location changed */ + ret_value = TRUE; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__ref_set_loc() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_reg_mem_getsize + * + * Purpose: Retrieves the size of a memory based region reference. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static size_t +H5T__ref_reg_mem_getsize(const void *_ref) +{ +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + const hreg_ref_t *ref = (const hreg_ref_t *)_ref; +#else + hreg_ref_t ref; +#endif + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* check parameters, return result */ +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + HDassert(ref); + + FUNC_LEAVE_NOAPI(ref->buf_size) +#else + HDassert(_ref); + HDmemcpy(&ref, _ref, sizeof(hreg_ref_t)); + + FUNC_LEAVE_NOAPI(ref.buf_size) +#endif +} /* end H5T__ref_reg_mem_getsize() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_reg_mem_read + * + * Purpose: "Reads" the memory based region reference into a buffer + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__ref_reg_mem_read(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, + void *_ref, void *buf, size_t buf_size) +{ +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + const hreg_ref_t *ref = (const hreg_ref_t *)_ref; +#else + hreg_ref_t ref; +#endif + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* check parameters, copy data */ + HDassert(buf); +#ifdef H5_NO_ALIGNMENT_RESTRICTIONS + HDassert(ref && ref->buf); + + HDmemcpy(buf, ref->buf, buf_size); +#else + HDassert(_ref); + HDmemcpy(&ref, _ref, sizeof(hreg_ref_t)); + HDassert(ref.buf); + + HDmemcpy(buf, ref.buf, buf_size); +#endif + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T__ref_reg_mem_read() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_reg_mem_write + * + * Purpose: "Writes" the memory region reference from a buffer + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__ref_reg_mem_write(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, + void *_ref, void *buf, void H5_ATTR_UNUSED *_bg, size_t buf_size) +{ + hreg_ref_t ref; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check parameters */ + HDassert(_ref); + HDassert(buf); + + if (buf_size != 0) { + if (NULL == (ref.buf = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for reference data") + + /* Copy the data into the newly allocated buffer */ + HDmemcpy(ref.buf, buf, buf_size); + } /* end if */ + else + ref.buf = NULL; + + /* Set the size */ + ref.buf_size = buf_size; + + /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ + HDmemcpy(_ref, &ref, sizeof(hreg_ref_t)); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__ref_reg_mem_write() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_disk_getsize + * + * Purpose: Retrieves the length of a disk based reference element. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static size_t +H5T__ref_disk_getsize(const void *_ref) +{ + const uint8_t *ref = (const uint8_t *)_ref; /* Pointer to the disk reference information */ + size_t buf_size = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* check parameters */ + HDassert(ref); + + UINT32DECODE(ref, buf_size); + + FUNC_LEAVE_NOAPI(buf_size) +} /* end H5T__ref_disk_getsize() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_disk_read + * + * Purpose: Reads the disk based region element into a buffer + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__ref_disk_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *buf, + size_t H5_ATTR_UNUSED buf_size) +{ + const uint8_t *ref = (const uint8_t *)_ref; + H5HG_t hobjid; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check parameters */ + HDassert(ref); + HDassert(buf); + HDassert(f); + + /* Skip the length of the sequence */ + ref += 4; + + /* Get the heap information */ + H5F_addr_decode(f, (const uint8_t **)&ref, &(hobjid.addr)); + UINT32DECODE(ref, hobjid.idx); + + /* Check if this sequence actually has any data */ + if(hobjid.addr > 0) { + /* Read the VL information from disk */ + if(H5HG_read(f, dxpl_id, &hobjid, buf, NULL) == NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read reference information") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__ref_disk_read() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_disk_write + * + * Purpose: Writes the disk based region element from a buffer + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__ref_disk_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *buf, void *_bg, + size_t buf_size) +{ + uint8_t *ref = (uint8_t *)_ref; /* Pointer to the user's information */ + const uint8_t *bg = (const uint8_t *)_bg; /* Pointer to the old data */ + H5HG_t hobjid; /* New reference's heap ID */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check parameters */ + HDassert(ref); + HDassert(buf_size == 0 || buf); + HDassert(f); + + /* TODO not sure if we need that but oh well... */ + /* Free heap object for old data. */ + if(bg != NULL) { + H5HG_t bg_hobjid; /* "Background" reference's ID info */ + + /* Skip the length of the reference 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, dxpl_id, &bg_hobjid) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") + } /* end if */ + } /* end if */ + + /* Set the size */ + UINT32ENCODE(ref, buf_size); + + /* Write the reference information to disk (allocates space also) */ + if(H5HG_insert(f, dxpl_id, buf_size, buf, &hobjid) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write reference information") + + /* Encode the heap information */ + H5F_addr_encode(f, &ref, hobjid.addr); + UINT32ENCODE(ref, hobjid.idx); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__ref_disk_write() */ + diff --git a/src/H5detect.c b/src/H5detect.c index 454118e..ad0205b 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -1653,11 +1653,13 @@ detect_C99_floats(void) static void detect_alignments(void) { - /* Detect structure alignment for pointers, hvl_t, hobj_ref_t, hdset_reg_ref_t, hattr_ref_t */ + /* Detect structure alignment for pointers, hvl_t, hobj_ref_t, + * hdset_reg_ref_t, hattr_ref_t, hreg_ref_t */ DETECT_M(void *, POINTER, m_g[na_g]); na_g++; DETECT_M(hvl_t, HVL, m_g[na_g]); na_g++; DETECT_M(hobj_ref_t, HOBJREF, m_g[na_g]); na_g++; DETECT_M(hdset_reg_ref_t, HDSETREGREF, m_g[na_g]); na_g++; + DETECT_M(hreg_ref_t, HREGREF, m_g[na_g]); na_g++; DETECT_M(hattr_ref_t, HATTRREF, m_g[na_g]); na_g++; } diff --git a/src/Makefile.am b/src/Makefile.am index 49fca61..09047fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,6 +108,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Toh.c \ H5Topaque.c \ H5Torder.c \ + H5Tref.c \ H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c H5VM.c H5WB.c H5Z.c \ H5X.c H5Xdummy.c H5Xalacrity.c H5Xfastbit.c \ H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \ -- cgit v0.12