From f5324cdd959149816ddca13adad121c3be5bb64f Mon Sep 17 00:00:00 2001 From: Jerome Soumagne Date: Sun, 27 Sep 2015 20:15:20 -0500 Subject: Modify attribute references to use variable length ref type Clean up H5R --- src/H5D.c | 43 +++++++++++++ src/H5Dint.c | 41 +++++++++++++ src/H5Dprivate.h | 4 ++ src/H5Dpublic.h | 1 + src/H5R.c | 182 +++++++++++++++++++++++++------------------------------ src/H5Rpublic.h | 16 ++--- src/H5T.c | 27 ++++++--- src/H5Tconv.c | 4 +- src/H5Tprivate.h | 1 + src/H5Tref.c | 159 ++++++++++++++++++++++++++++++++++++++---------- 10 files changed, 331 insertions(+), 147 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index 475b828..715358a 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -738,6 +738,49 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Diterate() */ +/*------------------------------------------------------------------------- + * Function: H5Dref_reclaim + * + * Purpose: Frees the buffers allocated for storing variable-length reference + * in memory. Only frees the VL data in the selection defined in the + * dataspace. The dataset transfer property list is required to find the + * correct allocation/free methods for the VL data in the buffer. + * + * Return: Non-negative on success, negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dref_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf) +{ + H5S_t *space; /* Dataspace for iteration */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "iii*x", type_id, space_id, plist_id, buf); + + /* Check args */ + if(H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument") + if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace") + if(!(H5S_has_extent(space))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == plist_id) + plist_id = H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* Call internal routine */ + ret_value = H5D_ref_reclaim(type_id, space, plist_id, buf); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dref_reclaim() */ + /*------------------------------------------------------------------------- * Function: H5Dvlen_reclaim diff --git a/src/H5Dint.c b/src/H5Dint.c index 7d18005..f3927e2 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -2184,6 +2184,47 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__get_offset() */ +/*------------------------------------------------------------------------- + * Function: H5D_ref_reclaim + * + * Purpose: Frees the buffers allocated for storing variable-length reference + * in memory. Only frees the VL data in the selection defined in the + * dataspace. The dataset transfer property list is required to find the + * correct allocation/free methods for the VL data in the buffer. + * + * Return: Non-negative on success, negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_ref_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, void *buf) +{ + H5T_t *type; /* Datatype */ + H5S_sel_iter_op_t dset_op; /* Operator for iteration */ + herr_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(H5I_DATATYPE == H5I_get_type(type_id)); + HDassert(space); + HDassert(H5P_isa_class(plist_id, H5P_DATASET_XFER)); + HDassert(buf); + + if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype") + + /* Call H5S_select_iterate with args, etc. */ + dset_op.op_type = H5S_SEL_ITER_OP_APP; + dset_op.u.app_op.op = H5T_ref_reclaim; + dset_op.u.app_op.type_id = type_id; + + ret_value = H5S_select_iterate(buf, type, space, &dset_op, NULL); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_ref_reclaim() */ + /*------------------------------------------------------------------------- * Function: H5D_vlen_reclaim diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 983ca71..121da08 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -188,6 +188,10 @@ H5_DLL herr_t H5D_get_index_size(H5D_t *dset, hsize_t *idx_size); H5_DLL H5S_t *H5D_query(H5D_t *dset, const H5S_t *file_space, const H5Q_t *query, hid_t xapl_id, hid_t xxpl_id); +/* Functions that operate on reference data */ +H5_DLL herr_t H5D_ref_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, + void *buf); + /* Functions that operate on vlen data */ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, void *buf); diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index 8cbba89..f62e38c 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -144,6 +144,7 @@ H5_DLL herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf); H5_DLL herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, void *operator_data); +H5_DLL herr_t H5Dref_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf); H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf); H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf, diff --git a/src/H5R.c b/src/H5R.c index fbed9f1..59b1250 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -415,13 +415,10 @@ H5R_create(void *_ref, H5R_type_t ref_type, ...) H5G_loc_t *loc; const char *name; hid_t dxpl_id; - H5HG_t hobjid; /* Heap object ID */ hattr_ref_t *ref = (hattr_ref_t *)_ref; /* Get pointer to correct type of reference struct */ - size_t buf_size; /* Size of buffer needed to serialize selection */ + size_t buf_size; /* Size of buffer needed to serialize attribute */ size_t attr_name_len; /* Length of the attribute name */ uint8_t *p; /* Pointer to OID to store */ - hbool_t heapid_found; /* Flag for non-zero heap ID found */ - unsigned u; /* local index */ const char *attr_name; /* Get arguments */ @@ -440,25 +437,6 @@ H5R_create(void *_ref, H5R_type_t ref_type, ...) HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found") obj_found = TRUE; - /* Set up information for attribute */ - - /* Return any previous heap block to the free list if we are garbage collecting */ - if(H5F_GC_REF(loc->oloc->file)) { - /* Check for an existing heap ID in the reference */ - for(u = 0, heapid_found = FALSE, p = (uint8_t *)ref; u < H5R_ATTR_REF_BUF_SIZE; u++) - if(p[u] != 0) { - heapid_found = TRUE; - break; - } /* end if */ - - if(heapid_found) { -/* Return heap block to free list */ - } /* end if */ - } /* end if */ - - /* Zero the heap ID out, may leak heap space if user is re-using reference and doesn't have garbage collection on */ - HDmemset(ref, 0, H5R_ATTR_REF_BUF_SIZE); - /* Get the amount of space required to serialize the attribute name */ attr_name_len = HDstrlen(attr_name); if(attr_name_len >= H5R_MAX_ATTR_REF_NAME_LEN) @@ -468,33 +446,24 @@ H5R_create(void *_ref, H5R_type_t ref_type, ...) buf_size = attr_name_len + 2 + sizeof(haddr_t); /* Allocate the space to store the serialized information */ - if(NULL == (buf = (uint8_t *)H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTALLOC, FAIL, "memory allocation failed") - - /* Serialize information for object's OID into heap buffer */ - p = (uint8_t *)buf; - H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr); - - /* Serialize information for attribute name length into the buffer */ - UINT16ENCODE(p, attr_name_len); - - /* Copy the attribute name into the buffer */ - HDmemcpy(p, attr_name, attr_name_len); + if(!ref->buf || ref->buf_size < buf_size) { + ref->buf_size = buf_size; + } else { + /* Serialize information for object's OID into buffer */ + p = (uint8_t *)ref->buf; + H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr); - /* Sanity check */ - HDassert((size_t)((p + attr_name_len) - buf) == buf_size); + /* Serialize information for attribute name length into the buffer */ + UINT16ENCODE(p, attr_name_len); - /* Save the serialized buffer for later */ - if(H5HG_insert(loc->oloc->file, dxpl_id, buf_size, buf, &hobjid) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection") + /* Copy the attribute name into the buffer */ + HDmemcpy(p, attr_name, attr_name_len); - /* Serialize the heap ID and index for storage in the file */ - p = (uint8_t *)ref; - H5F_addr_encode(loc->oloc->file, &p, hobjid.addr); - UINT32ENCODE(p, hobjid.idx); - - break; + /* Sanity check */ + HDassert((size_t)((p + attr_name_len) - (uint8_t *)ref->buf) == buf_size); + } } + break; case H5R_BADTYPE: case H5R_MAXTYPE: @@ -726,27 +695,25 @@ H5R_dereference(H5F_t *file, hid_t oapl_id, hid_t dxpl_id, H5R_type_t ref_type, } /* end case */ break; - case H5R_ATTR: + case H5R_REGION: { - H5HG_t hobjid; /* Heap object ID */ - uint8_t *buf; /* Buffer to store serialized selection in */ - const uint8_t *p; /* Pointer to OID to store */ - size_t attr_name_len; /* Length of the attribute name */ - - /* 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); + 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 */ - if(!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer") + /* Get the object oid for the dataset */ + p = (const uint8_t *)ref->buf; + H5F_addr_decode(oloc.file, &p, &(oloc.addr)); + } /* end case */ + break; - /* Get the dataset region from the heap (allocate inside routine) */ - if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL))) - HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information") + case H5R_ATTR: + { + const hattr_ref_t *ref = (const hattr_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + const uint8_t *p; /* Pointer to OID to store */ + size_t attr_name_len; /* Length of the attribute name */ /* Get the object oid for the dataset */ - p = buf; + p = (const uint8_t *)ref->buf; H5F_addr_decode(oloc.file, &p, &(oloc.addr)); /* Get the attribute name length */ @@ -760,20 +727,6 @@ H5R_dereference(H5F_t *file, hid_t oapl_id, hid_t dxpl_id, H5R_type_t ref_type, /* Get the attribute name */ HDmemcpy(attr_name, p, attr_name_len); attr_name[attr_name_len] = '\0'; - - /* Free the buffer allocated in H5HG_read() */ - H5MM_xfree(buf); - } /* 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; @@ -875,8 +828,7 @@ H5R_dereference(H5F_t *file, hid_t oapl_id, hid_t dxpl_id, H5R_type_t ref_type, } /* end else */ done: - if(attr_name) - H5MM_xfree(attr_name); + H5MM_xfree(attr_name); FUNC_LEAVE_NOAPI(ret_value) } /* end H5R_dereference() */ @@ -1139,27 +1091,27 @@ H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, break; } /* end case */ - case H5R_ATTR: + case H5R_REGION: { - H5HG_t hobjid; /* Heap object ID */ + const hreg_ref_t *ref = (const hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ const uint8_t *p; /* Pointer to reference to decode */ - uint8_t *buf; /* Buffer to store serialized selection in */ - /* 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 object oid for the dataset */ + p = (const uint8_t *)ref->buf; + H5F_addr_decode(oloc.file, &p, &(oloc.addr)); - /* 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, FAIL, "Unable to read attribute reference information") + break; + } /* end case */ + + case H5R_ATTR: + { + const hattr_ref_t *ref = (const hattr_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + const uint8_t *p; /* Pointer to reference to decode */ /* Get the object oid for the dataset */ - p = buf; + p = (const uint8_t *)ref->buf; H5F_addr_decode(oloc.file, &p, &(oloc.addr)); - /* Free the buffer allocated in H5HG_read() */ - H5MM_xfree(buf); break; } /* end case */ @@ -1305,10 +1257,40 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty H5MM_xfree(buf); } /* 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 reference to decode */ + + /* 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_ATTR: { - /* TODO */ - } + const hattr_ref_t *ref = (const hattr_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + const uint8_t *p; /* Pointer to OID to store */ + size_t attr_name_len; /* Length of the attribute name */ + size_t copy_len; + + /* Get the object oid for the dataset */ + p = (const uint8_t *)ref->buf; + H5F_addr_decode(oloc.file, &p, &(oloc.addr)); + + /* Get the attribute name length */ + UINT16DECODE(p, attr_name_len); + HDassert(attr_name_len < H5R_MAX_ATTR_REF_NAME_LEN); + copy_len = MIN(attr_name_len, size - 1); + + /* Get the attribute name */ + HDmemcpy(name, p, copy_len); + name[copy_len] = '\0'; + ret_value = (ssize_t)copy_len; + } /* end case */ break; case H5R_BADTYPE: case H5R_MAXTYPE: @@ -1317,13 +1299,15 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)") } /* end switch */ - /* Retrieve file ID for name search */ - if((file_id = H5I_get_file_id(id, FALSE)) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID") + if (ref_type != H5R_ATTR) { + /* Retrieve file ID for name search */ + if((file_id = H5I_get_file_id(id, FALSE)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID") - /* Get name, length, etc. */ - if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name") + /* Get name, length, etc. */ + if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name") + } done: /* Close file ID used for search */ diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h index 2ee47cf..421b9c2 100644 --- a/src/H5Rpublic.h +++ b/src/H5Rpublic.h @@ -53,18 +53,20 @@ 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 { +/* Variable length reference struct in memory */ +struct href_var { size_t buf_size;/* Size of serialized region reference */ void *buf; /* Pointer to serialized region reference */ -} hreg_ref_t; +}; + +typedef struct href_var 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 */ -/* Needs to be large enough to store 2x the largest haddr_t in a worst case machine (ie. 8 bytes currently) plus an int */ +/* Attribute reference structure for user's code (variable length) */ +typedef struct href_var hattr_ref_t; + +#define H5R_ATTR_REF_INITIALIZER { 0, NULL } /* Publicly visible data structures */ diff --git a/src/H5T.c b/src/H5T.c index 54c3974..36c5745 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -239,9 +239,11 @@ 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; \ +#define H5T_INIT_TYPE_ATTRREF_CORE { \ + H5T_INIT_TYPE_REF_COMMON \ + dt->shared->force_conv = TRUE; \ + dt->shared->u.atomic.u.r.rtype = H5R_ATTR; \ + dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC; \ } /* Define the code templates for the "SIZE_TMPL" in the H5T_INIT_TYPE macro */ @@ -736,6 +738,7 @@ H5T__init_package(void) 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 */ + H5T_t *attrref=NULL; /* Datatype structure for attribute 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) */ @@ -998,11 +1001,15 @@ H5T__init_package(void) 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") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "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) + H5T_INIT_TYPE(ATTRREF, H5T_STD_REF_ATTR_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, FAIL, "invalid datatype location") + attrref = dt; /* Keep type for later */ /* * Register conversion functions beginning with the most general and @@ -1039,6 +1046,7 @@ H5T__init_package(void) 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); + status |= H5T_register(H5T_PERS_SOFT, "attrref", attrref, attrref, H5T__conv_ref, H5AC_ind_dxpl_id, FALSE); /* * Native conversions should be listed last since we can use hardware to @@ -4355,8 +4363,10 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset) break; case H5R_REGION: - /* Does this need more to distinguish it? -QAK 8/25/15 */ - /*void */ + if (dt1->shared->u.atomic.u.r.loc < dt2->shared->u.atomic.u.r.loc) + HGOTO_DONE(-1); + if (dt1->shared->u.atomic.u.r.loc > dt2->shared->u.atomic.u.r.loc) + HGOTO_DONE(1); break; case H5R_ATTR: @@ -5289,7 +5299,8 @@ 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) { + if((dt->shared->u.atomic.u.r.rtype == H5R_REGION) || + (dt->shared->u.atomic.u.r.rtype == H5R_ATTR)) { /* 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"); diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 622d7a8..534ab99 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -3566,7 +3566,7 @@ done: /*------------------------------------------------------------------------- * Function: H5T__conv_ref * - * Purpose: Converts between region reference datatypes in memory and on disk. + * Purpose: Converts between reference datatypes in memory and on disk. * This is a soft conversion function. * * Return: Non-negative on success/Negative on failure @@ -3622,6 +3622,8 @@ H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, 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") + if (src->shared->u.atomic.u.r.rtype == H5R_OBJECT) break; + /* Initialize source & destination strides */ if(buf_stride) { HDassert(buf_stride >= src->shared->size); diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index d5250ae..4ed0887 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -141,6 +141,7 @@ H5_DLL htri_t H5T_is_variable_str(const H5T_t *dt); /* Reference specific functions */ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); +H5_DLL herr_t H5T_ref_reclaim(void *elem, hid_t type_id, unsigned ndim, const hsize_t *point, void *_op_data); /* Operations on named datatypes */ H5_DLL H5T_t *H5T_open(const H5G_loc_t *loc, hid_t dxpl_id); diff --git a/src/H5Tref.c b/src/H5Tref.c index def5cb1..a55c2e4 100644 --- a/src/H5Tref.c +++ b/src/H5Tref.c @@ -31,9 +31,11 @@ #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 herr_t H5T__ref_reclaim_recurse(void *elem, const H5T_t *dt); + +static size_t H5T__ref_mem_getsize(const void *_ref); +static herr_t H5T__ref_mem_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, size_t buf_size); +static herr_t H5T__ref_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); @@ -75,15 +77,16 @@ H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* 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) { + if((dt->shared->u.atomic.u.r.rtype == H5R_REGION) || + (dt->shared->u.atomic.u.r.rtype == H5R_ATTR)) { /* size in memory, disk size is different */ - dt->shared->size = sizeof(hreg_ref_t); + dt->shared->size = sizeof(struct href_var); /* 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; + dt->shared->u.atomic.u.r.getsize = H5T__ref_mem_getsize; + dt->shared->u.atomic.u.r.read = H5T__ref_mem_read; + dt->shared->u.atomic.u.r.write = H5T__ref_mem_write; } else { HDassert(0 && "Invalid reference type"); } @@ -133,21 +136,21 @@ done: } /* end H5T__ref_set_loc() */ /*------------------------------------------------------------------------- - * Function: H5T__ref_reg_mem_getsize + * Function: H5T__ref_mem_getsize * - * Purpose: Retrieves the size of a memory based region reference. + * Purpose: Retrieves the size of a memory based reference. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ static size_t -H5T__ref_reg_mem_getsize(const void *_ref) +H5T__ref_mem_getsize(const void *_ref) { #ifdef H5_NO_ALIGNMENT_RESTRICTIONS - const hreg_ref_t *ref = (const hreg_ref_t *)_ref; + const struct href_var *ref = (const struct href_var *)_ref; #else - hreg_ref_t ref; + struct href_var ref; #endif FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -159,29 +162,29 @@ H5T__ref_reg_mem_getsize(const void *_ref) FUNC_LEAVE_NOAPI(ref->buf_size) #else HDassert(_ref); - HDmemcpy(&ref, _ref, sizeof(hreg_ref_t)); + HDmemcpy(&ref, _ref, sizeof(struct href_var)); FUNC_LEAVE_NOAPI(ref.buf_size) #endif -} /* end H5T__ref_reg_mem_getsize() */ +} /* end H5T__ref_mem_getsize() */ /*------------------------------------------------------------------------- - * Function: H5T__ref_reg_mem_read + * Function: H5T__ref_mem_read * - * Purpose: "Reads" the memory based region reference into a buffer + * Purpose: "Reads" the memory based 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, +H5T__ref_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; + const struct href_var *ref = (const struct href_var *)_ref; #else - hreg_ref_t ref; + struct href_var ref; #endif FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -194,29 +197,29 @@ H5T__ref_reg_mem_read(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, HDmemcpy(buf, ref->buf, buf_size); #else HDassert(_ref); - HDmemcpy(&ref, _ref, sizeof(hreg_ref_t)); + HDmemcpy(&ref, _ref, sizeof(struct href_var)); HDassert(ref.buf); HDmemcpy(buf, ref.buf, buf_size); #endif FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5T__ref_reg_mem_read() */ +} /* end H5T__ref_mem_read() */ /*------------------------------------------------------------------------- - * Function: H5T__ref_reg_mem_write + * Function: H5T__ref_mem_write * - * Purpose: "Writes" the memory region reference from a buffer + * Purpose: "Writes" the memory 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, +H5T__ref_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; + struct href_var ref; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -239,16 +242,16 @@ H5T__ref_reg_mem_write(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, ref.buf_size = buf_size; /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - HDmemcpy(_ref, &ref, sizeof(hreg_ref_t)); + HDmemcpy(_ref, &ref, sizeof(struct href_var)); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__ref_reg_mem_write() */ +} /* end H5T__ref_mem_write() */ /*------------------------------------------------------------------------- * Function: H5T__ref_disk_getsize * - * Purpose: Retrieves the length of a disk based reference element. + * Purpose: Retrieves the length of a disk based reference. * * Return: Non-negative on success/Negative on failure * @@ -273,7 +276,7 @@ H5T__ref_disk_getsize(const void *_ref) /*------------------------------------------------------------------------- * Function: H5T__ref_disk_read * - * Purpose: Reads the disk based region element into a buffer + * Purpose: Reads the disk based reference into a buffer * * Return: Non-negative on success/Negative on failure * @@ -303,7 +306,7 @@ H5T__ref_disk_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *buf, /* Check if this sequence actually has any data */ if(hobjid.addr > 0) { - /* Read the VL information from disk */ + /* Read the 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 */ @@ -315,7 +318,7 @@ done: /*------------------------------------------------------------------------- * Function: H5T__ref_disk_write * - * Purpose: Writes the disk based region element from a buffer + * Purpose: Writes the disk based reference from a buffer * * Return: Non-negative on success/Negative on failure * @@ -372,3 +375,95 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__ref_disk_write() */ +/*------------------------------------------------------------------------- + * Function: H5T__ref_reclaim_recurse + * + * Purpose: Internal recursive routine to free reference datatypes + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__ref_reclaim_recurse(void *elem, const H5T_t *dt) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(elem); + HDassert(dt); + + /* Check the datatype of this element */ + switch(dt->shared->type) { + case H5T_REFERENCE: + if((dt->shared->u.atomic.u.r.rtype == H5R_REGION) || + (dt->shared->u.atomic.u.r.rtype == H5R_ATTR)) { + struct href_var *ref = (struct href_var *)elem; + + if(ref->buf_size != 0) { + ref->buf = H5MM_xfree(ref->buf); + } /* end if */ + } else { + HDassert(0 && "Invalid reference type"); + } /* end else */ + break; + + /* Don't do anything for other types */ + case H5T_ARRAY: + case H5T_COMPOUND: + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_VLEN: + break; + + /* Should never have these values */ + case H5T_NO_CLASS: + case H5T_NCLASSES: + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid datatype class") + break; + + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__ref_reclaim_recurse() */ + +/*------------------------------------------------------------------------- + * Function: H5T__ref_reclaim + * + * Purpose: Default method to reclaim any reference data for a buffer element + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_ref_reclaim(void *elem, hid_t type_id, unsigned H5_ATTR_UNUSED ndim, const hsize_t H5_ATTR_UNUSED *point, void H5_ATTR_UNUSED *op_data) +{ + H5T_t *dt; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(elem); + HDassert(H5I_DATATYPE == H5I_get_type(type_id)); + + /* Check args */ + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + 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__ref_reclaim_recurse(elem, dt) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim reference elements") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_ref_reclaim() */ + -- cgit v0.12