diff options
author | Larry Knox <lrknox@hdfgroup.org> | 2023-08-08 16:06:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-08 16:06:05 (GMT) |
commit | f43d301f633b5e2cd9cde160ddb2c13578f9231f (patch) | |
tree | 3c05bb6a52a5cb19869721dab02e4931f6e48e39 /src/H5FDint.c | |
parent | 8ceb226bae916152510387da6f7f9710903882a8 (diff) | |
download | hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.zip hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.tar.gz hdf5-f43d301f633b5e2cd9cde160ddb2c13578f9231f.tar.bz2 |
Merge Implementation of the mpio driver with selection I/O. (#3360)
Diffstat (limited to 'src/H5FDint.c')
-rw-r--r-- | src/H5FDint.c | 700 |
1 files changed, 583 insertions, 117 deletions
diff --git a/src/H5FDint.c b/src/H5FDint.c index 65b1424..fcc1b6c 100644 --- a/src/H5FDint.c +++ b/src/H5FDint.c @@ -62,17 +62,17 @@ /************************************************************************* * - * H5FD_vsrt_tmp_t + * H5FD_srt_tmp_t * - * Structure used to store vector I/O request addresses and the associated + * Structure used to store I/O request addresses and the associated * indexes in the addrs[] array for the purpose of determine the sorted * order. * - * This is done by allocating an array of H5FD_vsrt_tmp_t of length + * This is done by allocating an array of H5FD_srt_tmp_t of length * count, loading it with the contents of the addrs[] array and the * associated indices, and then sorting it. * - * This sorted array of H5FD_vsrt_tmp_t is then used to populate sorted + * This sorted array of H5FD_srt_tmp_t is then used to populate sorted * versions of the types[], addrs[], sizes[] and bufs[] vectors. * * addr: haddr_t containing the value of addrs[i], @@ -82,10 +82,10 @@ * *************************************************************************/ -typedef struct H5FD_vsrt_tmp_t { +typedef struct H5FD_srt_tmp_t { haddr_t addr; size_t index; -} H5FD_vsrt_tmp_t; +} H5FD_srt_tmp_t; /* Information needed for iterating over the registered VFD hid_t IDs. * The name or value of the new VFD that is being registered is stored @@ -109,12 +109,14 @@ typedef struct H5FD_get_driver_ud_t { /* Local Prototypes */ /********************/ static int H5FD__get_driver_cb(void *obj, hid_t id, void *_op_data); -static herr_t H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, - H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], - size_t element_sizes[], void *bufs[] /* out */); -static herr_t H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, - H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], - size_t element_sizes[], const void *bufs[]); +static herr_t H5FD__read_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, + hid_t dxpl_id, uint32_t count, H5S_t **mem_spaces, + H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], + void *bufs[] /* out */); +static herr_t H5FD__write_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, + hid_t dxpl_id, uint32_t count, H5S_t **mem_spaces, + H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], + const void *bufs[]); /*********************/ /* Package Variables */ @@ -734,8 +736,8 @@ done: * Function: H5FD__read_selection_translate * * Purpose: Translates a selection read call to a vector read call if - * vector reads are supported, or a series of scalar read - * calls otherwise. + * vector reads are supported and !skip_vector_cb, + * or a series of scalar read calls otherwise. * * Return: Success: SUCCEED * All reads have completed successfully, and @@ -748,8 +750,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, - H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], +H5FD__read_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, + uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) { hbool_t extend_sizes = FALSE; @@ -797,7 +799,7 @@ H5FD__read_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uin assert((bufs) || (count == 0)); /* Check if we're using vector I/O */ - use_vector = file->cls->read_vector != NULL; + use_vector = (file->cls->read_vector != NULL) && (!skip_vector_cb); if (count > 0) { /* Verify that the first elements of the element_sizes and bufs arrays are @@ -1063,8 +1065,8 @@ done: * If the underlying VFD supports selection reads, pass the * call through directly. * - * If it doesn't, convert the vector read into a sequence - * of individual reads. + * If it doesn't, convert the selection read into a sequence + * of vector or scalar reads. * * Return: Success: SUCCEED * All reads have completed successfully, and @@ -1189,8 +1191,8 @@ H5FD_read_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_s /* Otherwise, implement the selection read as a sequence of regular * or vector read calls. */ - if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, - element_sizes, bufs) < 0) + if (H5FD__read_selection_translate(SKIP_NO_CB, file, type, dxpl_id, count, mem_spaces, file_spaces, + offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed"); done: @@ -1228,6 +1230,15 @@ done: * Purpose: Like H5FD_read_selection(), but takes hid_t arrays instead * of H5S_t * arrays for the dataspaces. * + * Depending on the parameter skip_cb which is translated into + * skip_selection_cb and skip_vector_cb: + * + * --If the underlying VFD supports selection reads and !skip_selection_cb, + * pass the call through directly. + * + * --If it doesn't, convert the selection reads into a sequence of vector or + * scalar reads depending on skip_vector_cb. + * * Return: Success: SUCCEED * All reads have completed successfully, and * the results havce been into the supplied @@ -1239,7 +1250,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], +H5FD_read_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) { @@ -1250,6 +1261,8 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_ H5S_t **file_spaces = file_spaces_local; hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ uint32_t i; + uint32_t skip_selection_cb; + uint32_t skip_vector_cb; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1282,6 +1295,9 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_ } #endif /* H5_HAVE_PARALLEL */ + skip_selection_cb = skip_cb & SKIP_SELECTION_CB; + skip_vector_cb = skip_cb & SKIP_VECTOR_CB; + if (file->base_addr > 0) { /* apply the base_addr offset to the offsets array. Must undo before @@ -1320,7 +1336,7 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_ } /* if the underlying VFD supports selection read, make the call */ - if (file->cls->read_selection) { + if (!skip_selection_cb && file->cls->read_selection) { if ((file->cls->read_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read selection request failed"); @@ -1348,8 +1364,9 @@ H5FD_read_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_ } /* Translate to vector or scalar I/O */ - if (H5FD__read_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, - element_sizes, bufs) < 0) + + if (H5FD__read_selection_translate(skip_vector_cb, file, type, dxpl_id, count, mem_spaces, + file_spaces, offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "translation to vector or scalar read failed"); } @@ -1378,8 +1395,8 @@ done: * Function: H5FD__write_selection_translate * * Purpose: Translates a selection write call to a vector write call - * if vector writes are supported, or a series of scalar - * write calls otherwise. + * if vector writes are supported and !skip_vector_cb, + * or a series of scalar write calls otherwise. * * Return: Success: SUCCEED * All writes have completed successfully. @@ -1390,8 +1407,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, uint32_t count, - H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], +H5FD__write_selection_translate(uint32_t skip_vector_cb, H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, + uint32_t count, H5S_t **mem_spaces, H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], const void *bufs[]) { hbool_t extend_sizes = FALSE; @@ -1439,7 +1456,7 @@ H5FD__write_selection_translate(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, ui assert((bufs) || (count == 0)); /* Check if we're using vector I/O */ - use_vector = file->cls->write_vector != NULL; + use_vector = (file->cls->write_vector != NULL) && (!skip_vector_cb); if (count > 0) { /* Verify that the first elements of the element_sizes and bufs arrays are @@ -1705,8 +1722,8 @@ done: * If the underlying VFD supports selection writes, pass the * call through directly. * - * If it doesn't, convert the vector write into a sequence - * of individual writes. + * If it doesn't, convert the selection write into a sequence + * of vector or scalar writes. * * Return: Success: SUCCEED * All writes have completed successfully. @@ -1823,8 +1840,9 @@ H5FD_write_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, H5S_t **mem_ /* Otherwise, implement the selection write as a sequence of regular * or vector write calls. */ - if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, - element_sizes, bufs) < 0) + + if (H5FD__write_selection_translate(SKIP_NO_CB, file, type, dxpl_id, count, mem_spaces, file_spaces, + offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed"); done: @@ -1862,6 +1880,15 @@ done: * Purpose: Like H5FD_write_selection(), but takes hid_t arrays * instead of H5S_t * arrays for the dataspaces. * + * Depending on the parameter skip_cb which is translated into + * skip_selection_cb and skip_vector_cb: + * + * --If the underlying VFD supports selection writes and !skip_selection_cb, + * pass the call through directly. + * + * --If it doesn't, convert the selection writes into a sequence of vector or + * scalar reads depending on skip_vector_cb. + * * Return: Success: SUCCEED * All writes have completed successfully. * @@ -1871,8 +1898,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], - hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], const void *bufs[]) +H5FD_write_selection_id(uint32_t skip_cb, H5FD_t *file, H5FD_mem_t type, uint32_t count, + hid_t mem_space_ids[], hid_t file_space_ids[], haddr_t offsets[], + size_t element_sizes[], const void *bufs[]) { hbool_t offsets_cooked = FALSE; H5S_t *mem_spaces_local[H5FD_LOCAL_SEL_ARR_LEN]; @@ -1881,6 +1909,8 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem H5S_t **file_spaces = file_spaces_local; hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */ uint32_t i; + uint32_t skip_selection_cb; + uint32_t skip_vector_cb; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1913,6 +1943,9 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem } #endif /* H5_HAVE_PARALLEL */ + skip_selection_cb = skip_cb & SKIP_SELECTION_CB; + skip_vector_cb = skip_cb & SKIP_VECTOR_CB; + if (file->base_addr > 0) { /* apply the base_addr offset to the offsets array. Must undo before @@ -1945,7 +1978,7 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem } /* if the underlying VFD supports selection write, make the call */ - if (file->cls->write_selection) { + if (!skip_selection_cb && file->cls->write_selection) { if ((file->cls->write_selection)(file, type, dxpl_id, count, mem_space_ids, file_space_ids, offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write selection request failed"); @@ -1973,8 +2006,9 @@ H5FD_write_selection_id(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem } /* Translate to vector or scalar I/O */ - if (H5FD__write_selection_translate(file, type, dxpl_id, count, mem_spaces, file_spaces, offsets, - element_sizes, bufs) < 0) + + if (H5FD__write_selection_translate(skip_vector_cb, file, type, dxpl_id, count, mem_spaces, + file_spaces, offsets, element_sizes, bufs) < 0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "translation to vector or scalar write failed"); } @@ -2000,6 +2034,209 @@ done: } /* end H5FD_write_selection_id() */ /*------------------------------------------------------------------------- + * Function: H5FD_read_vector_from_selection + * + * Purpose: Internal routine for H5FDread_vector_from_selection() + * + * It will translate the selection read to a vector read call + * if vector reads are supported, or a series of scalar read + * calls otherwise. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + void *bufs[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + assert(file); + assert(file->cls); + assert((mem_space_ids) || (count == 0)); + assert((file_space_ids) || (count == 0)); + assert((offsets) || (count == 0)); + assert((element_sizes) || (count == 0)); + assert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + assert((count == 0) || (element_sizes[0] != 0)); + assert((count == 0) || (bufs[0] != NULL)); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_read_selection_id(SKIP_SELECTION_CB, file, type, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_read_vector_from_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_write_vector_from_selection + * + * Purpose: Internal routine for H5FDwrite_vector_from_selection() + * + * It will translate the selection write to a vector write call + * if vector writes are supported, or a series of scalar write + * calls otherwise. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write_vector_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + const void *bufs[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + assert(file); + assert(file->cls); + assert((mem_space_ids) || (count == 0)); + assert((file_space_ids) || (count == 0)); + assert((offsets) || (count == 0)); + assert((element_sizes) || (count == 0)); + assert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + assert((count == 0) || (element_sizes[0] != 0)); + assert((count == 0) || (bufs[0] != NULL)); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_write_selection_id(SKIP_SELECTION_CB, file, type, count, mem_space_ids, file_space_ids, offsets, + element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_write_vector_from_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_read_from_selection + * + * Purpose: Internal routine for H5FDread_from_selection() + * + * It will translate the selection read to a series of + * scalar read calls. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], void *bufs[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + assert(file); + assert(file->cls); + assert((mem_space_ids) || (count == 0)); + assert((file_space_ids) || (count == 0)); + assert((offsets) || (count == 0)); + assert((element_sizes) || (count == 0)); + assert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + assert((count == 0) || (element_sizes[0] != 0)); + assert((count == 0) || (bufs[0] != NULL)); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_read_selection_id(SKIP_SELECTION_CB | SKIP_VECTOR_CB, file, type, count, mem_space_ids, + file_space_ids, offsets, element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file selection read request failed"); + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_read_from_selection() */ + +/*------------------------------------------------------------------------- + * Function: H5FD_write_from_selection + * + * Purpose: Internal routine for H5FDwrite_from_selection() + * + * It will translate the selection write to a series of + * scalar write calls. + * + * Return: Success: SUCCEED + * All writes have completed successfully. + * + * Failure: FAIL + * One or more writes failed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write_from_selection(H5FD_t *file, H5FD_mem_t type, uint32_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + const void *bufs[]) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + assert(file); + assert(file->cls); + assert((mem_space_ids) || (count == 0)); + assert((file_space_ids) || (count == 0)); + assert((offsets) || (count == 0)); + assert((element_sizes) || (count == 0)); + assert((bufs) || (count == 0)); + + /* Verify that the first elements of the element_sizes and bufs arrays are + * valid. */ + assert((count == 0) || (element_sizes[0] != 0)); + assert((count == 0) || (bufs[0] != NULL)); + + /* Call private function */ + /* (Note compensating for base address addition in internal routine) */ + if (H5FD_write_selection_id(SKIP_SELECTION_CB | SKIP_VECTOR_CB, file, type, count, mem_space_ids, + file_space_ids, offsets, element_sizes, bufs) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file selection write request failed"); + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_write_from_selection() */ + +/*------------------------------------------------------------------------- * Function: H5FD_set_eoa * * Purpose: Private version of H5FDset_eoa() @@ -2138,6 +2375,119 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/) FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_driver_query() */ +/*------------------------------------------------------------------------ + * Function: H5FD__vstr_tmp_cmp() + * + * Purpose: This is the comparison callback function used by qsort() + * in H5FD__sort_io_req_real( ) + * + *------------------------------------------------------------------------- + */ +static int +H5FD__srt_tmp_cmp(const void *element_1, const void *element_2) +{ + haddr_t addr_1 = ((const H5FD_srt_tmp_t *)element_1)->addr; + haddr_t addr_2 = ((const H5FD_srt_tmp_t *)element_2)->addr; + int ret_value = 0; /* Return value */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity checks */ + assert(H5_addr_defined(addr_1)); + assert(H5_addr_defined(addr_2)); + + /* Compare the addresses */ + if (H5_addr_gt(addr_1, addr_2)) + ret_value = 1; + else if (H5_addr_lt(addr_1, addr_2)) + ret_value = -1; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FD__srt_tmp_cmp() */ + +/*------------------------------------------------------------------------- + * Function: H5FD__sort_io_req_real() + * + * Purpose: Scan the addrs array to see if it is sorted. + * + * If sorted, return TRUE in *was_sorted. + * + * If not sorted, use qsort() to sort the array. + * Do this by allocating an array of struct H5FD_srt_tmp_t, + * where each instance of H5FD_srt_tmp_t has two fields, + * addr and index. Load the array with the contents of the + * addrs array and the index of the associated entry. + * Then sort the array using qsort(). + * Return *FALSE in was_sorted. + * + * This is a common routine used by: + * --H5FD_sort_vector_io_req () + * --H5FD_sort_selection_io_req() + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD__sort_io_req_real(size_t count, haddr_t *addrs, hbool_t *was_sorted, struct H5FD_srt_tmp_t **srt_tmp) +{ + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity checks */ + + /* scan the offsets array to see if it is sorted */ + for (i = 1; i < count; i++) { + assert(H5_addr_defined(addrs[i - 1])); + + if (H5_addr_gt(addrs[i - 1], addrs[i])) + break; + else if (H5_addr_eq(addrs[i - 1], addrs[i])) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in selections"); + } + + /* if we traversed the entire array without breaking out, then + * the array was already sorted */ + if (i >= count) + *was_sorted = TRUE; + else + *was_sorted = FALSE; + + if (!(*was_sorted)) { + size_t srt_tmp_size; + + srt_tmp_size = (count * sizeof(struct H5FD_srt_tmp_t)); + + if (NULL == (*srt_tmp = (H5FD_srt_tmp_t *)malloc(srt_tmp_size))) + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc srt_tmp"); + + for (i = 0; i < count; i++) { + (*srt_tmp)[i].addr = addrs[i]; + (*srt_tmp)[i].index = i; + } + + /* sort the srt_tmp array */ + qsort(*srt_tmp, count, sizeof(struct H5FD_srt_tmp_t), H5FD__srt_tmp_cmp); + + /* verify no duplicate entries */ + i = 1; + + for (i = 1; i < count; i++) { + assert(H5_addr_lt((*srt_tmp)[i - 1].addr, (*srt_tmp)[i].addr)); + + if (H5_addr_eq(addrs[i - 1], addrs[i])) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addrs in array"); + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5FD__sort_io_req_real() */ + /*------------------------------------------------------------------------- * Function: H5FD_sort_vector_io_req * @@ -2169,38 +2519,15 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags /*out*/) * *------------------------------------------------------------------------- */ - -static int -H5FD__vsrt_tmp_cmp(const void *element_1, const void *element_2) -{ - haddr_t addr_1 = ((const H5FD_vsrt_tmp_t *)element_1)->addr; - haddr_t addr_2 = ((const H5FD_vsrt_tmp_t *)element_2)->addr; - int ret_value = 0; /* Return value */ - - FUNC_ENTER_PACKAGE_NOERR - - /* Sanity checks */ - assert(H5_addr_defined(addr_1)); - assert(H5_addr_defined(addr_2)); - - /* Compare the addresses */ - if (H5_addr_gt(addr_1, addr_2)) - ret_value = 1; - else if (H5_addr_lt(addr_1, addr_2)) - ret_value = -1; - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FD__vsrt_tmp_cmp() */ - herr_t H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[], H5_flexible_const_ptr_t bufs[], H5FD_mem_t **s_types_ptr, haddr_t **s_addrs_ptr, size_t **s_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr) { - herr_t ret_value = SUCCEED; /* Return value */ - size_t count = (size_t)_count; - size_t i; - struct H5FD_vsrt_tmp_t *srt_tmp = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + size_t count = (size_t)_count; + size_t i; + struct H5FD_srt_tmp_t *srt_tmp = NULL; FUNC_ENTER_NOAPI(FAIL) @@ -2224,22 +2551,12 @@ H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t assert((count == 0) || ((s_sizes_ptr) && (NULL == *s_sizes_ptr))); assert((count == 0) || ((s_bufs_ptr) && (NULL == *s_bufs_ptr))); - /* scan the addrs array to see if it is sorted */ - for (i = 1; i < count; i++) { - assert(H5_addr_defined(addrs[i - 1])); - - if (H5_addr_gt(addrs[i - 1], addrs[i])) - break; - else if (H5_addr_eq(addrs[i - 1], addrs[i])) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector"); - } - - /* if we traversed the entire array without breaking out, then - * the array was already sorted */ - if (i >= count) - *vector_was_sorted = TRUE; - else - *vector_was_sorted = FALSE; + /* Sort the addrs array in increasing addr order, while + * maintaining the association between each addr, and the + * sizes[], types[], and bufs[] values at the same index. + */ + if (H5FD__sort_io_req_real(count, addrs, vector_was_sorted, &srt_tmp) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sorting error in selection offsets"); if (*vector_was_sorted) { @@ -2250,46 +2567,14 @@ H5FD_sort_vector_io_req(hbool_t *vector_was_sorted, uint32_t _count, H5FD_mem_t } else { - /* must sort the addrs array in increasing addr order, while - * maintaining the association between each addr, and the - * sizes[], types[], and bufs[] values at the same index. - * - * Do this by allocating an array of struct H5FD_vsrt_tmp_t, where - * each instance of H5FD_vsrt_tmp_t has two fields, addr and index. - * Load the array with the contents of the addrs array and - * the index of the associated entry. Sort the array, allocate - * the s_types_ptr, s_addrs_ptr, s_sizes_ptr, and s_bufs_ptr + /* + * Allocate the s_types_ptr, s_addrs_ptr, s_sizes_ptr, and s_bufs_ptr * arrays and populate them using the mapping provided by - * the sorted array of H5FD_vsrt_tmp_t. + * the sorted array of H5FD_srt_tmp_t. */ size_t j; size_t fixed_size_index = count; size_t fixed_type_index = count; - size_t srt_tmp_size; - - srt_tmp_size = (count * sizeof(struct H5FD_vsrt_tmp_t)); - - if (NULL == (srt_tmp = (H5FD_vsrt_tmp_t *)malloc(srt_tmp_size))) - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc srt_tmp"); - - for (i = 0; i < count; i++) { - srt_tmp[i].addr = addrs[i]; - srt_tmp[i].index = i; - } - - /* sort the srt_tmp array */ - qsort(srt_tmp, count, sizeof(struct H5FD_vsrt_tmp_t), H5FD__vsrt_tmp_cmp); - - /* verify no duplicate entries */ - i = 1; - - for (i = 1; i < count; i++) { - assert(H5_addr_lt(srt_tmp[i - 1].addr, srt_tmp[i].addr)); - - if (H5_addr_eq(addrs[i - 1], addrs[i])) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "duplicate addr in vector"); - } if ((NULL == (*s_types_ptr = (H5FD_mem_t *)malloc(count * sizeof(H5FD_mem_t)))) || (NULL == (*s_addrs_ptr = (haddr_t *)malloc(count * sizeof(haddr_t)))) || @@ -2379,6 +2664,187 @@ done: } /* end H5FD_sort_vector_io_req() */ /*------------------------------------------------------------------------- + * Purpose: Determine whether the supplied selection I/O request is + * sorted. + * + * if is is, set *selection_was_sorted to TRUE, set: + * + * *s_mem_space_ids_ptr = mem_space_ids; + * *s_file_space_ids_ptr = file_space_ids; + * *s_offsets_ptr = offsets; + * *s_element_sizes_ptr = element_sizes; + * *s_bufs_ptr = bufs; + * + * and return. + * + * If it is not sorted, duplicate the mem_space_ids, file_space_ids, + * offsets, element_sizes and bufs arrays, storing the base + * addresses of the new arrays in *s_mem_space_ids_ptr, + * s_file_space_ids_ptr, s_offsets_ptr, *s_element_sizes_ptr, + * and s_bufs_ptr respectively. Determine the sorted order + * of the selection I/O request, and load it into the new + * selections in sorted order. + * + * Note that in this case, it is the caller's responsibility + * to free the sorted vectors. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_sort_selection_io_req(hbool_t *selection_was_sorted, size_t count, hid_t mem_space_ids[], + hid_t file_space_ids[], haddr_t offsets[], size_t element_sizes[], + H5_flexible_const_ptr_t bufs[], hid_t **s_mem_space_ids_ptr, + hid_t **s_file_space_ids_ptr, haddr_t **s_offsets_ptr, + size_t **s_element_sizes_ptr, H5_flexible_const_ptr_t **s_bufs_ptr) +{ + size_t i; + struct H5FD_srt_tmp_t *srt_tmp = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + + assert(selection_was_sorted); + + assert((mem_space_ids) || (count == 0)); + assert((file_space_ids) || (count == 0)); + assert((offsets) || (count == 0)); + assert((element_sizes) || (count == 0)); + assert((bufs) || (count == 0)); + + /* verify that the first elements of the element_sizes and bufs arrays are + * valid. + */ + assert((count == 0) || (element_sizes[0] != 0)); + assert((count == 0) || (bufs[0].cvp != NULL)); + + assert((count == 0) || ((s_mem_space_ids_ptr) && (NULL == *s_mem_space_ids_ptr))); + assert((count == 0) || ((s_file_space_ids_ptr) && (NULL == *s_file_space_ids_ptr))); + assert((count == 0) || ((s_offsets_ptr) && (NULL == *s_offsets_ptr))); + assert((count == 0) || ((s_element_sizes_ptr) && (NULL == *s_element_sizes_ptr))); + assert((count == 0) || ((s_bufs_ptr) && (NULL == *s_bufs_ptr))); + + /* Sort the offsets array in increasing offset order, while + * maintaining the association between each offset, and the + * mem_space_ids[], file_space_ids[], element_sizes and bufs[] + * values at the same index. + */ + if (H5FD__sort_io_req_real(count, offsets, selection_was_sorted, &srt_tmp) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sorting error in selection offsets"); + + if (*selection_was_sorted) { + + *s_mem_space_ids_ptr = mem_space_ids; + *s_file_space_ids_ptr = file_space_ids; + *s_offsets_ptr = offsets; + *s_element_sizes_ptr = element_sizes; + *s_bufs_ptr = bufs; + } + else { + + /* + * Allocate the s_mem_space_ids_ptr, s_file_space_ids_ptr, s_offsets_ptr, + * s_element_sizes_ptr and s_bufs_ptr arrays and populate them using the + * mapping provided by the sorted array of H5FD_srt_tmp_t. + */ + size_t j; + size_t fixed_element_sizes_index = count; + size_t fixed_bufs_index = count; + + if ((NULL == (*s_mem_space_ids_ptr = (hid_t *)malloc(count * sizeof(hid_t)))) || + (NULL == (*s_file_space_ids_ptr = (hid_t *)malloc(count * sizeof(hid_t)))) || + (NULL == (*s_offsets_ptr = (haddr_t *)malloc(count * sizeof(haddr_t)))) || + (NULL == (*s_element_sizes_ptr = (size_t *)malloc(count * sizeof(size_t)))) || + (NULL == + (*s_bufs_ptr = (H5_flexible_const_ptr_t *)malloc(count * sizeof(H5_flexible_const_ptr_t))))) { + + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't alloc sorted selection(s)"); + } + + assert(element_sizes[0] != 0); + assert(bufs[0].cvp != NULL); + + /* Scan the element_sizes and bufs array to determine if the fixed + * element_sizes / bufs optimization is in use, and if so, to determine + * the index of the last valid value on each array. + * We have already verified that the first + * elements of these arrays are valid so we can start at the second + * element (if it exists). + */ + for (i = 1; i < count && ((fixed_element_sizes_index == count) || (fixed_bufs_index == count)); i++) { + if ((fixed_element_sizes_index == count) && (element_sizes[i] == 0)) + fixed_element_sizes_index = i - 1; + if ((fixed_bufs_index == count) && (bufs[i].cvp == NULL)) + fixed_bufs_index = i - 1; + } + + assert(fixed_element_sizes_index <= count); + assert(fixed_bufs_index <= count); + + /* Populate the sorted arrays. Note that the index stored in srt_tmp + * refers to the index in the unsorted array, while the position of + * srt_tmp within the sorted array is the index in the sorted arrays */ + for (i = 0; i < count; i++) { + + j = srt_tmp[i].index; + + (*s_mem_space_ids_ptr)[i] = mem_space_ids[j]; + (*s_file_space_ids_ptr)[i] = file_space_ids[j]; + (*s_offsets_ptr)[i] = offsets[j]; + (*s_element_sizes_ptr)[i] = element_sizes[MIN(j, fixed_element_sizes_index)]; + (*s_bufs_ptr)[i] = bufs[MIN(j, fixed_bufs_index)]; + } + } + +done: + if (srt_tmp) { + free(srt_tmp); + srt_tmp = NULL; + } + + /* On failure, free the sorted arrays if they were allocated. + * Note that we only allocate these arrays if the original array + * was not sorted -- thus we check both for failure, and for + * the flag indicating that the original array was not sorted + * in increasing address order. + */ + if ((ret_value != SUCCEED) && (!(*selection_was_sorted))) { + + /* free space allocated for sorted arrays */ + if (*s_mem_space_ids_ptr) { + free(*s_mem_space_ids_ptr); + *s_mem_space_ids_ptr = NULL; + } + + if (*s_file_space_ids_ptr) { + free(*s_file_space_ids_ptr); + *s_file_space_ids_ptr = NULL; + } + + if (*s_offsets_ptr) { + free(*s_offsets_ptr); + *s_offsets_ptr = NULL; + } + + if (*s_element_sizes_ptr) { + free(*s_element_sizes_ptr); + *s_element_sizes_ptr = NULL; + } + + if (*s_bufs_ptr) { + free(*s_bufs_ptr); + *s_bufs_ptr = NULL; + } + } + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5FD_sort_selection_io_req() */ + +/*------------------------------------------------------------------------- * Function: H5FD_delete * * Purpose: Private version of H5FDdelete() |