From b67a1b0817a131481d18429f6fb780393195b196 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Wed, 31 Jan 2024 10:35:32 -0600 Subject: [PATCH] Do subset write through H5Tpack + H5Tconvert --- src/rest_vol.h | 28 +--- src/rest_vol_dataset.c | 291 ++++++++++++---------------------------- src/rest_vol_datatype.c | 2 +- 3 files changed, 94 insertions(+), 227 deletions(-) diff --git a/src/rest_vol.h b/src/rest_vol.h index 29d0e78a..82931b98 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -451,22 +451,6 @@ typedef enum { H5T_SUBSET_CAP /* Must be the last value */ } RV_subset_t; -/* Information about members of a compound type for subsetting */ -typedef struct RV_compound_info_t { - RV_subset_t subset_info; /* Subset relationship between src and dst */ - - int nmembers; /* Number of offset/length pairs in the subset */ - int nalloc; /* Number of offset/length pairs allocated */ - size_t full_type_size; /* Size of compound type with all fields */ - - size_t *src_offsets; /* Offsets of fields within source datatype */ - size_t *lengths; /* Lengths of members (in both datatypes) */ - - size_t subset_buf_size; - void *subset_buf; - void *subset_ptr; /* Pointer for writing into the subset buffer */ -} RV_compound_info_t; - /* * A struct which is used to return a link's name or the size of * a link's name when calling H5Lget_name_by_idx. @@ -600,6 +584,10 @@ typedef struct dataset_write_info { char *base64_encoded_values; curl_off_t write_len; upload_info uinfo; + + /* If writing using compound subsetting, this is a packed version of the + * compound type containing only the selected members */ + hid_t dense_cmpd_subset_dtype_id; } dataset_write_info; typedef struct dataset_read_info { @@ -631,9 +619,6 @@ typedef struct dataset_transfer_info { void *tconv_buf; void *bkg_buf; - /* Fields for writing to subsets of compound types */ - RV_compound_info_t compound_info; - transfer_type_t transfer_type; union { @@ -795,11 +780,10 @@ herr_t RV_convert_datatype_to_JSON(hid_t type_id, char **type_body, size_t *type herr_t RV_JSON_escape_string(const char *in, char *out, size_t *out_size); /* Determine if a read from file to mem dtype is a compound subset read */ -herr_t RV_get_compound_subset_info(hid_t src_type_id, hid_t dst_type_id, RV_subset_t *subset_info); +herr_t RV_get_cmpd_subset_type(hid_t src_type_id, hid_t dst_type_id, RV_subset_t *subset_info); /* Helper to get information about members in dst that are included in src compound */ -herr_t RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, - RV_compound_info_t *compound_info); +herr_t RV_get_cmpd_subset_nmembers(hid_t src_type_id, hid_t dst_type_id, size_t *num_cmpd_members); #define SERVER_VERSION_MATCHES_OR_EXCEEDS(version, major_needed, minor_needed, patch_needed) \ (version.major > major_needed) || (version.major == major_needed && version.minor > minor_needed) || \ diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index f56298f6..d1c580da 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -59,9 +59,6 @@ static herr_t rv_dataset_read_cb(hid_t mem_type_id, hid_t mem_space_id, hid_t fi static herr_t rv_dataset_write_cb(hid_t mem_type_id, hid_t mem_space_id, hid_t file_type_id, hid_t file_space_id, void *buf, struct response_buffer resp_buffer); -/* H5Dgather callback that packs selected compound type members from dst buf into a buffer */ -herr_t RV_gather_compound_subset_cb(const void *dst_buf, size_t dst_buf_bytes_used, void *op_data); - /* Struct for H5Dscatter's callback that allows it to scatter from a non-global response buffer */ struct response_read_info { void *buffer; @@ -887,8 +884,6 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa char cmpd_query[URL_MAX_LENGTH]; char *member_name = NULL; char *url_encoded_member_name = NULL; - void *gather_buffer = NULL; - int num_cmpd_members = 0; if ((transfer_info = RV_calloc(count * sizeof(dataset_transfer_info))) == NULL) FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate space for dataset transfer info"); @@ -941,26 +936,18 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa transfer_info[i].buf = (void *)buf[i]; transfer_info[i].transfer_type = WRITE; - transfer_info[i].mem_space_id = _mem_space_id[i]; - transfer_info[i].file_space_id = _file_space_id[i]; - transfer_info[i].mem_type_id = mem_type_id[i]; - transfer_info[i].file_type_id = ((RV_object_t *)dset[i])->u.dataset.dtype_id; - transfer_info[i].curl_headers = NULL; - transfer_info[i].host_headers = NULL; - transfer_info[i].resp_buffer.buffer_size = CURL_RESPONSE_BUFFER_DEFAULT_SIZE; - transfer_info[i].resp_buffer.curr_buf_ptr = transfer_info[i].resp_buffer.buffer; - transfer_info[i].tconv_buf = NULL; - transfer_info[i].bkg_buf = NULL; - transfer_info[i].compound_info.subset_info = H5T_SUBSET_BADVALUE; - - transfer_info[i].compound_info.nalloc = 0; - transfer_info[i].compound_info.nmembers = 0; - transfer_info[i].compound_info.src_offsets = NULL; - transfer_info[i].compound_info.lengths = NULL; - transfer_info[i].compound_info.subset_buf = NULL; - transfer_info[i].compound_info.subset_buf_size = 0; - transfer_info[i].compound_info.subset_ptr = NULL; - transfer_info[i].compound_info.full_type_size = 0; + transfer_info[i].mem_space_id = _mem_space_id[i]; + transfer_info[i].file_space_id = _file_space_id[i]; + transfer_info[i].mem_type_id = mem_type_id[i]; + transfer_info[i].file_type_id = ((RV_object_t *)dset[i])->u.dataset.dtype_id; + transfer_info[i].curl_headers = NULL; + transfer_info[i].host_headers = NULL; + transfer_info[i].resp_buffer.buffer_size = CURL_RESPONSE_BUFFER_DEFAULT_SIZE; + transfer_info[i].resp_buffer.curr_buf_ptr = transfer_info[i].resp_buffer.buffer; + transfer_info[i].tconv_buf = NULL; + transfer_info[i].bkg_buf = NULL; + + transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id = H5I_INVALID_HID; } #ifdef RV_CONNECTOR_DEBUG @@ -983,6 +970,8 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa /* Iterate over datasets to write to */ for (size_t i = 0; i < count; i++) { + hbool_t is_compound_subset = FALSE; + size_t dense_dtype_size = 0; /* Determine whether it's possible to send the data as a binary blob instead of as JSON */ if (H5T_NO_CLASS == (dtype_class = H5Tget_class(transfer_info[i].mem_type_id))) @@ -1067,16 +1056,47 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa #ifdef RV_CONNECTOR_DEBUG printf("-> Beginning type conversion for write\n"); #endif + RV_subset_t subset_type = H5T_SUBSET_BADVALUE; + hid_t dest_dtype = H5I_INVALID_HID; + size_t dest_dtype_size = 0; + if ((file_type_size = H5Tget_size(transfer_info[i].file_type_id)) == 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "unable to get size of file datatype"); if ((mem_type_size = H5Tget_size(transfer_info[i].mem_type_id)) == 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "unable to get size of memory datatype"); + if ((RV_get_cmpd_subset_type(transfer_info[i].mem_type_id, transfer_info[i].file_type_id, + &subset_type)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, + "can't determine if write uses compound subsetting"); + + is_compound_subset = (subset_type == H5T_SUBSET_SRC); + + if (is_compound_subset) { + if ((transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id = + H5Tcopy(transfer_info[i].mem_type_id)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy compound datatype"); + + if ((H5Tpack(transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTPACK, FAIL, "can't pack compound datatype"); + + if ((dense_dtype_size = + H5Tget_size(transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id)) == 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dense dtype size"); + + dest_dtype = transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id; + dest_dtype_size = dense_dtype_size; + } + else { + dest_dtype = transfer_info[i].mem_type_id; + dest_dtype_size = mem_type_size; + } + /* Initialize type conversion */ - RV_tconv_init(transfer_info[i].mem_type_id, &mem_type_size, transfer_info[i].file_type_id, - &file_type_size, (size_t)file_select_npoints, TRUE, FALSE, - &transfer_info[i].tconv_buf, &transfer_info[i].bkg_buf, NULL, &fill_bkg); + RV_tconv_init(transfer_info[i].mem_type_id, &mem_type_size, dest_dtype, &dest_dtype_size, + (size_t)file_select_npoints, TRUE, FALSE, &transfer_info[i].tconv_buf, + &transfer_info[i].bkg_buf, NULL, &fill_bkg); /* Copy memory to avoid modifying user-provided write buffer */ memset(transfer_info[i].tconv_buf, 0, file_type_size * (size_t)mem_select_npoints); @@ -1084,7 +1104,9 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa mem_type_size * (size_t)mem_select_npoints); /* Perform type conversion on values to write */ - if (H5Tconvert(transfer_info[i].mem_type_id, transfer_info[i].file_type_id, + if (H5Tconvert(transfer_info[i].mem_type_id, + (is_compound_subset ? transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id + : transfer_info[i].file_type_id), (size_t)file_select_npoints, transfer_info[i].tconv_buf, transfer_info[i].bkg_buf, H5P_DEFAULT) < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, @@ -1097,106 +1119,29 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa * types like object references or variable length types) */ if ((H5T_REFERENCE != dtype_class) && (H5T_VLEN != dtype_class) && !is_variable_str) { - hid_t dest_dtype = H5I_INVALID_HID; - hbool_t is_compound_subset = FALSE; - size_t write_dtype_size = 0; - - if ((RV_get_compound_subset_info(transfer_info[i].mem_type_id, transfer_info[i].file_type_id, - &transfer_info[i].compound_info.subset_info)) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "can't determine if write uses compound subsetting"); - - is_compound_subset = (transfer_info[i].compound_info.subset_info == H5T_SUBSET_SRC); - - dest_dtype = is_compound_subset ? transfer_info[i].mem_type_id : transfer_info[i].file_type_id; + size_t write_dtype_size = 0; if (!is_compound_subset) { - if (0 == (write_dtype_size = H5Tget_size(dest_dtype))) + if (0 == (write_dtype_size = H5Tget_size(transfer_info[i].file_type_id))) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "file datatype is invalid"); } else { - /* If compound subset write, size of written dtype is the sum of its member sizes */ - transfer_info[i].compound_info.nmembers = 0; - - if ((num_cmpd_members = H5Tget_nmembers(transfer_info[i].mem_type_id)) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "can't get num members in compound datatype"); - - transfer_info[i].compound_info.nalloc = num_cmpd_members; - - if ((transfer_info[i].compound_info.lengths = - RV_calloc(sizeof(size_t) * (size_t)num_cmpd_members)) == NULL) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "can't allocate memory for compound info"); - - if ((transfer_info[i].compound_info.src_offsets = - RV_calloc(sizeof(size_t) * (size_t)num_cmpd_members)) == NULL) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "can't allocate memory for compound info"); - - if (RV_get_compound_subset_members(transfer_info[i].mem_type_id, - transfer_info[i].file_type_id, - &transfer_info[i].compound_info) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "can't get members included in compound subset"); - - for (size_t ii = 0; ii < num_cmpd_members; ii++) { - write_dtype_size += transfer_info[i].compound_info.lengths[ii]; - } + write_dtype_size = dense_dtype_size; } write_body_len = (size_t)file_select_npoints * write_dtype_size; - if ((is_write_contiguous = RV_dataspace_selection_is_contiguous(transfer_info[i].mem_space_id)) < 0) FUNC_GOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "Unable to determine if the dataspace selection is contiguous"); - - is_write_contiguous = (is_compound_subset) ? FALSE : is_write_contiguous; - if (!is_write_contiguous) { if (NULL == (transfer_info[i].u.write_info.write_body = (char *)RV_malloc(write_body_len))) FUNC_GOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate space for the 'write_body' values"); - - if (is_compound_subset) { - transfer_info[i].compound_info.full_type_size = file_type_size; - transfer_info[i].compound_info.subset_buf_size = - write_dtype_size * (size_t)file_select_npoints; - - /* Temp buffer for each iteration of gather callback */ - if ((gather_buffer = RV_calloc(file_type_size * (size_t)file_select_npoints)) == NULL) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, - "can't allocate memory for compound buffer"); - - /* Final buffer populated piecemeal by Gather callback */ - /* This may be freely modified, because compound subset implies that type conversion took - * place, so this points to the type conversion allocated buffer */ - transfer_info[i].compound_info.subset_buf = buf_to_write; - - transfer_info[i].compound_info.subset_ptr = transfer_info[i].compound_info.subset_buf; - /* Avoid using the same buffer as both the dst_buf for H5Dgather and the buffer populated - * by callback */ - memcpy(gather_buffer, buf_to_write, file_type_size * (size_t)file_select_npoints); - - if (H5Dgather(transfer_info[i].mem_space_id, gather_buffer, transfer_info[i].file_type_id, - file_type_size * (size_t)file_select_npoints, gather_buffer, - RV_gather_compound_subset_cb, (void *)&transfer_info[i].compound_info) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, - "can't gather data to write buffer for cmpd subset"); - - RV_free(gather_buffer); - gather_buffer = NULL; - } - else { - /* Not a compound subset */ - if (H5Dgather(transfer_info[i].mem_space_id, buf_to_write, transfer_info[i].file_type_id, - write_body_len, transfer_info[i].u.write_info.write_body, NULL, NULL) < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, - "can't gather data to write buffer"); - - buf_to_write = transfer_info[i].u.write_info.write_body; - } + if (H5Dgather(transfer_info[i].mem_space_id, buf_to_write, transfer_info[i].file_type_id, + write_body_len, transfer_info[i].u.write_info.write_body, NULL, NULL) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't gather data to write buffer"); + buf_to_write = transfer_info[i].u.write_info.write_body; } else { if ((offset = RV_convert_start_to_offset(transfer_info[i].mem_space_id)) < 0) @@ -1206,7 +1151,6 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa } } /* end if */ else { - if (H5T_STD_REF_OBJ == transfer_info[i].file_type_id) { /* Convert the buffer of rest_obj_ref_t's to a binary buffer */ if (RV_convert_obj_refs_to_buffer( @@ -1242,9 +1186,16 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa has_selection_body = is_transfer_binary && selection_body && (H5S_SEL_POINTS != sel_type); /* Redirect cURL from the base URL to "/datasets//value" to write the value out */ - if (transfer_info[i].compound_info.subset_info == H5T_SUBSET_SRC) { - char *cmpd_query_ptr = cmpd_query; - ptrdiff_t cmpd_query_len = 0; + if (is_compound_subset) { + char *cmpd_query_ptr = cmpd_query; + ptrdiff_t cmpd_query_len = 0; + size_t num_cmpd_members = 0; + + /* Retrieve compound information for request */ + if (RV_get_cmpd_subset_nmembers(transfer_info[i].mem_type_id, + transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id, + &num_cmpd_members) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get compound subset information"); /* Construct compound member selection string for request URL */ if (!(SERVER_VERSION_SUPPORTS_MEMBER_SELECTION( @@ -1266,16 +1217,16 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa memcpy(cmpd_query_ptr, COMPOUND_MEMBER_QUERY, strlen(COMPOUND_MEMBER_QUERY)); cmpd_query_ptr += strlen(COMPOUND_MEMBER_QUERY); - for (size_t j = 0; j < (size_t)num_cmpd_members; j++) { + for (size_t j = 0; j < num_cmpd_members; j++) { if ((member_name = H5Tget_member_name(transfer_info[i].mem_type_id, (unsigned)j)) == NULL) FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get name of compound member"); cmpd_query_len = cmpd_query_ptr - cmpd_query; /* URL encode the member name */ - if ((url_encoded_member_name = curl_easy_escape(curl, member_name, strlen(member_name))) == - NULL) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, NULL, + if ((url_encoded_member_name = + curl_easy_escape(curl, member_name, (int)strlen(member_name))) == NULL) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "can't URL-encode compound member name"); if ((size_t)cmpd_query_len + strlen(url_encoded_member_name) + 1 > URL_MAX_LENGTH) @@ -1308,8 +1259,7 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa transfer_info[i].dataset->domain->u.file.server_info.base_URL, transfer_info[i].dataset->URI, has_selection_body ? "?select=" : "", has_selection_body ? selection_body : "", - (transfer_info[i].compound_info.subset_info == H5T_SUBSET_SRC) ? cmpd_query - : "") < 0)) + is_compound_subset ? cmpd_query : "") < 0)) FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1471,14 +1421,8 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa if (transfer_info[i].host_headers) RV_free(transfer_info[i].host_headers); - if (gather_buffer) - RV_free(gather_buffer); - - if (transfer_info[i].compound_info.src_offsets) - RV_free(transfer_info[i].compound_info.src_offsets); - - if (transfer_info[i].compound_info.lengths) - RV_free(transfer_info[i].compound_info.lengths); + if (transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id != H5I_INVALID_HID) + H5Tclose(transfer_info[i].u.write_info.dense_cmpd_subset_dtype_id); } curl_multi_cleanup(curl_multi_handle); @@ -1492,9 +1436,6 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa if (H5free_memory((void *)member_name) < 0) FUNC_DONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't free datatype member name"); - if (gather_buffer) - RV_free(gather_buffer); - PRINT_ERROR_STACK; return ret_value; @@ -4740,7 +4681,7 @@ rv_dataset_read_cb(hid_t mem_type_id, hid_t mem_space_id, hid_t file_type_id, hi RV_tconv_reuse_t reuse = RV_TCONV_REUSE_NONE; hbool_t fill_bkg = FALSE; - RV_subset_t subset_info; + RV_subset_t subset_type = H5T_SUBSET_BADVALUE; if (H5T_NO_CLASS == (dtype_class = H5Tget_class(mem_type_id))) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "memory datatype is invalid"); @@ -4797,14 +4738,14 @@ rv_dataset_read_cb(hid_t mem_type_id, hid_t mem_space_id, hid_t file_type_id, hi (size_t)file_select_npoints, TRUE, FALSE, &tconv_buf, &bkg_buf, &reuse, &fill_bkg); /* Handle compound subsetting */ - if (RV_get_compound_subset_info(file_type_id, mem_type_id, &subset_info) < 0) + if (RV_get_cmpd_subset_type(file_type_id, mem_type_id, &subset_type) < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get compound type subset info"); - if (subset_info < 0) + if (subset_type < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "error while checking if types are compound subsets"); - if (subset_info == H5T_SUBSET_DST) { + if (subset_type == H5T_SUBSET_DST) { /* Populate background buffer with bytes from user input buffer */ if (!bkg_buf || !fill_bkg) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, @@ -5252,11 +5193,9 @@ RV_json_values_to_binary_recursive(yajl_val value_entry, hid_t dtype_id, void *v return ret_value; } -/* Get the offsets and lengths of the compound type members in both destination and source type. - Requires compound_info->src_offsets and compound_info->lengths to be allocated ahead of time, - with the number of allocated slots specified in compound_info->nalloc. */ +/* Get the amount of compound type members in both destination and source type */ herr_t -RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, RV_compound_info_t *compound_info) +RV_get_cmpd_subset_nmembers(hid_t src_type_id, hid_t dst_type_id, size_t *num_cmpd_members) { herr_t ret_value = SUCCEED; H5T_class_t dst_type_class = H5T_NO_CLASS, src_type_class = H5T_NO_CLASS; @@ -5268,8 +5207,8 @@ RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, RV_compound size_t dst_member_offset = 0, src_member_offset = 0; size_t member_size = 0; - if (!compound_info) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "provided compound info struct is NULL"); + if (!num_cmpd_members) + FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "provided output pointer is NULL"); if (H5T_NO_CLASS == (src_type_class = H5Tget_class(src_type_id))) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "source datatype is invalid"); @@ -5286,10 +5225,7 @@ RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, RV_compound if ((src_nmembs = H5Tget_nmembers(src_type_id)) < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get nmembers of source datatype"); - if (src_nmembs > compound_info->nalloc) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "not enough space in compound info"); - - // TODO - Optimize this + /* Iterate and check which members have matching name, type, and offset between the datatypes */ for (unsigned int dst_idx = 0; dst_idx < dst_nmembs; dst_idx++) { match_for_dst_member = false; src_member_offset = 0; @@ -5327,25 +5263,13 @@ RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, RV_compound src_member_name = NULL; + /* This dst member has a match - no need to look through other src members */ if (match_for_dst_member) break; } - /* If member in dst type is included by subsetting, copy its offset and length */ - if (match_for_dst_member) { - dst_member_offset = H5Tget_member_offset(dst_type_id, dst_idx); - - if ((member_size = H5Tget_size(dst_member_type)) == 0) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, - "can't get size of destination datatype member"); - - if (compound_info->nmembers >= compound_info->nalloc) - FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "compound info struct is full"); - - compound_info->src_offsets[compound_info->nmembers] = src_member_offset; - compound_info->lengths[compound_info->nmembers] = member_size; - compound_info->nmembers++; - } + if (match_for_dst_member) + (*num_cmpd_members)++; if (H5Tclose(dst_member_type) < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close destination datatype member"); @@ -5382,45 +5306,4 @@ RV_get_compound_subset_members(hid_t src_type_id, hid_t dst_type_id, RV_compound FUNC_DONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close destination datatype member"); return ret_value; -} - -/* H5Dgather callback that packs selected compound type members from dst buf into a buffer */ -herr_t -RV_gather_compound_subset_cb(const void *dst_buf, size_t dst_buf_bytes_used, void *op_data) -{ - - RV_compound_info_t *cinfo = (RV_compound_info_t *)op_data; - - herr_t ret_value = H5_ITER_CONT; - size_t num_elems = 0; - - if (dst_buf_bytes_used % cinfo->full_type_size != 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_BADVALUE, H5_ITER_STOP, - "provided buffer does not contain multiple of type size bytes"); - - num_elems = (dst_buf_bytes_used / cinfo->full_type_size); - - for (size_t elem_idx = 0; elem_idx < num_elems; elem_idx++) { - const void *src_elem = (const char *)dst_buf + elem_idx * cinfo->full_type_size; - - for (size_t member_idx = 0; member_idx < cinfo->nmembers; member_idx++) { - const void *src_member = (const char *)src_elem + cinfo->src_offsets[member_idx]; - ptrdiff_t subset_bytes_used = 0; - - subset_bytes_used = (char *)cinfo->subset_ptr - (char *)cinfo->subset_buf; - - if (subset_bytes_used < 0) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_INTERNAL, FAIL, "invalid subset buffer pointer"); - - if ((size_t)subset_bytes_used + cinfo->lengths[member_idx] > cinfo->subset_buf_size) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, - "compound subset members too large for buffer"); - - memcpy(cinfo->subset_ptr, src_member, cinfo->lengths[member_idx]); - cinfo->subset_ptr = (void *)((char *)cinfo->subset_ptr + cinfo->lengths[member_idx]); - } - } - -done: - return (ret_value); } \ No newline at end of file diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index c11b061c..86fae095 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -2641,7 +2641,7 @@ RV_tconv_init(hid_t src_type_id, size_t *src_type_size, hid_t dst_type_id, size_ /* Determine the subset relationsip (if any) between src and dst datatypes */ herr_t -RV_get_compound_subset_info(hid_t src_type_id, hid_t dst_type_id, RV_subset_t *subset) +RV_get_cmpd_subset_type(hid_t src_type_id, hid_t dst_type_id, RV_subset_t *subset) { herr_t ret_value = SUCCEED; H5T_class_t dst_type_class = H5T_NO_CLASS, src_type_class = H5T_NO_CLASS;