From 4a4755d314542d951bf22ad49911ff053a5b67ec Mon Sep 17 00:00:00 2001 From: David Young Date: Wed, 29 Jan 2020 14:11:10 -0600 Subject: H5T_copy() constification plus Quincey's contributions. --- src/H5Aint.c | 6 +- src/H5Dint.c | 4 +- src/H5Fmount.c | 2 +- src/H5Gint.c | 2 +- src/H5Gobj.c | 2 +- src/H5Gtraverse.c | 2 +- src/H5L.c | 4 +- src/H5Oint.c | 101 ++++++++++--- src/H5Oprivate.h | 2 + src/H5T.c | 444 ++++++++++++++++++++++++++++++++++++++---------------- src/H5Tcommit.c | 6 +- src/H5Tcompound.c | 87 ++++++++--- src/H5Tnative.c | 2 +- src/H5Tprivate.h | 6 +- src/H5Znbit.c | 4 +- 15 files changed, 480 insertions(+), 194 deletions(-) diff --git a/src/H5Aint.c b/src/H5Aint.c index fc5ea34..1a74abe 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -224,7 +224,7 @@ H5A__create(const H5G_loc_t *loc, const char *attr_name, const H5T_t *type, HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set version of dataspace") /* Copy the object header information */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry") /* Deep copy of the group hierarchy path */ @@ -390,7 +390,7 @@ H5A__open_common(const H5G_loc_t *loc, H5A_t *attr) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") /* Deep copy of the symbol table entry */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") /* Deep copy of the group hier. path */ @@ -909,7 +909,7 @@ H5A__get_type(H5A_t *attr) * reopen the type before returning it to the user. Make the type * read-only. */ - if (NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN))) + if (NULL == (dt = H5T_copy_reopen(attr->shared->dt))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy datatype") /* Mark any datatypes as being in memory now */ diff --git a/src/H5Dint.c b/src/H5Dint.c index 436a507..c89c170 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -1535,7 +1535,7 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&(dataset->oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy_shallow(&(dataset->oloc), loc->oloc) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ @@ -3882,7 +3882,7 @@ H5D__get_type(const H5D_t *dset) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer") /* Copy the dataset's datatype */ - if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN))) + if(NULL == (dt = H5T_copy_reopen(dset->shared->type))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype") /* Mark any datatypes as being in memory now */ diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 13d95aa..5e6b899 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -766,7 +766,7 @@ H5F_traverse_mount(H5O_loc_t *oloc/*in,out*/) HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to free object location") /* Copy the entry for the root group */ - if(H5O_loc_copy(oloc, mnt_oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy_deep(oloc, mnt_oloc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location") /* In case the shared root group info points to a different file handle diff --git a/src/H5Gint.c b/src/H5Gint.c index e0b8bd7..a3849a6 100644 --- a/src/H5Gint.c +++ b/src/H5Gint.c @@ -336,7 +336,7 @@ H5G_open(const H5G_loc_t *loc) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for group") /* Shallow copy (take ownership) of the group location object */ - if(H5O_loc_copy(&(grp->oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy_shallow(&(grp->oloc), loc->oloc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy object location") if(H5G_name_copy(&(grp->path), loc->path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy path") diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 15dbd79..1892182 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -738,7 +738,7 @@ H5G__obj_info(const H5O_loc_t *oloc, H5G_info_t *grp_info) H5G_loc_reset(&grp_loc); /* Deep copy (duplicate) of the group location object */ - if(H5O_loc_copy(&grp_oloc, (H5O_loc_t *)oloc, H5_COPY_DEEP) < 0) /* (Casting away const OK - QAK) */ + if(H5O_loc_copy_deep(&grp_oloc, oloc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy object location") /* Open the group */ diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 7482e27..0f27880 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -132,7 +132,7 @@ H5G__traverse_slink_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc, const char H5_ATTR_UNU } /* end if */ else { /* Copy new location information for resolved object */ - H5O_loc_copy(udata->obj_loc->oloc, obj_loc->oloc, H5_COPY_DEEP); + H5O_loc_copy_deep(udata->obj_loc->oloc, obj_loc->oloc); /* Indicate that the object exists */ udata->exists = TRUE; diff --git a/src/H5L.c b/src/H5L.c index 0d5bc02..47e29c0 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -1910,7 +1910,7 @@ H5L__link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t H5_ATT * copy and wipe out grp_loc) */ H5G_name_reset(&temp_path); - if(H5O_loc_copy(&temp_oloc, grp_loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy_deep(&temp_oloc, grp_loc->oloc) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy object location") temp_loc.oloc = &temp_oloc; @@ -2695,7 +2695,7 @@ H5L__move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name, * copy and wipe out grp_loc) */ H5G_name_reset(&temp_path); - if(H5O_loc_copy(&temp_oloc, grp_loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy_deep(&temp_oloc, grp_loc->oloc) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy object location") temp_loc.oloc = &temp_oloc; diff --git a/src/H5Oint.c b/src/H5Oint.c index d5a3a71..04220af 100644 --- a/src/H5Oint.c +++ b/src/H5Oint.c @@ -1913,27 +1913,19 @@ H5O_loc_reset(H5O_loc_t *loc) FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_loc_reset() */ - + /*------------------------------------------------------------------------- * Function: H5O_loc_copy * - * Purpose: Copy object location information + * Purpose: Copy object location information, according to the depth. * * Return: Success: Non-negative - * Failure: Negative + * Failure: Negative * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Monday, September 19, 2005 * - * Notes: 'depth' parameter determines how much of the group entry - * structure we want to copy. The values are: - * H5_COPY_SHALLOW - Copy all the field values from the source - * to the destination, but not copying objects pointed to. - * (Destination "takes ownership" of objects pointed to) - * H5_COPY_DEEP - Copy all the fields from the source to - * the destination, deep copying objects pointed to. - * *------------------------------------------------------------------------- */ herr_t @@ -1946,25 +1938,88 @@ H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth) HDassert(dst); HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP); + /* Invoke correct routine */ + if(depth == H5_COPY_SHALLOW) + H5O_loc_copy_shallow(dst, src); + else + H5O_loc_copy_deep(dst, src); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_loc_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_loc_copy_shallow + * + * Purpose: Shallow copy object location information. Copies all the field + * values from the source to the destination, but not copying + * objects pointed to. (i.e. destination "takes ownership" of + * objects pointed to) + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_loc_copy_shallow(H5O_loc_t *dst, H5O_loc_t *src) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check arguments */ + HDassert(src); + HDassert(dst); + /* Copy the top level information */ H5MM_memcpy(dst, src, sizeof(H5O_loc_t)); - /* Deep copy the names */ - if(depth == H5_COPY_DEEP) { - /* If the original entry was holding open the file, this one should - * hold it open, too. - */ - if(src->holding_file) - H5F_INCR_NOPEN_OBJS(dst->file); - } - else if(depth == H5_COPY_SHALLOW) { - H5O_loc_reset(src); - } + /* Reset the source location, as the destination 'owns' it now */ + H5O_loc_reset(src); FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5O_loc_copy() */ +} /* end H5O_loc_copy_shallow() */ + +/*------------------------------------------------------------------------- + * Function: H5O_loc_copy_deep + * + * Purpose: Deep copy object location information. Copies all the fields + * from the source to the destination, deep copying objects + * pointed to. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_loc_copy_deep(H5O_loc_t *dst, const H5O_loc_t *src) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check arguments */ + HDassert(src); + HDassert(dst); + + /* Copy the top level information */ + H5MM_memcpy(dst, src, sizeof(H5O_loc_t)); + + /* If the original entry was holding open the file, this one should + * hold it open, too. + */ + if(src->holding_file) + H5F_INCR_NOPEN_OBJS(dst->file); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_loc_copy_deep() */ + /*------------------------------------------------------------------------- * Function: H5O_loc_hold_file * diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 52a72b2..ceaa96d 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -997,6 +997,8 @@ H5_DLL herr_t H5O_debug(H5F_t *f, haddr_t addr, FILE * stream, int indent, /* These functions operate on object locations */ H5_DLL herr_t H5O_loc_reset(H5O_loc_t *loc); H5_DLL herr_t H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth); +H5_DLL herr_t H5O_loc_copy_shallow(H5O_loc_t *dst, H5O_loc_t *src); +H5_DLL herr_t H5O_loc_copy_deep(H5O_loc_t *dst, const H5O_loc_t *src); H5_DLL herr_t H5O_loc_hold_file(H5O_loc_t *loc); H5_DLL herr_t H5O_loc_free(H5O_loc_t *loc); H5_DLL H5O_loc_t *H5O_get_loc(hid_t id); diff --git a/src/H5T.c b/src/H5T.c index f1c2dbb..5d3c4a1 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -301,6 +301,9 @@ /* Local Typedefs */ /******************/ +/* Typedef for recursive const-correct datatype copying routines */ +typedef H5T_t *(*H5T_copy_func_t)(H5T_t *old_dt); + /********************/ /* Local Prototypes */ @@ -313,6 +316,11 @@ static herr_t H5T__set_size(H5T_t *dt, size_t size); static herr_t H5T__close_cb(H5T_t *dt); static H5T_path_t *H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv); static hbool_t H5T__detect_vlen_ref(const H5T_t *dt); +static H5T_t *H5T__initiate_copy(const H5T_t *old_dt); +static H5T_t *H5T__copy_transient(H5T_t *old_dt); +static H5T_t *H5T__copy_all(H5T_t *old_dt); +static herr_t H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, + H5T_shared_t *reopened_fo, hbool_t set_memory_type, H5T_copy_func_t copyfn); /*****************************/ @@ -3304,132 +3312,152 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__create() */ - + /*------------------------------------------------------------------------- - * Function: H5T_copy + * Function: H5T__initiate_copy * - * Purpose: Copies datatype OLD_DT. The resulting data type is not - * locked and is a transient type. + * Purpose: Allocates datatype structures, copies core fields, and initializes + * VOL fields. * * Return: Success: Pointer to a new copy of the OLD_DT argument. - * * Failure: NULL * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 + * Note: Common code for both H5T_copy and H5T_copy_reopen, as part of + * the const-correct datatype copying routines. + * + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ -H5T_t * -H5T_copy(H5T_t *old_dt, H5T_copy_t method) +static H5T_t * +H5T__initiate_copy(const H5T_t *old_dt) { - H5T_t *new_dt = NULL, *tmp = NULL; - H5T_shared_t *reopened_fo = NULL; - unsigned i; - char *s; - H5T_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(NULL) + H5T_t *new_dt = NULL; /* Copy of datatype */ + H5T_t *ret_value = NULL; /* Return value */ - /* check args */ - HDassert(old_dt); + FUNC_ENTER_STATIC /* Allocate space */ if(NULL == (new_dt = H5FL_MALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_t memory allocation failed") if(NULL == (new_dt->shared = H5FL_MALLOC(H5T_shared_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_shared_t memory allocation failed") - /* Copy shared information (entry information is copied last) */ + /* Copy shared information */ *(new_dt->shared) = *(old_dt->shared); - /* No VOL object */ + /* Reset VOL fields */ new_dt->vol_obj = NULL; - - /* No owned VOL object */ new_dt->shared->owned_vol_obj = NULL; - /* Check what sort of copy we are making */ - switch (method) { - case H5T_COPY_TRANSIENT: - /* - * Return an unlocked transient type. - */ - new_dt->shared->state = H5T_STATE_TRANSIENT; - break; + /* Set return value */ + ret_value = new_dt; - case H5T_COPY_ALL: - /* - * Return a transient type (locked or unlocked) or an unopened named - * type. Immutable transient types are degraded to read-only. - */ - if(H5T_STATE_OPEN==old_dt->shared->state) - new_dt->shared->state = H5T_STATE_NAMED; - else if(H5T_STATE_IMMUTABLE==old_dt->shared->state) - new_dt->shared->state = H5T_STATE_RDONLY; - break; +done: + if(ret_value == NULL) + if(new_dt) { + if(new_dt->shared) + new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); + new_dt = H5FL_FREE(H5T_t, new_dt); + } /* end if */ - case H5T_COPY_REOPEN: - /* - * Return a transient type (locked or unlocked) or an opened named - * type. Immutable transient types are degraded to read-only. - */ - if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { - /* Check if the object is already open */ - if(NULL == (reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) { - /* Clear any errors from H5FO_opened() */ - H5E_clear_stack(NULL); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__initiate_copy() */ - /* Open named datatype again */ - if(H5O_open(&old_dt->oloc) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type") + +/*------------------------------------------------------------------------- + * Function: H5T__copy_transient + * + * Purpose: Part of recursive framework for const-correct datatype copying. + * + * Return: Success: Pointer to a new copy of the OLD_DT argument. + * Failure: NULL + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +static H5T_t * +H5T__copy_transient(H5T_t *old_dt) +{ + H5T_t *ret_value = NULL; /* Return value */ - /* Insert opened named datatype into opened object list for the file */ - if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") + FUNC_ENTER_STATIC - /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + /* Copy datatype, with correct method */ + if(NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'transient' copy of datatype") - new_dt->shared->fo_count = 1; - } /* end if */ - else { - /* The object is already open. Free the H5T_shared_t struct - * we had been using and use the one that already exists. - * Not terribly efficient. */ - new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); - new_dt->shared = reopened_fo; - - reopened_fo->fo_count++; - - /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) { - /* Open the object through this top file */ - if(H5O_open(&old_dt->oloc) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") - } /* end if */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__copy_transient() */ - /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") - } /* end else */ - new_dt->shared->state = H5T_STATE_OPEN; - } - else if(H5T_STATE_IMMUTABLE == old_dt->shared->state) { - new_dt->shared->state = H5T_STATE_RDONLY; - } - break; - default: - HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type") - } /* end switch */ + +/*------------------------------------------------------------------------- + * Function: H5T__copy_all + * + * Purpose: Part of recursive framework for const-correct datatype copying. + * + * Return: Success: Pointer to a new copy of the OLD_DT argument. + * Failure: NULL + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +static H5T_t * +H5T__copy_all(H5T_t *old_dt) +{ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_STATIC + + /* Copy datatype, with correct method */ + if(NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'all' copy of datatype") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__copy_transient() */ + + +/*------------------------------------------------------------------------- + * Function: H5T__complete_copy + * + * Purpose: Completes copying datatype fields, as part of the recursive + * const-correct datatype copy routines. + * + * Return: Success: non-negative + * Failure: negative + * + * Note: Common code for both H5T_copy and H5T_copy_reopen. + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo, + hbool_t set_memory_type, H5T_copy_func_t copyfn) +{ + H5T_t *tmp = NULL; /* Temporary copy of compound field's datatype */ + char *s; /* Temporary copy of compound field name / enum value name */ + unsigned i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC /* Update fields in the new struct, if we aren't sharing an already opened * committed datatype */ if(!reopened_fo) { /* Copy parent information */ if(old_dt->shared->parent) - new_dt->shared->parent = H5T_copy(old_dt->shared->parent, method); + if(NULL == (new_dt->shared->parent = (*copyfn)(old_dt->shared->parent))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype's parent type") switch(new_dt->shared->type) { case H5T_COMPOUND: @@ -3443,10 +3471,8 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) */ /* Only malloc if space has been allocated for members - NAF */ if(new_dt->shared->u.compnd.nalloc > 0) { - new_dt->shared->u.compnd.memb = - (H5T_cmemb_t *)H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t)); - if (NULL == new_dt->shared->u.compnd.memb) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(NULL == (new_dt->shared->u.compnd.memb = H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t)))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed") H5MM_memcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb, new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t)); @@ -3456,15 +3482,17 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) unsigned j; int old_match; - s = new_dt->shared->u.compnd.memb[i].name; - new_dt->shared->u.compnd.memb[i].name = H5MM_xstrdup(s); - tmp = H5T_copy (old_dt->shared->u.compnd.memb[i].type, method); + if(NULL == (s = H5MM_xstrdup(new_dt->shared->u.compnd.memb[i].name))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy string for compound field's name") + new_dt->shared->u.compnd.memb[i].name = s; + if(NULL == (tmp = (*copyfn)(old_dt->shared->u.compnd.memb[i].type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy compound field's datatype") new_dt->shared->u.compnd.memb[i].type = tmp; HDassert(tmp != NULL); /* Range check against compound member's offset */ - if ((accum_change < 0) && ((ssize_t) new_dt->shared->u.compnd.memb[i].offset < accum_change)) - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype") + if((accum_change < 0) && ((ssize_t) new_dt->shared->u.compnd.memb[i].offset < accum_change)) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype") /* Apply the accumulated size change to the offset of the field */ new_dt->shared->u.compnd.memb[i].offset += (size_t) accum_change; @@ -3479,7 +3507,7 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) /* check if we couldn't find a match */ if(old_match < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "fields in datatype corrupted") } /* end if */ else old_match = (int) i; @@ -3494,8 +3522,8 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) } /* end for */ /* Range check against datatype size */ - if ((accum_change < 0) && ((ssize_t) new_dt->shared->size < accum_change)) - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype") + if((accum_change < 0) && ((ssize_t) new_dt->shared->size < accum_change)) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype") /* Apply the accumulated size change to the size of the compound struct */ new_dt->shared->size += (size_t) accum_change; @@ -3508,27 +3536,25 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) * of each new member with copied values. That is, H5T_copy() is a * deep copy. */ - new_dt->shared->u.enumer.name = - (char **)H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char*)); - new_dt->shared->u.enumer.value = - (uint8_t *)H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size); - if(NULL == new_dt->shared->u.enumer.value) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(NULL == (new_dt->shared->u.enumer.name = H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char*)))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam name array memory allocation failed") + if(NULL == (new_dt->shared->u.enumer.value = H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam value array memory allocation failed") H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value, new_dt->shared->u.enumer.nmembs * new_dt->shared->size); for(i = 0; i < new_dt->shared->u.enumer.nmembs; i++) { - s = old_dt->shared->u.enumer.name[i]; - new_dt->shared->u.enumer.name[i] = H5MM_xstrdup(s); + if(NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i]))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy string for enum value's name") + new_dt->shared->u.enumer.name[i] = s; } /* end for */ break; case H5T_VLEN: case H5T_REFERENCE: - if(method == H5T_COPY_TRANSIENT || method == H5T_COPY_REOPEN) { + if(set_memory_type) /* H5T_copy converts any type into a memory type */ if(H5T_set_loc(new_dt, NULL, H5T_LOC_MEMORY) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") - } /* end if */ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") break; case H5T_OPAQUE: @@ -3540,7 +3566,7 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) case H5T_ARRAY: /* Re-compute the array's size, in case it's base type changed size */ - new_dt->shared->size=new_dt->shared->u.array.nelem*new_dt->shared->parent->shared->size; + new_dt->shared->size = new_dt->shared->u.array.nelem * new_dt->shared->parent->shared->size; break; case H5T_NO_CLASS: @@ -3559,15 +3585,15 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) * type and the new type is also named. */ if(H5O_loc_reset(&new_dt->oloc) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to initialize location") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location") if(H5G_name_reset(&new_dt->path) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset path") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path") if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { - if(H5O_loc_copy(&(new_dt->oloc), &(old_dt->oloc), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") + if(H5O_loc_copy_deep(&(new_dt->oloc), &(old_dt->oloc)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy object location") if(H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to copy path") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy path") } /* end if */ /* Copy shared location information if the new type is named or if it is @@ -3576,28 +3602,194 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method) if((old_dt->sh_loc.type == H5O_SHARE_TYPE_SOHM || old_dt->sh_loc.type == H5O_SHARE_TYPE_HERE) || new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { if(H5O_set_shared(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy shared information") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy shared information") } /* end if */ else /* Reset shared component info */ H5O_msg_reset_share(H5O_DTYPE_ID, new_dt); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__complete_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_copy + * + * Purpose: Copies datatype OLD_DT. The resulting data type is not + * locked and is a transient type. + * + * Return: Success: Pointer to a new copy of the OLD_DT argument. + * Failure: NULL + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_copy(const H5T_t *old_dt, H5T_copy_t method) +{ + H5T_t *new_dt = NULL; /* New datatype */ + H5T_copy_func_t copyfn; /* Pointer to correct copy routine */ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* check args */ + HDassert(old_dt); + + /* Allocate and copy core datatype information */ + if(NULL == (new_dt = H5T__initiate_copy(old_dt))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info") + + /* Check what sort of copy we are making */ + switch (method) { + case H5T_COPY_TRANSIENT: + /* + * Return an unlocked transient type. + */ + new_dt->shared->state = H5T_STATE_TRANSIENT; + copyfn = H5T__copy_transient; + break; + + case H5T_COPY_ALL: + /* + * Return a transient type (locked or unlocked) or an unopened named + * type. Immutable transient types are degraded to read-only. + */ + if(H5T_STATE_OPEN==old_dt->shared->state) + new_dt->shared->state = H5T_STATE_NAMED; + else if(H5T_STATE_IMMUTABLE==old_dt->shared->state) + new_dt->shared->state = H5T_STATE_RDONLY; + copyfn = H5T__copy_all; + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type") + } /* end switch */ + + /* Finish making the copy of the datatype */ + if(H5T__complete_copy(new_dt, old_dt, NULL, (method == H5T_COPY_TRANSIENT), copyfn) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization") + /* Set return value */ ret_value = new_dt; done: - if(ret_value == NULL) { + if(ret_value == NULL) if(new_dt) { - if(new_dt->shared) - new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); + HDassert(new_dt->shared); + new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); new_dt = H5FL_FREE(H5T_t, new_dt); } /* end if */ - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_copy() */ + +/*------------------------------------------------------------------------- + * Function: H5T_copy_reopen + * + * Purpose: Copy a datatype, possibly reopening a named datatype, as part + * the const-correct datatype copying routines. + * + * Return: Success: Pointer to a new copy of the OLD_DT argument. + * Failure: NULL + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_copy_reopen(H5T_t *old_dt) +{ + H5T_t *new_dt = NULL; /* New datatype */ + H5T_shared_t *reopened_fo = NULL; /* Pointer to reopened existing named datatype */ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + /* check args */ + HDassert(old_dt); + + /* Allocate and copy core datatype information */ + if(NULL == (new_dt = H5T__initiate_copy(old_dt))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info") + + /* + * Return a transient type (locked or unlocked) or an opened named + * type. Immutable transient types are degraded to read-only. + */ + if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { + /* Check if the object is already open */ + if(NULL == (reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) { + /* Clear any errors from H5FO_opened() */ + H5E_clear_stack(NULL); + + /* Open named datatype again */ + if(H5O_open(&old_dt->oloc) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type") + + /* Insert opened named datatype into opened object list for the file */ + if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + + new_dt->shared->fo_count = 1; + } /* end if */ + else { + /* The object is already open. Free the H5T_shared_t struct + * we had been using and use the one that already exists. + * Not terribly efficient. */ + new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); + new_dt->shared = reopened_fo; + + reopened_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) { + /* Open the object through this top file */ + if(H5O_open(&old_dt->oloc) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + } /* end else */ + + /* Set state for new datatype */ + new_dt->shared->state = H5T_STATE_OPEN; + } /* end if */ + else + /* Downgrade immutable datatypes to read-only */ + if(H5T_STATE_IMMUTABLE == old_dt->shared->state) + new_dt->shared->state = H5T_STATE_RDONLY; + + /* Finish making the copy of the datatype */ + if(H5T__complete_copy(new_dt, old_dt, reopened_fo, TRUE, H5T_copy_reopen) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization") + + /* Set return value */ + ret_value = new_dt; + +done: + if(ret_value == NULL) + if(new_dt) { + HDassert(new_dt->shared); + new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared); + new_dt = H5FL_FREE(H5T_t, new_dt); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_copy_reopen() */ + /*------------------------------------------------------------------------- * Function: H5T_lock * diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 1b922d5..7d26af3 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -446,7 +446,7 @@ H5T__commit(H5F_t *file, H5T_t *type, hid_t tcpl_id) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") /* Copy the new object header's location into the datatype, taking ownership of it */ - if(H5O_loc_copy(&(type->oloc), &temp_oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy_shallow(&(type->oloc), &temp_oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") if(H5G_name_copy(&(type->path), &temp_path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") @@ -943,7 +943,7 @@ H5T_open(const H5G_loc_t *loc) #endif /* H5_USING_MEMCHECKER */ /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy_shallow(&dt->oloc, loc->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ @@ -1033,7 +1033,7 @@ H5T__open_oid(const H5G_loc_t *loc) dt->shared->state = H5T_STATE_OPEN; /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy_shallow(&dt->oloc, loc->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c index d4f1008..f4a9e04 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -51,8 +51,9 @@ /********************/ /* Local Prototypes */ /********************/ -static herr_t H5T_pack(const H5T_t *dt); -static htri_t H5T_is_packed(const H5T_t *dt); +static herr_t H5T__pack(const H5T_t *dt); +static htri_t H5T__is_packed(const H5T_t *dt); +static H5T_t *H5T__reopen_member_type(const H5T_t *dt, unsigned membno); /*********************/ @@ -226,7 +227,7 @@ H5Tget_member_type(hid_t type_id, unsigned membno) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid member number") /* Retrieve the datatype for the member */ - if(NULL == (memb_dt = H5T_get_member_type(dt, membno, H5T_COPY_REOPEN))) + if(NULL == (memb_dt = H5T__reopen_member_type(dt, membno))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to retrieve member type") /* Get an ID for the datatype */ @@ -245,8 +246,7 @@ done: /*------------------------------------------------------------------------- * Function: H5T_get_member_type * - * Purpose: Private function for H5Tget_member_type. Returns the data - * type of the specified member. + * Purpose: Returns a copy of the data type of the specified member. * * Return: Success: A copy of the member datatype; * modifying the returned datatype does not @@ -260,18 +260,19 @@ done: *------------------------------------------------------------------------- */ H5T_t * -H5T_get_member_type(const H5T_t *dt, unsigned membno, H5T_copy_t method) +H5T_get_member_type(const H5T_t *dt, unsigned membno) { H5T_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) + /* Sanity checks */ HDassert(dt); HDassert(membno < dt->shared->u.compnd.nmembs); - /* Copy datatype into an atom */ - if(NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, method))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member datatype") + /* Copy datatype */ + if(NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy member datatype") done: FUNC_LEAVE_NOAPI(ret_value) @@ -279,6 +280,43 @@ done: /*------------------------------------------------------------------------- + * Function: H5T__reopen_member_type + * + * Purpose: Private function for H5Tget_member_type. Returns a re-opened + * copy of the data type of the specified member. + * + * Return: Success: A copy of the member datatype; + * modifying the returned datatype does not + * modify the member type. + * + * Failure: NULL + * + * Programmer: David Young + * January 18, 2020 + * + *------------------------------------------------------------------------- + */ +static H5T_t * +H5T__reopen_member_type(const H5T_t *dt, unsigned membno) +{ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(dt); + HDassert(membno < dt->shared->u.compnd.nmembs); + + /* Copy datatype, possibly re-opening it */ + if(NULL == (ret_value = H5T_copy_reopen(dt->shared->u.compnd.memb[membno].type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to reopen member datatype") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__reopen_member_type() */ + + +/*------------------------------------------------------------------------- * Function: H5T__get_member_size * * Purpose: Returns the size of the specified member. @@ -387,7 +425,7 @@ H5Tpack(hid_t type_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype") /* Pack */ - if(H5T_pack(dt) < 0) + if(H5T__pack(dt) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound datatype") done: @@ -493,7 +531,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5T_pack + * Function: H5T__pack * * Purpose: Recursively packs a compound datatype by removing padding * bytes. This is done in place (that is, destructively). @@ -506,17 +544,17 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5T_pack(const H5T_t *dt) +H5T__pack(const H5T_t *dt) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC HDassert(dt); if(H5T_detect_class(dt, H5T_COMPOUND, FALSE) > 0) { /* If datatype has been packed, skip packing it and indicate success */ - if(TRUE == H5T_is_packed(dt)) + if(TRUE == H5T__is_packed(dt)) HGOTO_DONE(SUCCEED) /* Check for packing unmodifiable datatype */ @@ -524,7 +562,7 @@ H5T_pack(const H5T_t *dt) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is read-only") if(dt->shared->parent) { - if (H5T_pack(dt->shared->parent) < 0) + if(H5T__pack(dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack parent of datatype") /* Adjust size of datatype appropriately */ @@ -539,7 +577,7 @@ H5T_pack(const H5T_t *dt) /* Recursively pack the members */ for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { - if(H5T_pack(dt->shared->u.compnd.memb[i].type) < 0) + if(H5T__pack(dt->shared->u.compnd.memb[i].type) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound datatype") /* Update the member size */ @@ -552,7 +590,7 @@ H5T_pack(const H5T_t *dt) for(i = 0, offset = 0; i < dt->shared->u.compnd.nmembs; i++) { dt->shared->u.compnd.memb[i].offset = offset; offset += dt->shared->u.compnd.memb[i].size; - } + } /* end for */ /* Change total size */ dt->shared->size = MAX(1, offset); @@ -564,11 +602,11 @@ H5T_pack(const H5T_t *dt) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_pack() */ +} /* end H5T__pack() */ /*------------------------------------------------------------------------- - * Function: H5T_is_packed + * Function: H5T__is_packed * * Purpose: Checks whether a datatype which is compound (or has compound * components) is packed. @@ -583,11 +621,11 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5T_is_packed(const H5T_t *dt) +H5T__is_packed(const H5T_t *dt) { htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(dt); @@ -596,12 +634,11 @@ H5T_is_packed(const H5T_t *dt) dt = dt->shared->parent; /* If this is a compound datatype, check if it is packed */ - if(dt->shared->type == H5T_COMPOUND) { + if(dt->shared->type == H5T_COMPOUND) ret_value = (htri_t)(dt->shared->u.compnd.packed); - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T_is_packed() */ +} /* end H5T__is_packed() */ /*------------------------------------------------------------------------- @@ -638,7 +675,7 @@ H5T__update_packed(const H5T_t *dt) /* Now check if all members are packed */ for(i = 0; i < dt->shared->u.compnd.nmembs; i++) - if(!H5T_is_packed(dt->shared->u.compnd.memb[i].type)) { + if(!H5T__is_packed(dt->shared->u.compnd.memb[i].type)) { dt->shared->u.compnd.packed = FALSE; break; } /* end if */ diff --git a/src/H5Tnative.c b/src/H5Tnative.c index 1d203c7..178d1a0 100644 --- a/src/H5Tnative.c +++ b/src/H5Tnative.c @@ -272,7 +272,7 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali /* Construct child compound type and retrieve a list of their IDs, offsets, total size, and alignment for compound type. */ for(u = 0; u < nmemb; u++) { - if(NULL == (memb_type = H5T_get_member_type(dtype, u, H5T_COPY_TRANSIENT))) + if(NULL == (memb_type = H5T_get_member_type(dtype, u))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "member type retrieval failed") if(NULL == (comp_mname[u] = H5T__get_member_name(dtype, u))) diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index d8e98af..e05bb4e 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -59,7 +59,6 @@ struct H5S_t; typedef enum H5T_copy_t { H5T_COPY_TRANSIENT, H5T_COPY_ALL, - H5T_COPY_REOPEN } H5T_copy_t; /* Location of datatype information */ @@ -109,7 +108,8 @@ H5_DLLVAR H5T_order_t H5T_native_order_g; /* Private functions */ H5_DLL herr_t H5T_init(void); -H5_DLL H5T_t *H5T_copy(H5T_t *old_dt, H5T_copy_t method); +H5_DLL H5T_t *H5T_copy(const H5T_t *old_dt, H5T_copy_t method); +H5_DLL H5T_t *H5T_copy_reopen(H5T_t *old_dt); H5_DLL herr_t H5T_lock(H5T_t *dt, hbool_t immutable); H5_DLL herr_t H5T_close(H5T_t *dt); H5_DLL herr_t H5T_close_real(H5T_t *dt); @@ -164,7 +164,7 @@ H5_DLL herr_t H5T_update_shared(H5T_t *type); /* Field functions (for both compound & enumerated types) */ H5_DLL int H5T_get_nmembers(const H5T_t *dt); -H5_DLL H5T_t *H5T_get_member_type(const H5T_t *dt, unsigned membno, H5T_copy_t method); +H5_DLL H5T_t *H5T_get_member_type(const H5T_t *dt, unsigned membno); H5_DLL size_t H5T_get_member_offset(const H5T_t *dt, unsigned membno); /* Atomic functions */ diff --git a/src/H5Znbit.c b/src/H5Znbit.c index fe0041c..2f79725 100644 --- a/src/H5Znbit.c +++ b/src/H5Znbit.c @@ -338,7 +338,7 @@ H5Z_calc_parms_compound(const H5T_t *type, size_t *cd_values_actual_nparms) H5T_class_t dtype_member_class; /* Compound datatype's member datatype's class */ /* Get member datatype */ - if(NULL == (dtype_member = H5T_get_member_type(type, u, H5T_COPY_TRANSIENT))) + if(NULL == (dtype_member = H5T_get_member_type(type, u))) HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype") /* Get member datatype's class */ @@ -695,7 +695,7 @@ H5Z_set_parms_compound(const H5T_t *type, unsigned *cd_values_index, /* For each member, set parameters */ for(u = 0; u < nmembers; u++) { /* Get member datatype */ - if(NULL == (dtype_member = H5T_get_member_type(type, u, H5T_COPY_TRANSIENT))) + if(NULL == (dtype_member = H5T_get_member_type(type, u))) HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype") /* Get member datatype's class */ -- cgit v0.12 From f398fe6beefdd1d8bd7f34ec3ca9a17068c926a5 Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 30 Jan 2020 14:10:07 -0600 Subject: Temporarily add some code that measures the time to run the simplest possible H5T__copy_all()-like routine 10 million times and then measures the version with FUNC_ENTER_STATIC/_LEAVE_NOAPI and a HGOTO_ERROR() statement. --- test/Makefile.am | 2 ++ test/dtypes.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/nop.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 test/nop.c diff --git a/test/Makefile.am b/test/Makefile.am index 57080aa..6b6930b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -140,6 +140,8 @@ libh5test_la_SOURCES=h5test.c testframe.c cache_common.c swmr_common.c external_ # Use libhd5test.la to compile all of the tests LDADD=libh5test.la $(LIBHDF5) +dtypes_SOURCES=dtypes.c nop.c + # List the source files for tests that have more than one ttsafe_SOURCES=ttsafe.c ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c \ ttsafe_acreate.c diff --git a/test/dtypes.c b/test/dtypes.c index 0f95830..05da909 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -7815,6 +7815,30 @@ error: return 1; } /* end test_versionbounds() */ +herr_t no_operation(H5T_t *t, int mode); +herr_t H5T__forward_args_with_func_overhead(H5T_t *t); +herr_t H5T__forward_args_without_func_overhead(H5T_t *t); + +herr_t +H5T__forward_args_with_func_overhead(H5T_t *t) +{ + herr_t ret_value = FAIL; + + FUNC_ENTER_STATIC + + if ((ret_value = no_operation(t, 10)) == FAIL) + HGOTO_ERROR(17, 31, FAIL, "that didn't work"); + + ret_value = SUCCEED; +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +herr_t +H5T__forward_args_without_func_overhead(H5T_t *t) +{ + return no_operation(t, 10); +} /*------------------------------------------------------------------------- * Function: main @@ -7837,6 +7861,9 @@ main(void) { long nerrors = 0; hid_t fapl = -1; + H5T_t *t; + int i, ntimes = 10 * 1000 * 1000; + uint64_t start, stop; /* Set the random # seed */ HDsrandom((unsigned)HDtime(NULL)); @@ -7847,6 +7874,23 @@ main(void) if(ALIGNMENT) printf("Testing non-aligned conversions (ALIGNMENT=%d)....\n", ALIGNMENT); + t = (H5T_t *)H5I_object(H5T_NATIVE_SHORT); + if (t == NULL) abort(); + + start = __builtin_ia32_rdtsc(); + for (i = 0; i < ntimes; i++) + H5T__forward_args_without_func_overhead(t); + stop = __builtin_ia32_rdtsc(); + printf("%d calls to no-overhead version, %" PRIu64 " cycles\n", + ntimes, stop - start); + + start = __builtin_ia32_rdtsc(); + for (i = 0; i < ntimes; i++) + H5T__forward_args_with_func_overhead(t); + stop = __builtin_ia32_rdtsc(); + printf("%d calls to overhead version, %" PRIu64 " cycles\n", + ntimes, stop - start); + /* Do the tests */ nerrors += test_classes(); nerrors += test_copy(); diff --git a/test/nop.c b/test/nop.c new file mode 100644 index 0000000..4829eb9 --- /dev/null +++ b/test/nop.c @@ -0,0 +1,29 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "testhdf5.h" +#include "H5srcdir.h" +#include "H5Iprivate.h" /* For checking that datatype id's don't leak */ + +#define H5T_FRIEND /*suppress error about including H5Tpkg */ +#include "H5Tpkg.h" + +herr_t no_operation(H5T_t *t, int mode); + +herr_t +no_operation(H5T_t *t, int mode) +{ + static int ncalls = 0; + ncalls++; + return SUCCEED; +} -- cgit v0.12 From 69a064eef8aeeba0090ccbe0914348daced513ff Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 30 Jan 2020 15:46:12 -0600 Subject: Increase iterations, provide a baseline for no-op, simplify the overhead case a bit. --- test/dtypes.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/dtypes.c b/test/dtypes.c index 05da909..a12d204 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -7819,7 +7819,7 @@ herr_t no_operation(H5T_t *t, int mode); herr_t H5T__forward_args_with_func_overhead(H5T_t *t); herr_t H5T__forward_args_without_func_overhead(H5T_t *t); -herr_t +herr_t __attribute__((noinline)) H5T__forward_args_with_func_overhead(H5T_t *t) { herr_t ret_value = FAIL; @@ -7829,12 +7829,11 @@ H5T__forward_args_with_func_overhead(H5T_t *t) if ((ret_value = no_operation(t, 10)) == FAIL) HGOTO_ERROR(17, 31, FAIL, "that didn't work"); - ret_value = SUCCEED; done: FUNC_LEAVE_NOAPI(ret_value) } -herr_t +herr_t __attribute__((noinline)) H5T__forward_args_without_func_overhead(H5T_t *t) { return no_operation(t, 10); @@ -7862,7 +7861,7 @@ main(void) long nerrors = 0; hid_t fapl = -1; H5T_t *t; - int i, ntimes = 10 * 1000 * 1000; + int i, ntimes = 100 * 1000 * 1000; uint64_t start, stop; /* Set the random # seed */ @@ -7879,6 +7878,13 @@ main(void) start = __builtin_ia32_rdtsc(); for (i = 0; i < ntimes; i++) + no_operation(t, 10); + stop = __builtin_ia32_rdtsc(); + printf("%d calls to no-op routine, %" PRIu64 " cycles\n", + ntimes, stop - start); + + start = __builtin_ia32_rdtsc(); + for (i = 0; i < ntimes; i++) H5T__forward_args_without_func_overhead(t); stop = __builtin_ia32_rdtsc(); printf("%d calls to no-overhead version, %" PRIu64 " cycles\n", -- cgit v0.12 From a5a9e75f6a0ebf6f67509a740d9235366b7de046 Mon Sep 17 00:00:00 2001 From: David Young Date: Thu, 6 Feb 2020 11:00:10 -0600 Subject: Make calls through a function pointer. Use the same number of arguments, always. --- test/dtypes.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/test/dtypes.c b/test/dtypes.c index a12d204..a58edf1 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -7816,17 +7816,17 @@ error: } /* end test_versionbounds() */ herr_t no_operation(H5T_t *t, int mode); -herr_t H5T__forward_args_with_func_overhead(H5T_t *t); -herr_t H5T__forward_args_without_func_overhead(H5T_t *t); +herr_t H5T__forward_args_with_func_overhead(H5T_t *t, int); +herr_t H5T__forward_args_without_func_overhead(H5T_t *t, int); herr_t __attribute__((noinline)) -H5T__forward_args_with_func_overhead(H5T_t *t) +H5T__forward_args_with_func_overhead(H5T_t *t, int mode) { herr_t ret_value = FAIL; FUNC_ENTER_STATIC - if ((ret_value = no_operation(t, 10)) == FAIL) + if ((ret_value = no_operation(t, mode)) == FAIL) HGOTO_ERROR(17, 31, FAIL, "that didn't work"); done: @@ -7834,9 +7834,9 @@ done: } herr_t __attribute__((noinline)) -H5T__forward_args_without_func_overhead(H5T_t *t) +H5T__forward_args_without_func_overhead(H5T_t *t, int mode) { - return no_operation(t, 10); + return no_operation(t, mode); } /*------------------------------------------------------------------------- @@ -7863,6 +7863,8 @@ main(void) H5T_t *t; int i, ntimes = 100 * 1000 * 1000; uint64_t start, stop; + typedef herr_t (*fn_t)(H5T_t *, int); + volatile fn_t fn = no_operation; /* Set the random # seed */ HDsrandom((unsigned)HDtime(NULL)); @@ -7876,26 +7878,32 @@ main(void) t = (H5T_t *)H5I_object(H5T_NATIVE_SHORT); if (t == NULL) abort(); + fn = no_operation; start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) - no_operation(t, 10); + for (i = 0; i < ntimes; i++) { + (*fn)(t, 10); + } stop = __builtin_ia32_rdtsc(); - printf("%d calls to no-op routine, %" PRIu64 " cycles\n", - ntimes, stop - start); + printf("%d calls to %11s routine, %" PRIu64 " cycles\n", + ntimes, "no-op", stop - start); + fn = H5T__forward_args_without_func_overhead; start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) - H5T__forward_args_without_func_overhead(t); + for (i = 0; i < ntimes; i++) { + (*fn)(t, 10); + } stop = __builtin_ia32_rdtsc(); - printf("%d calls to no-overhead version, %" PRIu64 " cycles\n", - ntimes, stop - start); + printf("%d calls to %11s version, %" PRIu64 " cycles\n", + ntimes, "no-overhead", stop - start); + fn = H5T__forward_args_with_func_overhead; start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) - H5T__forward_args_with_func_overhead(t); + for (i = 0; i < ntimes; i++) { + (*fn)(t, 10); + } stop = __builtin_ia32_rdtsc(); - printf("%d calls to overhead version, %" PRIu64 " cycles\n", - ntimes, stop - start); + printf("%d calls to %11s version, %" PRIu64 " cycles\n", + ntimes, "overhead", stop - start); /* Do the tests */ nerrors += test_classes(); -- cgit v0.12 From 3f903a441ad84001ea66589728bd8b036b6fdfca Mon Sep 17 00:00:00 2001 From: David Young Date: Fri, 14 Feb 2020 15:01:44 -0600 Subject: Take out the temporary performance tests. --- test/Makefile.am | 2 -- test/dtypes.c | 58 -------------------------------------------------------- test/nop.c | 29 ---------------------------- 3 files changed, 89 deletions(-) delete mode 100644 test/nop.c diff --git a/test/Makefile.am b/test/Makefile.am index 6b6930b..57080aa 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -140,8 +140,6 @@ libh5test_la_SOURCES=h5test.c testframe.c cache_common.c swmr_common.c external_ # Use libhd5test.la to compile all of the tests LDADD=libh5test.la $(LIBHDF5) -dtypes_SOURCES=dtypes.c nop.c - # List the source files for tests that have more than one ttsafe_SOURCES=ttsafe.c ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c \ ttsafe_acreate.c diff --git a/test/dtypes.c b/test/dtypes.c index a58edf1..0f95830 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -7815,29 +7815,6 @@ error: return 1; } /* end test_versionbounds() */ -herr_t no_operation(H5T_t *t, int mode); -herr_t H5T__forward_args_with_func_overhead(H5T_t *t, int); -herr_t H5T__forward_args_without_func_overhead(H5T_t *t, int); - -herr_t __attribute__((noinline)) -H5T__forward_args_with_func_overhead(H5T_t *t, int mode) -{ - herr_t ret_value = FAIL; - - FUNC_ENTER_STATIC - - if ((ret_value = no_operation(t, mode)) == FAIL) - HGOTO_ERROR(17, 31, FAIL, "that didn't work"); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - -herr_t __attribute__((noinline)) -H5T__forward_args_without_func_overhead(H5T_t *t, int mode) -{ - return no_operation(t, mode); -} /*------------------------------------------------------------------------- * Function: main @@ -7860,11 +7837,6 @@ main(void) { long nerrors = 0; hid_t fapl = -1; - H5T_t *t; - int i, ntimes = 100 * 1000 * 1000; - uint64_t start, stop; - typedef herr_t (*fn_t)(H5T_t *, int); - volatile fn_t fn = no_operation; /* Set the random # seed */ HDsrandom((unsigned)HDtime(NULL)); @@ -7875,36 +7847,6 @@ main(void) if(ALIGNMENT) printf("Testing non-aligned conversions (ALIGNMENT=%d)....\n", ALIGNMENT); - t = (H5T_t *)H5I_object(H5T_NATIVE_SHORT); - if (t == NULL) abort(); - - fn = no_operation; - start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) { - (*fn)(t, 10); - } - stop = __builtin_ia32_rdtsc(); - printf("%d calls to %11s routine, %" PRIu64 " cycles\n", - ntimes, "no-op", stop - start); - - fn = H5T__forward_args_without_func_overhead; - start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) { - (*fn)(t, 10); - } - stop = __builtin_ia32_rdtsc(); - printf("%d calls to %11s version, %" PRIu64 " cycles\n", - ntimes, "no-overhead", stop - start); - - fn = H5T__forward_args_with_func_overhead; - start = __builtin_ia32_rdtsc(); - for (i = 0; i < ntimes; i++) { - (*fn)(t, 10); - } - stop = __builtin_ia32_rdtsc(); - printf("%d calls to %11s version, %" PRIu64 " cycles\n", - ntimes, "overhead", stop - start); - /* Do the tests */ nerrors += test_classes(); nerrors += test_copy(); diff --git a/test/nop.c b/test/nop.c deleted file mode 100644 index 4829eb9..0000000 --- a/test/nop.c +++ /dev/null @@ -1,29 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 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. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "testhdf5.h" -#include "H5srcdir.h" -#include "H5Iprivate.h" /* For checking that datatype id's don't leak */ - -#define H5T_FRIEND /*suppress error about including H5Tpkg */ -#include "H5Tpkg.h" - -herr_t no_operation(H5T_t *t, int mode); - -herr_t -no_operation(H5T_t *t, int mode) -{ - static int ncalls = 0; - ncalls++; - return SUCCEED; -} -- cgit v0.12