diff options
author | jhendersonHDF <jhenderson@hdfgroup.org> | 2024-03-10 07:47:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-10 07:47:31 (GMT) |
commit | ef401a5f5edf2fc689334a485a6c2ec3f53ecb85 (patch) | |
tree | 4807deea31bdb83a5f3903f9dc3fddd48a1e0785 /src/H5T.c | |
parent | 28aaeb967ce66477441dc1f92fc45dddb51255c2 (diff) | |
download | hdf5-ef401a5f5edf2fc689334a485a6c2ec3f53ecb85.zip hdf5-ef401a5f5edf2fc689334a485a6c2ec3f53ecb85.tar.gz hdf5-ef401a5f5edf2fc689334a485a6c2ec3f53ecb85.tar.bz2 |
Refactor datatype conversion code to use pointers rather than IDs (#4104)
The datatype conversion code previously used IDs for the source and
destination datatypes rather than pointers to the internal structures
for those datatypes. This was mostly due to the need for an ID for these
datatypes that can be passed to an application-registered datatype
conversion function or datatype conversion exception function. However,
using IDs internally caused a lot of unnecessary ID lookups and hurt
performance of datatype conversions in general. This was especially
problematic for compound datatype conversions, where the ID lookups were
occuring on every member of every compound element of a dataset. The
code has now been refactored to use pointers internally and only create
IDs for datatypes when necessary.
Fixed a test issue in dt_arith where a library datatype conversion
function was being cast to an application conversion function. Since the
two have different prototypes, this started failing after the parameters
for a library conversion function changed from hid_t to H5T_t * and an
extra parameter was added. This appears to have worked coincidentally in
the past since the only different between a library conversion function
and application conversion function was an extra DXPL parameter at the
end of an application conversion function
Fixed an issue where memory wasn't being freed in the h5fc_chk_idx test
program. Even though the program exits quickly after allocating the
memory, it still causes failures when testing with -fsanitize=address
Diffstat (limited to 'src/H5T.c')
-rw-r--r-- | src/H5T.c | 372 |
1 files changed, 281 insertions, 91 deletions
@@ -1499,8 +1499,8 @@ H5T_top_term_package(void) } /* end if */ } /* end if */ else { - if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, - (size_t)0, (size_t)0, NULL, NULL) < 0) { + if ((path->conv.u.lib_func)(NULL, NULL, &(path->cdata), NULL, (size_t)0, (size_t)0, + (size_t)0, NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf(H5DEBUG(T), @@ -2457,13 +2457,16 @@ done: static herr_t H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_func_t *conv) { - hid_t tmp_sid = -1, tmp_did = -1; /*temporary data type IDs */ - H5T_path_t *old_path = NULL; /*existing conversion path */ - H5T_path_t *new_path = NULL; /*new conversion path */ - H5T_cdata_t cdata; /*temporary conversion data */ - int nprint = 0; /*number of paths shut down */ - int i; /*counter */ - herr_t ret_value = SUCCEED; /*return value */ + H5T_path_t *old_path = NULL; /*existing conversion path */ + H5T_path_t *new_path = NULL; /*new conversion path */ + H5T_cdata_t cdata; /*temporary conversion data */ + H5T_t *tmp_stype = NULL; /*temporary source datatype */ + H5T_t *tmp_dtype = NULL; /*temporary destination datatype */ + hid_t tmp_sid = H5I_INVALID_HID; /*temporary datatype ID */ + hid_t tmp_did = H5I_INVALID_HID; /*temporary datatype ID */ + int nprint = 0; /*number of paths shut down */ + int i; /*counter */ + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_PACKAGE @@ -2524,27 +2527,36 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con old_path->dst->shared->type != dst->shared->type) continue; - if ((tmp_sid = H5I_register(H5I_DATATYPE, H5T_copy(old_path->src, H5T_COPY_ALL), false)) < 0 || - (tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL), false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "unable to register data types for conv query"); + if (NULL == (tmp_stype = H5T_copy(old_path->src, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy src datatype"); + if (NULL == (tmp_dtype = H5T_copy(old_path->dst, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy dst datatype"); + memset(&cdata, 0, sizeof cdata); cdata.command = H5T_CONV_INIT; if (conv->is_app) { + if ((tmp_sid = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for source datatype"); + if ((tmp_did = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for destination datatype"); + if ((conv->u.app_func)(tmp_sid, tmp_did, &cdata, (size_t)0, (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) { H5I_dec_ref(tmp_sid); H5I_dec_ref(tmp_did); - tmp_sid = tmp_did = -1; + tmp_sid = tmp_did = H5I_INVALID_HID; + tmp_stype = tmp_dtype = NULL; H5E_clear_stack(NULL); continue; } /* end if */ } /* end if */ - else if ((conv->u.lib_func)(tmp_sid, tmp_did, &cdata, (size_t)0, (size_t)0, (size_t)0, NULL, - NULL) < 0) { - H5I_dec_ref(tmp_sid); - H5I_dec_ref(tmp_did); - tmp_sid = tmp_did = -1; + else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &cdata, NULL, (size_t)0, (size_t)0, (size_t)0, + NULL, NULL) < 0) { + H5T_close(tmp_stype); + H5T_close(tmp_dtype); + tmp_stype = tmp_dtype = NULL; H5E_clear_stack(NULL); continue; } /* end if */ @@ -2580,8 +2592,8 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con #endif } /* end if */ } /* end if */ - else if ((old_path->conv.u.lib_func)(tmp_sid, tmp_did, &(old_path->cdata), (size_t)0, (size_t)0, - (size_t)0, NULL, NULL) < 0) { + else if ((old_path->conv.u.lib_func)(tmp_stype, tmp_dtype, &(old_path->cdata), NULL, (size_t)0, + (size_t)0, (size_t)0, NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) fprintf(H5DEBUG(T), @@ -2595,9 +2607,28 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con old_path = H5FL_FREE(H5T_path_t, old_path); /* Release temporary atoms */ - H5I_dec_ref(tmp_sid); - H5I_dec_ref(tmp_did); - tmp_sid = tmp_did = -1; + if (tmp_sid >= 0) { + if (H5I_dec_ref(tmp_sid) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID"); + tmp_sid = H5I_INVALID_HID; + tmp_stype = NULL; + } + else if (tmp_stype) { + if (H5T_close(tmp_stype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); + tmp_stype = NULL; + } + if (tmp_did >= 0) { + if (H5I_dec_ref(tmp_did) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID"); + tmp_did = H5I_INVALID_HID; + tmp_dtype = NULL; + } + else if (tmp_dtype) { + if (H5T_close(tmp_dtype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); + tmp_dtype = NULL; + } /* We don't care about any failures during the freeing process */ H5E_clear_stack(NULL); @@ -2613,11 +2644,24 @@ done: (void)H5T_close_real(new_path->dst); new_path = H5FL_FREE(H5T_path_t, new_path); } /* end if */ - if (tmp_sid >= 0) - H5I_dec_ref(tmp_sid); - if (tmp_did >= 0) - H5I_dec_ref(tmp_did); - } /* end if */ + } /* end if */ + + if (tmp_sid >= 0) { + if (H5I_dec_ref(tmp_sid) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID"); + } + else if (tmp_stype) { + if (H5T_close(tmp_stype) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); + } + if (tmp_did >= 0) { + if (H5I_dec_ref(tmp_did) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID"); + } + else if (tmp_dtype) { + if (H5T_close(tmp_dtype) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__register() */ @@ -2770,7 +2814,7 @@ H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5VL_o #endif } /* end if */ } /* end if */ - else if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, (size_t)0, + else if ((path->conv.u.lib_func)(NULL, NULL, &(path->cdata), NULL, (size_t)0, (size_t)0, (size_t)0, NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) @@ -2953,7 +2997,7 @@ H5Tconvert(hid_t src_id, hid_t dst_id, size_t nelmts, void *buf, void *backgroun if (NULL == (tpath = H5T_path_find(src, dst))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst data types"); - if (H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, buf, background) < 0) + if (H5T_convert(tpath, src, dst, nelmts, (size_t)0, (size_t)0, buf, background) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); done: @@ -2975,6 +3019,7 @@ done: herr_t H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf) { + H5T_t *type; H5S_t *space; /* Dataspace for iteration */ herr_t ret_value; /* Return value */ @@ -2982,8 +3027,10 @@ H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf) H5TRACE4("e", "iii*x", type_id, space_id, dxpl_id, buf); /* Check args */ - if (H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument"); + if (buf == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "'buf' pointer is NULL"); + if (NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype"); 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))) @@ -2999,7 +3046,7 @@ H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf) H5CX_set_dxpl(dxpl_id); /* Call internal routine */ - ret_value = H5T_reclaim(type_id, space, buf); + ret_value = H5T_reclaim(type, space, buf); done: FUNC_LEAVE_API(ret_value) @@ -4877,16 +4924,19 @@ done: static H5T_path_t * H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv) { - int lt, rt; /* left and right edges */ - int md; /* middle */ - int cmp; /* comparison result */ - int old_npaths; /* Previous number of paths in table */ - H5T_path_t *table = NULL; /* path existing in the table */ - H5T_path_t *path = NULL; /* new path */ - hid_t src_id = -1, dst_id = -1; /* src and dst type identifiers */ - int i; /* counter */ - int nprint = 0; /* lines of output printed */ - H5T_path_t *ret_value = NULL; /* Return value */ + int lt, rt; /* left and right edges */ + int md; /* middle */ + int cmp; /* comparison result */ + int old_npaths; /* Previous number of paths in table */ + H5T_path_t *table = NULL; /* path existing in the table */ + H5T_path_t *path = NULL; /* new path */ + H5T_t *tmp_stype = NULL; /* temporary source datatype */ + H5T_t *tmp_dtype = NULL; /* temporary destination datatype */ + hid_t src_id = H5I_INVALID_HID; /* source datatype identifier */ + hid_t dst_id = H5I_INVALID_HID; /* destination datatype identifier */ + int i; /* counter */ + int nprint = 0; /* lines of output printed */ + H5T_path_t *ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE @@ -4911,8 +4961,8 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co H5T_g.path[0]->conv.is_app = false; H5T_g.path[0]->conv.u.lib_func = H5T__conv_noop; H5T_g.path[0]->cdata.command = H5T_CONV_INIT; - if (H5T__conv_noop((hid_t)FAIL, (hid_t)FAIL, &(H5T_g.path[0]->cdata), (size_t)0, (size_t)0, (size_t)0, - NULL, NULL) < 0) { + if (H5T__conv_noop(NULL, NULL, &(H5T_g.path[0]->cdata), NULL, (size_t)0, (size_t)0, (size_t)0, NULL, + NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) fprintf(H5DEBUG(T), "H5T: unable to initialize no-op conversion function (ignored)\n"); @@ -4994,28 +5044,53 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co (!table || (table && conv->is_app) || (table && !table->is_hard && !conv->is_app))) { assert(path != table); assert(NULL == path->conv.u.app_func); - if (path->src && (src_id = H5I_register(H5I_DATATYPE, H5T_copy(path->src, H5T_COPY_ALL), false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, - "unable to register source conversion type for query"); - if (path->dst && (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(path->dst, H5T_COPY_ALL), false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, - "unable to register destination conversion type for query"); + if (path->src && (NULL == (tmp_stype = H5T_copy(path->src, H5T_COPY_ALL)))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy source datatype"); + if (path->dst && (NULL == (tmp_dtype = H5T_copy(path->dst, H5T_COPY_ALL)))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy destination datatype"); + path->cdata.command = H5T_CONV_INIT; if (conv->is_app) { + if (tmp_stype && ((src_id = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, + "unable to register ID for source datatype"); + if (tmp_dtype && ((dst_id = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, + "unable to register ID for destination datatype"); + if ((conv->u.app_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function"); } /* end if */ - else if ((conv->u.lib_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, - NULL) < 0) + else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), NULL, (size_t)0, (size_t)0, + (size_t)0, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function"); - if (src_id >= 0) - H5I_dec_ref(src_id); - if (dst_id >= 0) - H5I_dec_ref(dst_id); - src_id = dst_id = -1; - path->conv = *conv; - path->is_hard = true; + + if (src_id >= 0) { + if (H5I_dec_ref(src_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + src_id = H5I_INVALID_HID; + tmp_stype = NULL; + } + else if (tmp_stype) { + if (H5T_close(tmp_stype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + tmp_stype = NULL; + } + if (dst_id >= 0) { + if (H5I_dec_ref(dst_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + dst_id = H5I_INVALID_HID; + tmp_dtype = NULL; + } + else if (tmp_dtype) { + if (H5T_close(tmp_dtype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + tmp_dtype = NULL; + } + + path->conv = *conv; + path->is_hard = true; } /* end if */ /* @@ -5030,14 +5105,27 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co if (src->shared->type != H5T_g.soft[i].src || dst->shared->type != H5T_g.soft[i].dst) continue; - if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(path->src, H5T_COPY_ALL), false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, - "unable to register src conversion type for query"); - if ((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(path->dst, H5T_COPY_ALL), false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, - "unable to register dst conversion type for query"); + + assert(tmp_stype == NULL); + assert(tmp_dtype == NULL); + + if (NULL == (tmp_stype = H5T_copy(path->src, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy source datatype"); + if (NULL == (tmp_dtype = H5T_copy(path->dst, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy destination datatype"); + path->cdata.command = H5T_CONV_INIT; if (H5T_g.soft[i].conv.is_app) { + assert(src_id == H5I_INVALID_HID); + assert(dst_id == H5I_INVALID_HID); + + if ((src_id = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, + "unable to register ID for source datatype"); + if ((dst_id = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, + "unable to register ID for destination datatype"); + if ((H5T_g.soft[i].conv.u.app_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) { memset(&(path->cdata), 0, sizeof(H5T_cdata_t)); @@ -5045,8 +5133,8 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co path_init_error = true; } /* end if */ } /* end if */ - else if ((H5T_g.soft[i].conv.u.lib_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, - (size_t)0, NULL, NULL) < 0) { + else if ((H5T_g.soft[i].conv.u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), NULL, (size_t)0, + (size_t)0, (size_t)0, NULL, NULL) < 0) { memset(&(path->cdata), 0, sizeof(H5T_cdata_t)); H5E_clear_stack(NULL); /*ignore the error*/ path_init_error = true; @@ -5059,9 +5147,29 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co path->conv = H5T_g.soft[i].conv; path->is_hard = false; } /* end else */ - H5I_dec_ref(src_id); - H5I_dec_ref(dst_id); - src_id = dst_id = -1; + + if (src_id >= 0) { + if (H5I_dec_ref(src_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + src_id = H5I_INVALID_HID; + tmp_stype = NULL; + } + else if (tmp_stype) { + if (H5T_close(tmp_stype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + tmp_stype = NULL; + } + if (dst_id >= 0) { + if (H5I_dec_ref(dst_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + dst_id = H5I_INVALID_HID; + tmp_dtype = NULL; + } + else if (tmp_dtype) { + if (H5T_close(tmp_dtype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + tmp_dtype = NULL; + } } /* end for */ if (!path->conv.u.app_func) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no appropriate function for conversion path"); @@ -5105,8 +5213,8 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co H5E_clear_stack(NULL); /*ignore the failure*/ } /* end if */ } /* end if */ - else if ((table->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(table->cdata), (size_t)0, (size_t)0, - (size_t)0, NULL, NULL) < 0) { + else if ((table->conv.u.lib_func)(NULL, NULL, &(table->cdata), NULL, (size_t)0, (size_t)0, (size_t)0, + NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) fprintf(H5DEBUG(T), "H5T: conversion function 0x%016zx free failed for %s (ignored)\n", @@ -5160,10 +5268,23 @@ done: (void)H5T_close_real(path->dst); path = H5FL_FREE(H5T_path_t, path); } /* end if */ - if (src_id >= 0) - H5I_dec_ref(src_id); - if (dst_id >= 0) - H5I_dec_ref(dst_id); + + if (src_id >= 0) { + if (H5I_dec_ref(src_id) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + } + else if (tmp_stype) { + if (H5T_close(tmp_stype) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + } + if (dst_id >= 0) { + if (H5I_dec_ref(dst_id) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, NULL, "can't decrement reference on temporary ID"); + } + else if (tmp_dtype) { + if (H5T_close(tmp_dtype) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype"); + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__path_find_real() */ @@ -5403,13 +5524,16 @@ done: *------------------------------------------------------------------------- */ herr_t -H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, size_t nelmts, size_t buf_stride, +H5T_convert(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg) { + H5T_conv_ctx_t conv_ctx = {0}; #ifdef H5T_DEBUG - H5_timer_t timer; /* Timer for conversion */ + H5_timer_t timer = {0}; /* Timer for conversion */ #endif - herr_t ret_value = SUCCEED; /* Return value */ + hid_t src_type_id = H5I_INVALID_HID; + hid_t dst_type_id = H5I_INVALID_HID; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) @@ -5421,16 +5545,42 @@ H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, size_t nelmts, size_t } /* end if */ #endif - /* Call the appropriate conversion callback */ - tpath->cdata.command = H5T_CONV_CONV; - if (tpath->conv.is_app) { - if ((tpath->conv.u.app_func)(src_id, dst_id, &(tpath->cdata), nelmts, buf_stride, bkg_stride, buf, - bkg, H5CX_get_dxpl()) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); - } /* end if */ - else if ((tpath->conv.u.lib_func)(src_id, dst_id, &(tpath->cdata), nelmts, buf_stride, bkg_stride, buf, - bkg) < 0) + /* Get the datatype conversion exception callback structure from the API context */ + if (H5CX_get_dt_conv_cb(&conv_ctx.cb_struct) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + + /* + * If this is an application conversion function or an exception callback + * function was supplied, register IDs for the datatypes so we can pass + * those as appropriate. Also grab the DXPL if necessary so we can pass + * that to the app conversion function. + */ + if (tpath->conv.is_app || conv_ctx.cb_struct.func) { + if ((src_type_id = H5I_register(H5I_DATATYPE, src_type, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register ID for source datatype"); + if ((dst_type_id = H5I_register(H5I_DATATYPE, dst_type, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for destination datatype"); + + if (tpath->conv.is_app) + conv_ctx.dxpl_id = H5CX_get_dxpl(); + } + conv_ctx.src_type_id = src_type_id; + conv_ctx.dst_type_id = dst_type_id; + + if (H5T_convert_with_ctx(tpath, src_type, dst_type, &conv_ctx, nelmts, buf_stride, bkg_stride, buf, bkg) < + 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); + +done: + /* Remove IDs, but don't decrement their reference counts, as they + * could have been registered for datatypes that weren't copied + */ + if ((src_type_id >= 0) && (NULL == H5I_remove(src_type_id))) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't decrement temporary datatype ID"); + if ((dst_type_id >= 0) && (NULL == H5I_remove(dst_type_id))) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't decrement temporary datatype ID"); + #ifdef H5T_DEBUG if (H5DEBUG(T)) { /* Stop timer */ @@ -5445,11 +5595,51 @@ H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, size_t nelmts, size_t } /* end if */ #endif -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_convert() */ /*------------------------------------------------------------------------- + * Function: H5T_convert_with_ctx + * + * Purpose: Helper routine for H5T_convert that accepts a pointer to a + * H5T_conv_ctx_t conversion context structure. Useful for + * conversion routines involving container datatypes, such as + * compounds, where the conversion context structure that was + * setup during the initial H5T_convert call can be reused. + * This avoids the expensive and unnecessary overhead of + * recreating this structure and possibly re-registering IDs for + * the source and destination datatypes for every single member + * of the container datatype and every single element being + * converted that consists of that container datatype. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_convert_with_ctx(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Call the appropriate conversion callback */ + tpath->cdata.command = H5T_CONV_CONV; + if (tpath->conv.is_app) { + if ((tpath->conv.u.app_func)(conv_ctx->src_type_id, conv_ctx->dst_type_id, &(tpath->cdata), nelmts, + buf_stride, bkg_stride, buf, bkg, conv_ctx->dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); + } /* end if */ + else if ((tpath->conv.u.lib_func)(src_type, dst_type, &(tpath->cdata), conv_ctx, nelmts, buf_stride, + bkg_stride, buf, bkg) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_convert_with_ctx() */ + +/*------------------------------------------------------------------------- * Function: H5T_oloc * * Purpose: Returns a pointer to the object location for a named datatype. |