diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2018-06-02 03:54:18 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2018-06-02 03:54:18 (GMT) |
commit | faa9f888bed54cf67a6a6b5c15053bbbceaa5465 (patch) | |
tree | 351c94a083996f7b1da2de45e12c2df9c6d40cb8 | |
parent | 66717bf1370ba7ab2a252ffd23aac6bc21f536a8 (diff) | |
download | hdf5-faa9f888bed54cf67a6a6b5c15053bbbceaa5465.zip hdf5-faa9f888bed54cf67a6a6b5c15053bbbceaa5465.tar.gz hdf5-faa9f888bed54cf67a6a6b5c15053bbbceaa5465.tar.bz2 |
Implement chunking. File and memory selections must currently be the
same shape. Has not been fully tested yet.
-rw-r--r-- | examples/h5rados_dset_create.c | 21 | ||||
-rw-r--r-- | src/H5VLrados.c | 1107 |
2 files changed, 800 insertions, 328 deletions
diff --git a/examples/h5rados_dset_create.c b/examples/h5rados_dset_create.c index 3bf1fa9..0e14a7f 100644 --- a/examples/h5rados_dset_create.c +++ b/examples/h5rados_dset_create.c @@ -3,13 +3,14 @@ int main(int argc, char *argv[]) { rados_t cluster; char *pool = "mypool"; - hid_t file = -1, dset = -1, space = -1, fapl = -1; + hid_t file = -1, dset = -1, space = -1, fapl = -1, dcpl = H5P_DEFAULT; hsize_t dims[2] = {4, 6}; + hsize_t cdims[2]; (void)MPI_Init(&argc, &argv); - if(argc != 3) - PRINTF_ERROR("argc != 3\n"); + if((argc != 3) && (argc != 5)) + PRINTF_ERROR("argc is not 3 or 5\n"); if(rados_create(&cluster, NULL) < 0) ERROR; @@ -28,6 +29,16 @@ int main(int argc, char *argv[]) { if(H5Pset_all_coll_metadata_ops(fapl, true) < 0) ERROR; + /* Set up DCPL */ + if(argc == 5) { + cdims[0] = (hsize_t)atoi(argv[3]); + cdims[1] = (hsize_t)atoi(argv[4]); + if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) + ERROR; + if(H5Pset_chunk(dcpl, 2, cdims) < 0) + ERROR; + } /* end if */ + /* Set up dataspace */ if((space = H5Screate_simple(2, dims, NULL)) < 0) ERROR; @@ -39,7 +50,7 @@ int main(int argc, char *argv[]) { printf("Creating dataset\n"); /* Create dataset */ - if((dset = H5Dcreate2(file, argv[2], H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + if((dset = H5Dcreate2(file, argv[2], H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) ERROR; /* Close */ @@ -51,6 +62,8 @@ int main(int argc, char *argv[]) { ERROR; if(H5Pclose(fapl) < 0) ERROR; + if((dcpl != H5P_DEFAULT) && (H5Pclose(dcpl) < 0)) + ERROR; printf("Success\n"); diff --git a/src/H5VLrados.c b/src/H5VLrados.c index 38a5810..76a865e 100644 --- a/src/H5VLrados.c +++ b/src/H5VLrados.c @@ -55,6 +55,9 @@ hid_t H5VL_RADOS_g = -1; #define H5VL_RADOS_TYPE_DSET 0x4000000000000000ull #define H5VL_RADOS_TYPE_DTYPE 0x8000000000000000ull +/* Definitions for chunking code */ +#define H5VL_RADOS_DEFAULT_NUM_SEL_CHUNKS 64 + /* * Typedefs */ @@ -97,6 +100,16 @@ typedef struct { uint64_t idx; } H5VL_rados_vl_file_ud_t; #endif + +/* Information about a singular selected chunk during a Dataset read/write */ +typedef struct H5VL_rados_select_chunk_info_t { + uint64_t chunk_coords[H5S_MAX_RANK]; /* The starting coordinates ("upper left corner") of the chunk */ + hid_t mspace_id; /* The memory space corresponding to the + selection in the chunk in memory */ + hid_t fspace_id; /* The file space corresponding to the + selection in the chunk in the file */ +} H5VL_rados_select_chunk_info_t; + /* * Prototypes */ @@ -214,8 +227,11 @@ static void *H5VL_rados_group_reconstitute(H5VL_rados_file_t *file, static htri_t H5VL_rados_need_bkg(hid_t src_type_id, hid_t dst_type_id, size_t *dst_type_size, hbool_t *fill_bkg); static herr_t H5VL_rados_tconv_init(hid_t src_type_id, size_t *src_type_size, - hid_t dst_type_id, size_t *dst_type_size, size_t num_elem, void **tconv_buf, - void **bkg_buf, H5VL_rados_tconv_reuse_t *reuse, hbool_t *fill_bkg); + hid_t dst_type_id, size_t *dst_type_size, hbool_t *_types_equal, + H5VL_rados_tconv_reuse_t *reuse, hbool_t *_need_bkg, hbool_t *fill_bkg); +static herr_t H5VL_rados_get_selected_chunk_info(hid_t dcpl_id, + hid_t file_space_id, hid_t mem_space_id, + H5VL_rados_select_chunk_info_t **chunk_info, size_t *chunk_info_len); static herr_t H5VL_rados_build_io_op_merge(H5S_t *mem_space, H5S_t *file_space, size_t type_size, size_t tot_nelem, void *rbuf, const void *wbuf, rados_read_op_t read_op, rados_write_op_t write_op); @@ -364,12 +380,15 @@ done: /* Create a RADOS string oid for a data chunk given the file name, binary oid, - * dataset rank, and chunk location */ + * dataset rank, and chunk location. If *oid is not NULL, it is assumed to be a + * buffer large enough, i.e. one previously returned by this function with the + * same file and rank */ static herr_t H5VL_rados_oid_create_chunk(const H5VL_rados_file_t *file, uint64_t bin_oid, - int rank, hsize_t *chunk_loc, char **oid) + int rank, uint64_t *chunk_loc, char **oid) { - char *tmp_oid = NULL; + char *tmp_buf = NULL; + char *enc_buf = NULL; size_t oid_len; size_t oid_off; int i; @@ -379,31 +398,40 @@ H5VL_rados_oid_create_chunk(const H5VL_rados_file_t *file, uint64_t bin_oid, HDassert((rank >= 0) && (rank <= 99)); - /* Allocate space for oid */ + /* Calculate space needed for oid */ oid_len = 2 + file->file_name_len + 16 + ((size_t)rank * 16) + 1; - if(NULL == (tmp_oid = (char *)H5MM_malloc(oid_len))) - HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate RADOS object id") + + /* Assign encoding buffer and allocate buffer, if needed */ + if(*oid) + enc_buf = *oid; + else { + if(NULL == (tmp_buf = (char *)H5MM_malloc(oid_len))) + HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate RADOS object id") + enc_buf = tmp_buf; + } /* end else */ /* Encode file name and binary oid into string oid */ - if(HDsnprintf(tmp_oid, oid_len, "%02d%s%016llX", rank, file->file_name, + if(HDsnprintf(enc_buf, oid_len, "%02d%s%016llX", rank, file->file_name, (long long unsigned)bin_oid) != 2 + (int)file->file_name_len + 16) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't encode string object id") oid_off = 2 + file->file_name_len + 16; /* Encode chunk location */ for(i = 0; i < rank; i++) { - if(HDsnprintf(tmp_oid + oid_off, oid_len - oid_off, "%016llX", chunk_loc[i]) + if(HDsnprintf(enc_buf + oid_off, oid_len - oid_off, "%016llX", (long long unsigned)chunk_loc[i]) != 16) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't encode string object id") oid_off += 16; } /* end for */ /* Return oid string value */ - *oid = tmp_oid; - tmp_oid = NULL; + if(!*oid) { + *oid = tmp_buf; + tmp_buf = NULL; + } /* end if */ done: - H5MM_xfree(tmp_oid); + H5MM_xfree(tmp_buf); FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_rados_oid_create_chunk() */ @@ -2470,10 +2498,10 @@ done: */ static herr_t H5VL_rados_tconv_init(hid_t src_type_id, size_t *src_type_size, - hid_t dst_type_id, size_t *dst_type_size, size_t num_elem, void **tconv_buf, - void **bkg_buf, H5VL_rados_tconv_reuse_t *reuse, hbool_t *fill_bkg) + hid_t dst_type_id, size_t *dst_type_size, hbool_t *_types_equal, + H5VL_rados_tconv_reuse_t *reuse, hbool_t *_need_bkg, hbool_t *fill_bkg) { - htri_t need_bkg; + htri_t need_bkg = FALSE; htri_t types_equal; herr_t ret_value = SUCCEED; @@ -2481,10 +2509,8 @@ H5VL_rados_tconv_init(hid_t src_type_id, size_t *src_type_size, HDassert(src_type_size); HDassert(dst_type_size); - HDassert(tconv_buf); - HDassert(!*tconv_buf); - HDassert(bkg_buf); - HDassert(!*bkg_buf); + HDassert(_types_equal); + HDassert(_need_bkg); HDassert(fill_bkg); HDassert(!*fill_bkg); @@ -2514,27 +2540,16 @@ H5VL_rados_tconv_init(hid_t src_type_id, size_t *src_type_size, else if(need_bkg) *reuse = H5VL_RADOS_TCONV_REUSE_BKG; } /* end if */ - - /* Allocate conversion buffer if it is not being reused */ - if(!reuse || (*reuse != H5VL_RADOS_TCONV_REUSE_TCONV)) - if(NULL == (*tconv_buf = H5MM_malloc(num_elem * (*src_type_size - > *dst_type_size ? *src_type_size : *dst_type_size)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate type conversion buffer") - - /* Allocate background buffer if one is needed and it is not being - * reused */ - if(need_bkg && (!reuse || (*reuse != H5VL_RADOS_TCONV_REUSE_BKG))) - if(NULL == (*bkg_buf = H5MM_calloc(num_elem * *dst_type_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate background buffer") } /* end else */ + /* Set return values */ + *_types_equal = types_equal; + *_need_bkg = need_bkg; + done: /* Cleanup on failure */ if(ret_value < 0) { - *tconv_buf = H5MM_xfree(*tconv_buf); - *bkg_buf = H5MM_xfree(*bkg_buf); - if(reuse) - *reuse = H5VL_RADOS_TCONV_REUSE_NONE; + *reuse = H5VL_RADOS_TCONV_REUSE_NONE; } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -2927,6 +2942,254 @@ done: /*------------------------------------------------------------------------- + * Function: H5VL_rados_get_selected_chunk_info + * + * Purpose: Calculates the starting coordinates for the chunks selected + * in the file space given by file_space_id and sets up + * individual memory and file spaces for each chunk. The chunk + * coordinates and dataspaces are returned through the + * chunk_info struct pointer. + * + * XXX: Note that performance could be increased by + * calculating all of the chunks in the entire dataset + * and then caching them in the dataset object for + * re-use in subsequent reads/writes + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Neil Fortner + * May, 2018 + * Based on H5VL_daosm_get_selected_chunk_info by Jordan + * Henderson, May, 2017 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_rados_get_selected_chunk_info(hid_t dcpl, + hid_t file_space_id, hid_t mem_space_id, + H5VL_rados_select_chunk_info_t **chunk_info, size_t *chunk_info_len) +{ + H5VL_rados_select_chunk_info_t *_chunk_info = NULL; + hssize_t num_sel_points; + hssize_t chunk_file_space_adjust[H5O_LAYOUT_NDIMS]; + hsize_t chunk_dims[H5S_MAX_RANK]; + hsize_t file_sel_start[H5S_MAX_RANK], file_sel_end[H5S_MAX_RANK]; + hsize_t mem_sel_start[H5S_MAX_RANK], mem_sel_end[H5S_MAX_RANK]; + hsize_t start_coords[H5O_LAYOUT_NDIMS], end_coords[H5O_LAYOUT_NDIMS]; + hsize_t selection_start_coords[H5O_LAYOUT_NDIMS]; + hsize_t num_sel_points_cast; + htri_t space_same_shape = FALSE; + size_t info_buf_alloced; + size_t i, j; + H5S_t *fspace = NULL, *mspace = NULL; + int fspace_ndims, mspace_ndims; + int increment_dim; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(chunk_info); + HDassert(chunk_info_len); + + if ((num_sel_points = H5Sget_select_npoints(file_space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "can't get number of points select in dataspace") + H5_CHECKED_ASSIGN(num_sel_points_cast, hsize_t, num_sel_points, hssize_t); + + /* Get the chunking information */ + if (H5Pget_chunk(dcpl, H5S_MAX_RANK, chunk_dims) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get chunking information") + + if ((fspace_ndims = H5Sget_simple_extent_ndims(file_space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file space dimensionality") + if ((mspace_ndims = H5Sget_simple_extent_ndims(mem_space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get memory space dimensionality") + HDassert(mspace_ndims == fspace_ndims); + + /* Get the bounding box for the current selection in the file space */ + if (H5Sget_select_bounds(file_space_id, file_sel_start, file_sel_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get bounding box for file selection") + + if (H5Sget_select_bounds(mem_space_id, mem_sel_start, mem_sel_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get bounding box for memory selection") + + /* Calculate the adjustment for memory selection from the file selection */ + for (i = 0; i < (size_t) fspace_ndims; i++) { + H5_CHECK_OVERFLOW(file_sel_start[i], hsize_t, hssize_t); + H5_CHECK_OVERFLOW(mem_sel_start[i], hsize_t, hssize_t); + chunk_file_space_adjust[i] = (hssize_t) file_sel_start[i] - (hssize_t) mem_sel_start[i]; + } /* end for */ + + if (NULL == (_chunk_info = (H5VL_rados_select_chunk_info_t *) H5MM_malloc(H5VL_RADOS_DEFAULT_NUM_SEL_CHUNKS * sizeof(*_chunk_info)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate space for selected chunk info buffer") + info_buf_alloced = H5VL_RADOS_DEFAULT_NUM_SEL_CHUNKS * sizeof(*_chunk_info); + + /* Calculate the coordinates for the initial chunk */ + for (i = 0; i < (size_t) fspace_ndims; i++) { + start_coords[i] = selection_start_coords[i] = (file_sel_start[i] / chunk_dims[i]) * chunk_dims[i]; + end_coords[i] = (start_coords[i] + chunk_dims[i]) - 1; + } /* end for */ + + if (NULL == (fspace = (H5S_t *) H5I_object_verify(file_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + if (NULL == (mspace = (H5S_t *) H5I_object_verify(mem_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + if (FAIL == (space_same_shape = H5S_select_shape_same(fspace, mspace))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Iterate through each "chunk" in the dataset */ + for (i = 0; num_sel_points_cast;) { + /* Check for intersection of file selection and "chunk". If there is + * an intersection, set up a valid memory and file space for the chunk. */ + if (TRUE == H5S_hyper_intersect_block(fspace, start_coords, end_coords)) { + hssize_t chunk_mem_space_adjust[H5O_LAYOUT_NDIMS]; + hssize_t chunk_sel_npoints; + hid_t tmp_chunk_fspace_id; + H5S_t *tmp_chunk_fspace = NULL; + + /* Re-allocate selected chunk info buffer if necessary */ + while (i > (info_buf_alloced / sizeof(*_chunk_info)) - 1) { + if (NULL == (_chunk_info = (H5VL_rados_select_chunk_info_t *) H5MM_realloc(_chunk_info, 2 * info_buf_alloced))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't reallocate space for selected chunk info buffer") + info_buf_alloced *= 2; + } /* end while */ + + /* + * Set up the file Dataspace for this chunk. + */ + + /* Create temporary chunk for selection operations */ + if ((tmp_chunk_fspace_id = H5Scopy(file_space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space") + + if (NULL == (tmp_chunk_fspace = (H5S_t *) H5I_object_verify(tmp_chunk_fspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */ + if (H5S_hyper_convert(tmp_chunk_fspace) < 0) { + (void) H5S_close(tmp_chunk_fspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees") + } /* end if */ + + /* "AND" temporary chunk and current chunk */ + if (H5S_select_hyperslab(tmp_chunk_fspace, H5S_SELECT_AND, start_coords, NULL, chunk_dims, NULL) < 0) { + (void) H5S_close(tmp_chunk_fspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection") + } /* end if */ + + /* Resize chunk's dataspace dimensions to size of chunk */ + if (H5S_set_extent_real(tmp_chunk_fspace, chunk_dims) < 0) { + (void) H5S_close(tmp_chunk_fspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions") + } /* end if */ + + /* Move selection back to have correct offset in chunk */ + if (H5S_SELECT_ADJUST_U(tmp_chunk_fspace, start_coords) < 0) { + (void) H5S_close(tmp_chunk_fspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection") + } /* end if */ + + /* Copy the chunk's coordinates to the selected chunk info buffer */ + HDmemcpy(_chunk_info[i].chunk_coords, start_coords, (size_t) fspace_ndims * sizeof(hsize_t)); + + _chunk_info[i].fspace_id = tmp_chunk_fspace_id; + + /* + * Now set up the memory Dataspace for this chunk. + */ + if (space_same_shape) { + hid_t tmp_chunk_mspace_id; + H5S_t *tmp_chunk_mspace = NULL; + + if ((tmp_chunk_mspace_id = H5Scopy(mem_space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space") + + if (NULL == (tmp_chunk_mspace = (H5S_t *) H5I_object_verify(tmp_chunk_mspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Release the current selection */ + if (H5S_SELECT_RELEASE(tmp_chunk_mspace) < 0) { + (void) H5S_close(tmp_chunk_mspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection") + } /* end if */ + + /* Copy the chunk's file space selection to its memory space selection */ + if (H5S_select_copy(tmp_chunk_mspace, tmp_chunk_fspace, FALSE) < 0) { + (void) H5S_close(tmp_chunk_mspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection") + } /* end if */ + + /* Compute the adjustment for the chunk */ + for (j = 0; j < (size_t) fspace_ndims; j++) { + H5_CHECK_OVERFLOW(_chunk_info[i].chunk_coords[j], hsize_t, hssize_t); + chunk_mem_space_adjust[j] = chunk_file_space_adjust[j] - (hssize_t) _chunk_info[i].chunk_coords[j]; + } /* end for */ + + /* Adjust the selection */ + if (H5S_hyper_adjust_s(tmp_chunk_mspace, chunk_mem_space_adjust) < 0) { + (void) H5S_close(tmp_chunk_mspace); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk memory space selection") + } /* end if */ + + _chunk_info[i].mspace_id = tmp_chunk_mspace_id; + } /* end if */ + else { + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "file and memory selections must currently have the same shape") + } /* end else */ + + i++; + + /* Determine if there are more chunks to process */ + if ((chunk_sel_npoints = H5S_GET_SELECT_NPOINTS(tmp_chunk_fspace)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get number of points selected in chunk file space") + + num_sel_points_cast -= (hsize_t) chunk_sel_npoints; + + if (num_sel_points_cast == 0) + HGOTO_DONE(SUCCEED) + } /* end if */ + + /* Set current increment dimension */ + increment_dim = fspace_ndims - 1; + + /* Increment chunk location in fastest changing dimension */ + H5_CHECK_OVERFLOW(chunk_dims[increment_dim], hsize_t, hssize_t); + start_coords[increment_dim] += chunk_dims[increment_dim]; + end_coords[increment_dim] += chunk_dims[increment_dim]; + + /* Bring chunk location back into bounds, if necessary */ + if (start_coords[increment_dim] > file_sel_end[increment_dim]) { + do { + /* Reset current dimension's location to 0 */ + start_coords[increment_dim] = selection_start_coords[increment_dim]; + end_coords[increment_dim] = (start_coords[increment_dim] + chunk_dims[increment_dim]) - 1; + + /* Decrement current dimension */ + increment_dim--; + + /* Increment chunk location in current dimension */ + start_coords[increment_dim] += chunk_dims[increment_dim]; + end_coords[increment_dim] = (start_coords[increment_dim] + chunk_dims[increment_dim]) - 1; + } while (start_coords[increment_dim] > file_sel_end[increment_dim]); + } /* end if */ + } /* end for */ + +done: + if (ret_value >= 0) { + *chunk_info = _chunk_info; + *chunk_info_len = i; + } /* end if */ + else { + if (_chunk_info) + H5MM_free(_chunk_info); + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_rados_get_selected_chunk_info() */ + + +/*------------------------------------------------------------------------- * Function: H5VL_rados_build_io_op_merge * * Purpose: RADOSINC @@ -3357,6 +3620,7 @@ static herr_t H5VL_rados_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id, void *buf, void H5_ATTR_UNUSED **req) { + H5VL_rados_select_chunk_info_t *chunk_info = NULL; /* Array of info for each chunk selected in the file */ H5VL_rados_dset_t *dset = (H5VL_rados_dset_t *)_dset; H5S_sel_iter_t sel_iter; /* Selection iteration info */ hbool_t sel_iter_init = FALSE; /* Selection iteration info has been initialized */ @@ -3365,19 +3629,29 @@ H5VL_rados_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, hid_t real_file_space_id; hid_t real_mem_space_id; hssize_t num_elem; - hsize_t chunk_coords[H5S_MAX_RANK]; + hssize_t num_elem_chunk; + size_t chunk_info_len; char *chunk_oid = NULL; rados_read_op_t read_op; hbool_t read_op_init = FALSE; + size_t file_type_size = 0; + size_t mem_type_size; + hbool_t types_equal = TRUE; + hbool_t need_bkg = FALSE; + hbool_t fill_bkg = FALSE; //hid_t base_type_id = FAIL; //size_t base_type_size = 0; - void *tconv_buf = NULL; - void *bkg_buf = NULL; + void *tmp_tconv_buf = NULL; + void *tmp_bkg_buf = NULL; + void *tconv_buf; + void *bkg_buf; //H5T_class_t type_class; //hbool_t is_vl = FALSE; //htri_t is_vl_str = FALSE; + hbool_t close_spaces = FALSE; H5VL_rados_tconv_reuse_t reuse = H5VL_RADOS_TCONV_REUSE_NONE; int ret; + uint64_t i; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -3418,15 +3692,6 @@ H5VL_rados_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, if(num_elem == 0) HGOTO_DONE(SUCCEED) - /* Create chunk key - always contiguous for now */ - chunk_coords[0] = 0; - if(H5VL_rados_oid_create_chunk(dset->obj.item.file, dset->obj.bin_oid, 1, - chunk_coords, &chunk_oid) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create dataset chunk oid") - - /* Create read op */ - read_op = rados_create_read_op(); - read_op_init = TRUE; #if 0 /* Check for vlen */ if(H5T_NO_CLASS == (type_class = H5Tget_class(mem_type_id))) @@ -3447,195 +3712,292 @@ H5VL_rados_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, if(is_vl_str) is_vl = TRUE; } /* end if */ + else +#endif + { + /* Initialize type conversion */ + if(H5VL_rados_tconv_init(dset->type_id, &file_type_size, mem_type_id, &mem_type_size, &types_equal, &reuse, &need_bkg, &fill_bkg) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize type conversion") + } /* end else */ - /* Check for variable length */ - if(is_vl) { - H5VL_daosm_vl_mem_ud_t mem_ud; - H5VL_daosm_vl_file_ud_t file_ud; + /* Check if the dataset actually has a chunked storage layout. If it does not, simply + * set up the dataset as a single "chunk". + */ + switch(H5Pget_layout(dset->dcpl_id)) { + case H5D_COMPACT: + case H5D_CONTIGUOUS: + if (NULL == (chunk_info = (H5VL_rados_select_chunk_info_t *)H5MM_malloc(sizeof(H5VL_rados_select_chunk_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate single chunk info buffer") + chunk_info_len = 1; + + /* Set up "single-chunk dataset", with the "chunk" starting at coordinate 0 */ + chunk_info->fspace_id = real_file_space_id; + chunk_info->mspace_id = real_mem_space_id; + HDmemset(chunk_info->chunk_coords, 0, sizeof(chunk_info->chunk_coords)); + + break; + + case H5D_CHUNKED: +// if(is_vl) +// HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "vlen types are currently unsupported with chunking") + + /* Get the coordinates of the currently selected chunks in the file, setting up memory and file dataspaces for them */ + if(H5VL_rados_get_selected_chunk_info(dset->dcpl_id, real_file_space_id, real_mem_space_id, &chunk_info, &chunk_info_len) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get selected chunk info") + + close_spaces = TRUE; + + break; + default: + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "invalid, unknown or unsupported dataset storage layout type") + } /* end switch */ + + /* Get number of elements in a chunk */ + if((num_elem_chunk = H5Sget_simple_extent_npoints(chunk_info[0].fspace_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of points in chunk") + + /* Iterate through each of the "chunks" in the dataset */ + for(i = 0; i < chunk_info_len; i++) { + /* Create read op */ + read_op = rados_create_read_op(); + read_op_init = TRUE; + + /* Create chunk key */ + if(H5VL_rados_oid_create_chunk(dset->obj.item.file, dset->obj.bin_oid, ndims, + chunk_info[i].chunk_coords, &chunk_oid) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create dataset chunk oid") /* Get number of elements in selection */ - if((num_elem = H5Sget_select_npoints(real_mem_space_id)) < 0) + if((num_elem = H5Sget_select_npoints(chunk_info[i].mspace_id)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of points in selection") +#if 0 + /* Check for variable length */ + if(is_vl) { + H5VL_daosm_vl_mem_ud_t mem_ud; + H5VL_daosm_vl_file_ud_t file_ud; + + /* Get number of elements in selection */ + if((num_elem = H5Sget_select_npoints(real_mem_space_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of points in selection") + + /* Allocate array of akey pointers */ + if(NULL == (akeys = (uint8_t **)H5MM_calloc((size_t)num_elem * sizeof(uint8_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for akey array") + + /* Allocate array of iods */ + if(NULL == (iods = (daos_iod_t *)H5MM_calloc((size_t)num_elem * sizeof(daos_iod_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for I/O descriptor array") + + /* Fill in size fields of iod as DAOS_REC_ANY so we can read the vl + * sizes */ + for(i = 0; i < (uint64_t)num_elem; i++) + iods[i].iod_size = DAOS_REC_ANY; + + /* Iterate over file selection. Note the bogus buffer and type_id, + * these don't matter since the "elem" parameter of the callback is not + * used. */ + file_ud.akeys = akeys; + file_ud.iods = iods; + file_ud.idx = 0; + if(H5Diterate((void *)buf, mem_type_id, real_file_space_id, H5VL_daosm_dataset_file_vl_cb, &file_ud) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "file selection iteration failed") + HDassert(file_ud.idx == (uint64_t)num_elem); + + /* Read vl sizes from dataset */ + /* Note cast to unsigned reduces width to 32 bits. Should eventually + * check for overflow and iterate over 2^32 size blocks */ + if(0 != (ret = daos_obj_fetch(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)num_elem, iods, NULL, NULL /*maps*/, NULL /*event*/))) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't read vl data sizes from dataset: %d", ret) + + /* Allocate array of sg_iovs */ + if(NULL == (sg_iovs = (daos_iov_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_iov_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list") + + /* Allocate array of sgls */ + if(NULL == (sgls = (daos_sg_list_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_sg_list_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list array") + + /* Iterate over memory selection */ + mem_ud.iods = iods; + mem_ud.sgls = sgls; + mem_ud.sg_iovs = sg_iovs; + mem_ud.is_vl_str = is_vl_str; + mem_ud.base_type_size = base_type_size; + mem_ud.offset = 0; + mem_ud.idx = 0; + if(H5Diterate((void *)buf, mem_type_id, real_mem_space_id, H5VL_daosm_dataset_mem_vl_rd_cb, &mem_ud) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "memory selection iteration failed") + HDassert(mem_ud.idx == (uint64_t)num_elem); - /* Allocate array of akey pointers */ - if(NULL == (akeys = (uint8_t **)H5MM_calloc((size_t)num_elem * sizeof(uint8_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for akey array") - - /* Allocate array of iods */ - if(NULL == (iods = (daos_iod_t *)H5MM_calloc((size_t)num_elem * sizeof(daos_iod_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for I/O descriptor array") - - /* Fill in size fields of iod as DAOS_REC_ANY so we can read the vl - * sizes */ - for(i = 0; i < (uint64_t)num_elem; i++) - iods[i].iod_size = DAOS_REC_ANY; - - /* Iterate over file selection. Note the bogus buffer and type_id, - * these don't matter since the "elem" parameter of the callback is not - * used. */ - file_ud.akeys = akeys; - file_ud.iods = iods; - file_ud.idx = 0; - if(H5Diterate((void *)buf, mem_type_id, real_file_space_id, H5VL_daosm_dataset_file_vl_cb, &file_ud) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "file selection iteration failed") - HDassert(file_ud.idx == (uint64_t)num_elem); - - /* Read vl sizes from dataset */ - /* Note cast to unsigned reduces width to 32 bits. Should eventually - * check for overflow and iterate over 2^32 size blocks */ - if(0 != (ret = daos_obj_fetch(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)num_elem, iods, NULL, NULL /*maps*/, NULL /*event*/))) - HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't read vl data sizes from dataset: %d", ret) - - /* Allocate array of sg_iovs */ - if(NULL == (sg_iovs = (daos_iov_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_iov_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list") - - /* Allocate array of sgls */ - if(NULL == (sgls = (daos_sg_list_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_sg_list_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list array") - - /* Iterate over memory selection */ - mem_ud.iods = iods; - mem_ud.sgls = sgls; - mem_ud.sg_iovs = sg_iovs; - mem_ud.is_vl_str = is_vl_str; - mem_ud.base_type_size = base_type_size; - mem_ud.offset = 0; - mem_ud.idx = 0; - if(H5Diterate((void *)buf, mem_type_id, real_mem_space_id, H5VL_daosm_dataset_mem_vl_rd_cb, &mem_ud) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "memory selection iteration failed") - HDassert(mem_ud.idx == (uint64_t)num_elem); - - /* Read data from dataset */ - /* Note cast to unsigned reduces width to 32 bits. Should eventually - * check for overflow and iterate over 2^32 size blocks */ - if(0 != (ret = daos_obj_fetch(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)((uint64_t)num_elem - mem_ud.offset), iods, sgls, NULL /*maps*/, NULL /*event*/))) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %d", ret) - } /* end if */ - else + /* Read data from dataset */ + /* Note cast to unsigned reduces width to 32 bits. Should eventually + * check for overflow and iterate over 2^32 size blocks */ + if(0 != (ret = daos_obj_fetch(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)((uint64_t)num_elem - mem_ud.offset), iods, sgls, NULL /*maps*/, NULL /*event*/))) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %d", ret) + } /* end if */ + else #endif - { - H5S_t *file_space = NULL; - H5S_t *mem_space = NULL; - size_t file_type_size; - htri_t types_equal; - - /* Get datatype size */ - if((file_type_size = H5Tget_size(dset->type_id)) == 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size") - - /* Get file dataspace object */ - if(NULL == (file_space = (H5S_t *)H5I_object(real_file_space_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); - - /* Check if the types are equal */ - if((types_equal = H5Tequal(dset->type_id, mem_type_id)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOMPARE, FAIL, "can't check if types are equal") - if(types_equal) { - /* No type conversion necessary */ - /* Check for memory space is H5S_ALL, use file space in this case */ - if(mem_space_id == H5S_ALL) { - /* Build read op from file space */ - if(H5VL_rados_build_io_op_match(file_space, file_type_size, (size_t)num_elem, buf, NULL, read_op, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS read op") + { + H5S_t *chunk_fspace = NULL; + H5S_t *chunk_mspace = NULL; + htri_t match_select = FALSE; + + /* Get file dataspace object */ + if(NULL == (chunk_fspace = (H5S_t *) H5I_object_verify(chunk_info[i].fspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Check if the types are equal */ + if(types_equal) { + /* No type conversion necessary */ + /* Check if we should match the file and memory sequence lists + * (serialized selections). We can do this if the memory space + * is H5S_ALL and the chunk extent equals the file extent. If + * the number of chunks selected is more than one we do not need + * to check the extents because they cannot be the same. We + * could also allow the case where the memory space is not + * H5S_ALL but is equivalent. */ + if(mem_space_id == H5S_ALL && chunk_info_len == 1) + if((match_select = H5Sextent_equal(real_file_space_id, chunk_info[i].fspace_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check if file and chunk dataspaces are equal") + + /* Check for matching selections */ + if(match_select) { + /* Build read op from file space */ + if(H5VL_rados_build_io_op_match(chunk_fspace, file_type_size, (size_t)num_elem, buf, NULL, read_op, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS read op") + } /* end if */ + else { + /* Get memory dataspace object */ + if(NULL == (chunk_mspace = (H5S_t *) H5I_object_verify(chunk_info[i].mspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Build read op from file space and mem space */ + if(H5VL_rados_build_io_op_merge(chunk_mspace, chunk_fspace, file_type_size, (size_t)num_elem, buf, NULL, read_op, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS read op") + } /* end else */ + + /* Read data from dataset */ + if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) } /* end if */ else { + size_t nseq_tmp; + size_t nelem_tmp; + hsize_t sel_off; + size_t sel_len; + hbool_t contig; + + /* Type conversion necessary */ /* Get memory dataspace object */ - if(NULL == (mem_space = (H5S_t *)H5I_object(real_mem_space_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(NULL == (chunk_mspace = (H5S_t *) H5I_object_verify(chunk_info[i].mspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Check for contiguous memory buffer */ + + /* Initialize selection iterator */ + if(H5S_select_iter_init(&sel_iter, chunk_mspace, (size_t)1) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + sel_iter_init = TRUE; /* Selection iteration info has been initialized */ + + /* Get the sequence list - only check the first sequence because we only + * care if it is contiguous and if so where the contiguous selection + * begins */ + if(H5S_SELECT_GET_SEQ_LIST(chunk_mspace, 0, &sel_iter, (size_t)1, (size_t)-1, &nseq_tmp, &nelem_tmp, &sel_off, &sel_len) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") + contig = (sel_len == (size_t)num_elem); + sel_off *= (hsize_t)mem_type_size; - /* Build read op from file space and mem space */ - if(H5VL_rados_build_io_op_merge(mem_space, file_space, file_type_size, (size_t)num_elem, buf, NULL, read_op, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS read op") - } /* end else */ + /* Release selection iterator */ + if(H5S_SELECT_ITER_RELEASE(&sel_iter) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + sel_iter_init = FALSE; - /* Read data from dataset */ - if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) - } /* end if */ - else { - size_t nseq_tmp; - size_t nelem_tmp; - hsize_t sel_off; - size_t sel_len; - size_t mem_type_size; - hbool_t fill_bkg = FALSE; - hbool_t contig; - - /* Type conversion necessary */ - /* Check for contiguous memory buffer */ - /* Get memory dataspace object */ - if(NULL == (mem_space = (H5S_t *)H5I_object(real_mem_space_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); - - /* Initialize selection iterator */ - if(H5S_select_iter_init(&sel_iter, mem_space, (size_t)1) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - sel_iter_init = TRUE; /* Selection iteration info has been initialized */ - - /* Get the sequence list - only check the first sequence because we only - * care if it is contiguous and if so where the contiguous selection - * begins */ - if(H5S_SELECT_GET_SEQ_LIST(mem_space, 0, &sel_iter, (size_t)1, (size_t)-1, &nseq_tmp, &nelem_tmp, &sel_off, &sel_len) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") - contig = (sel_len == (size_t)num_elem); + /* Find or allocate usable type conversion buffer */ + if(contig && (reuse == H5VL_RADOS_TCONV_REUSE_TCONV)) + tconv_buf = (char *)buf + (size_t)sel_off; + else { + if(!tmp_tconv_buf) + if(NULL == (tmp_tconv_buf = H5MM_malloc( + (size_t)num_elem_chunk * (file_type_size + > mem_type_size ? file_type_size + : mem_type_size)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate type conversion buffer") + tconv_buf = tmp_tconv_buf; + } /* end else */ + + /* Find or allocate usable background buffer */ + if(need_bkg) { + if(contig && (reuse == H5VL_RADOS_TCONV_REUSE_BKG)) + bkg_buf = (char *)buf + (size_t)sel_off; + else { + if(!tmp_bkg_buf) + if(NULL == (tmp_bkg_buf = H5MM_malloc( + (size_t)num_elem_chunk * mem_type_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate background buffer") + bkg_buf = tmp_bkg_buf; + } /* end else */ + } /* end if */ + else + bkg_buf = NULL; - /* Initialize type conversion */ - if(H5VL_rados_tconv_init(dset->type_id, &file_type_size, mem_type_id, &mem_type_size, (size_t)num_elem, &tconv_buf, &bkg_buf, contig ? &reuse : NULL, &fill_bkg) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize type conversion") + /* Build read op from file space */ + if(H5VL_rados_build_io_op_contig(chunk_fspace, file_type_size, (size_t)num_elem, tconv_buf, NULL, read_op, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") - /* Reuse buffer as appropriate */ - if(contig) { - sel_off *= (hsize_t)mem_type_size; - if(reuse == H5VL_RADOS_TCONV_REUSE_TCONV) - tconv_buf = (char *)buf + (size_t)sel_off; - else if(reuse == H5VL_RADOS_TCONV_REUSE_BKG) - bkg_buf = (char *)buf + (size_t)sel_off; - } /* end if */ + /* Read data from dataset */ + if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) - /* Build read op from file space */ - if(H5VL_rados_build_io_op_contig(file_space, file_type_size, (size_t)num_elem, tconv_buf, NULL, read_op, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + /* Gather data to background buffer if necessary */ + if(fill_bkg && (bkg_buf == tmp_bkg_buf)) + if(H5Dgather(chunk_info[i].mspace_id, buf, mem_type_id, (size_t)num_elem * mem_type_size, bkg_buf, NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't gather data to background buffer") - /* Read data from dataset */ - if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) - - /* Gather data to background buffer if necessary */ - if(fill_bkg && (reuse != H5VL_RADOS_TCONV_REUSE_BKG)) - if(H5Dgather(real_mem_space_id, buf, mem_type_id, (size_t)num_elem * mem_type_size, bkg_buf, NULL, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't gather data to background buffer") - - /* Perform type conversion */ - if(H5Tconvert(dset->type_id, mem_type_id, (size_t)num_elem, tconv_buf, bkg_buf, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't perform type conversion") - - /* Scatter data to memory buffer if necessary */ - if(reuse != H5VL_RADOS_TCONV_REUSE_TCONV) { - H5VL_rados_scatter_cb_ud_t scatter_cb_ud; - - scatter_cb_ud.buf = tconv_buf; - scatter_cb_ud.len = (size_t)num_elem * mem_type_size; - if(H5Dscatter(H5VL_rados_scatter_cb, &scatter_cb_ud, mem_type_id, real_mem_space_id, buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't scatter data to read buffer") - } /* end if */ + /* Perform type conversion */ + if(H5Tconvert(dset->type_id, mem_type_id, (size_t)num_elem, tconv_buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't perform type conversion") + + /* Scatter data to memory buffer if necessary */ + if(tconv_buf == tmp_tconv_buf) { + H5VL_rados_scatter_cb_ud_t scatter_cb_ud; + + scatter_cb_ud.buf = tconv_buf; + scatter_cb_ud.len = (size_t)num_elem * mem_type_size; + if(H5Dscatter(H5VL_rados_scatter_cb, &scatter_cb_ud, mem_type_id, chunk_info[i].mspace_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't scatter data to read buffer") + } /* end if */ + } /* end else */ } /* end else */ - } /* end else */ + + rados_release_read_op(read_op); + read_op_init = FALSE; + } /* end for */ done: /* Free memory */ if(read_op_init) rados_release_read_op(read_op); H5MM_xfree(chunk_oid); - if(tconv_buf && (reuse != H5VL_RADOS_TCONV_REUSE_TCONV)) - H5MM_free(tconv_buf); - if(bkg_buf && (reuse != H5VL_RADOS_TCONV_REUSE_BKG)) - H5MM_free(bkg_buf); + H5MM_xfree(tmp_tconv_buf); + H5MM_xfree(tmp_bkg_buf); /*if(base_type_id != FAIL) if(H5I_dec_app_ref(base_type_id) < 0) HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close base type id")*/ + if(chunk_info) { + if(close_spaces) { + for(i = 0; i < chunk_info_len; i++) { + if(H5Sclose(chunk_info[i].mspace_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "can't close memory space"); + if(H5Sclose(chunk_info[i].fspace_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "can't close file space"); + } /* end for */ + } /* end if */ + + H5MM_free(chunk_info); + } /* end if */ + /* Release selection iterator */ if(sel_iter_init && H5S_SELECT_ITER_RELEASE(&sel_iter) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") @@ -3738,20 +4100,25 @@ H5VL_rados_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t H5_ATTR_UNUSED dxpl_id, const void *buf, void H5_ATTR_UNUSED **req) { + H5VL_rados_select_chunk_info_t *chunk_info = NULL; /* Array of info for each chunk selected in the file */ H5VL_rados_dset_t *dset = (H5VL_rados_dset_t *)_dset; int ndims; hsize_t dim[H5S_MAX_RANK]; hid_t real_file_space_id; hid_t real_mem_space_id; - H5S_t *file_space = NULL; - H5S_t *mem_space = NULL; hssize_t num_elem; - hsize_t chunk_coords[H5S_MAX_RANK]; + hssize_t num_elem_chunk; + size_t chunk_info_len; char *chunk_oid = NULL; rados_write_op_t write_op; hbool_t write_op_init = FALSE; rados_read_op_t read_op; hbool_t read_op_init = FALSE; + size_t file_type_size; + size_t mem_type_size; + hbool_t types_equal = TRUE; + hbool_t need_bkg = FALSE; + hbool_t fill_bkg = FALSE; //hid_t base_type_id = FAIL; //size_t base_type_size = 0; void *tconv_buf = NULL; @@ -3759,7 +4126,10 @@ H5VL_rados_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, //H5T_class_t type_class; //hbool_t is_vl = FALSE; //uhtri_t is_vl_str = FALSE; + hbool_t close_spaces = FALSE; + H5VL_rados_tconv_reuse_t reuse = H5VL_RADOS_TCONV_REUSE_NONE; int ret; + uint64_t i; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -3803,16 +4173,6 @@ H5VL_rados_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, /* Check for no selection */ if(num_elem == 0) HGOTO_DONE(SUCCEED) - - /* Create chunk key - always contiguous for now */ - chunk_coords[0] = 0; - if(H5VL_rados_oid_create_chunk(dset->obj.item.file, dset->obj.bin_oid, 1, - chunk_coords, &chunk_oid) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create dataset chunk oid") - - /* Create write op */ - write_op = rados_create_write_op(); - write_op_init = TRUE; #if 0 /* Check for vlen */ if(H5T_NO_CLASS == (type_class = H5Tget_class(mem_type_id))) @@ -3833,125 +4193,211 @@ H5VL_rados_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, if(is_vl_str) is_vl = TRUE; } /* end if */ - - /* Check for variable length */ - if(is_vl) { - H5VL_daosm_vl_mem_ud_t mem_ud; - H5VL_daosm_vl_file_ud_t file_ud; - - /* Allocate array of akey pointers */ - if(NULL == (akeys = (uint8_t **)H5MM_calloc((size_t)num_elem * sizeof(uint8_t *)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for akey array") - - /* Allocate array of iods */ - if(NULL == (iods = (daos_iod_t *)H5MM_calloc((size_t)num_elem * sizeof(daos_iod_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for I/O descriptor array") - - /* Allocate array of sg_iovs */ - if(NULL == (sg_iovs = (daos_iov_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_iov_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list") - - /* Allocate array of sgls */ - if(NULL == (sgls = (daos_sg_list_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_sg_list_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list array") - - /* Iterate over memory selection */ - mem_ud.iods = iods; - mem_ud.sgls = sgls; - mem_ud.sg_iovs = sg_iovs; - mem_ud.is_vl_str = is_vl_str; - mem_ud.base_type_size = base_type_size; - mem_ud.idx = 0; - if(H5Diterate((void *)buf, mem_type_id, real_mem_space_id, H5VL_daosm_dataset_mem_vl_wr_cb, &mem_ud) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "memory selection iteration failed") - HDassert(mem_ud.idx == (uint64_t)num_elem); - - /* Iterate over file selection. Note the bogus buffer and type_id, - * these don't matter since the "elem" parameter of the callback is not - * used. */ - file_ud.akeys = akeys; - file_ud.iods = iods; - file_ud.idx = 0; - if(H5Diterate((void *)buf, mem_type_id, real_file_space_id, H5VL_daosm_dataset_file_vl_cb, &file_ud) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "file selection iteration failed") - HDassert(file_ud.idx == (uint64_t)num_elem); - - /* Write data to dataset */ - /* Note cast to unsigned reduces width to 32 bits. Should eventually - * check for overflow and iterate over 2^32 size blocks */ - if(0 != (ret = daos_obj_update(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)num_elem, iods, sgls, NULL /*event*/))) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data to dataset: %d", ret) - } /* end if */ else #endif - { - size_t file_type_size; - size_t mem_type_size; - hbool_t fill_bkg = FALSE; - + { /* Initialize type conversion */ - if(H5VL_rados_tconv_init(mem_type_id, &mem_type_size, dset->type_id, &file_type_size, (size_t)num_elem, &tconv_buf, &bkg_buf, NULL, &fill_bkg) < 0) + if(H5VL_rados_tconv_init(dset->type_id, &file_type_size, mem_type_id, &mem_type_size, &types_equal, &reuse, &need_bkg, &fill_bkg) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize type conversion") + } /* end else */ - /* Build recxs and sg_iovs */ - /* Get file dataspace object */ - if(NULL == (file_space = (H5S_t *)H5I_object(real_file_space_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + /* Check if the dataset actually has a chunked storage layout. If it does not, simply + * set up the dataset as a single "chunk". + */ + switch(H5Pget_layout(dset->dcpl_id)) { + case H5D_COMPACT: + case H5D_CONTIGUOUS: + if (NULL == (chunk_info = (H5VL_rados_select_chunk_info_t *)H5MM_malloc(sizeof(H5VL_rados_select_chunk_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate single chunk info buffer") + chunk_info_len = 1; + + /* Set up "single-chunk dataset", with the "chunk" starting at coordinate 0 */ + chunk_info->fspace_id = real_file_space_id; + chunk_info->mspace_id = real_mem_space_id; + HDmemset(chunk_info->chunk_coords, 0, sizeof(chunk_info->chunk_coords)); - /* Check for type conversion */ - if(tconv_buf) { - /* Check if we need to fill background buffer */ - if(fill_bkg) { - HDassert(bkg_buf); + break; - /* Create read op */ - read_op = rados_create_read_op(); - read_op_init = TRUE; + case H5D_CHUNKED: +// if(is_vl) +// HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "vlen types are currently unsupported with chunking") - /* Build io ops (to read to bkg_buf and write from tconv_buf) - * from file space */ - if(H5VL_rados_build_io_op_contig(file_space, file_type_size, (size_t)num_elem, bkg_buf, tconv_buf, read_op, write_op) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + /* Get the coordinates of the currently selected chunks in the file, setting up memory and file dataspaces for them */ + if(H5VL_rados_get_selected_chunk_info(dset->dcpl_id, real_file_space_id, real_mem_space_id, &chunk_info, &chunk_info_len) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get selected chunk info") - /* Read data from dataset to background buffer */ - if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) - } /* end if */ - else - /* Build write op from file space */ - if(H5VL_rados_build_io_op_contig(file_space, file_type_size, (size_t)num_elem, NULL, tconv_buf, NULL, write_op) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + close_spaces = TRUE; - /* Gather data to conversion buffer */ - if(H5Dgather(real_mem_space_id, buf, mem_type_id, (size_t)num_elem * mem_type_size, tconv_buf, NULL, NULL) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't gather data to conversion buffer") + break; + default: + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "invalid, unknown or unsupported dataset storage layout type") + } /* end switch */ - /* Perform type conversion */ - if(H5Tconvert(mem_type_id, dset->type_id, (size_t)num_elem, tconv_buf, bkg_buf, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't perform type conversion") + /* Get number of elements in a chunk */ + if((num_elem_chunk = H5Sget_simple_extent_npoints(chunk_info[0].fspace_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of points in chunk") + + /* Allocate tconv_buf if necessary */ + if(!types_equal) + if(NULL == (tconv_buf = H5MM_malloc( (size_t)num_elem_chunk + * (file_type_size > mem_type_size ? file_type_size + : mem_type_size)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate type conversion buffer") + + /* Allocate bkg_buf if necessary */ + if(need_bkg) + if(NULL == (bkg_buf = H5MM_malloc((size_t)num_elem_chunk + * mem_type_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate background buffer") + + /* Iterate through each of the "chunks" in the dataset */ + for(i = 0; i < chunk_info_len; i++) { + /* Create write op */ + write_op = rados_create_write_op(); + write_op_init = TRUE; + + /* Create chunk key */ + if(H5VL_rados_oid_create_chunk(dset->obj.item.file, dset->obj.bin_oid, ndims, + chunk_info[i].chunk_coords, &chunk_oid) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create dataset chunk oid") + + /* Get number of elements in selection */ + if((num_elem = H5Sget_select_npoints(chunk_info[i].mspace_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of points in selection") +#if 0 + /* Check for variable length */ + if(is_vl) { + H5VL_daosm_vl_mem_ud_t mem_ud; + H5VL_daosm_vl_file_ud_t file_ud; + + /* Allocate array of akey pointers */ + if(NULL == (akeys = (uint8_t **)H5MM_calloc((size_t)num_elem * sizeof(uint8_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for akey array") + + /* Allocate array of iods */ + if(NULL == (iods = (daos_iod_t *)H5MM_calloc((size_t)num_elem * sizeof(daos_iod_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for I/O descriptor array") + + /* Allocate array of sg_iovs */ + if(NULL == (sg_iovs = (daos_iov_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_iov_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list") + + /* Allocate array of sgls */ + if(NULL == (sgls = (daos_sg_list_t *)H5MM_malloc((size_t)num_elem * sizeof(daos_sg_list_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for scatter gather list array") + + /* Iterate over memory selection */ + mem_ud.iods = iods; + mem_ud.sgls = sgls; + mem_ud.sg_iovs = sg_iovs; + mem_ud.is_vl_str = is_vl_str; + mem_ud.base_type_size = base_type_size; + mem_ud.idx = 0; + if(H5Diterate((void *)buf, mem_type_id, real_mem_space_id, H5VL_daosm_dataset_mem_vl_wr_cb, &mem_ud) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "memory selection iteration failed") + HDassert(mem_ud.idx == (uint64_t)num_elem); + + /* Iterate over file selection. Note the bogus buffer and type_id, + * these don't matter since the "elem" parameter of the callback is not + * used. */ + file_ud.akeys = akeys; + file_ud.iods = iods; + file_ud.idx = 0; + if(H5Diterate((void *)buf, mem_type_id, real_file_space_id, H5VL_daosm_dataset_file_vl_cb, &file_ud) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "file selection iteration failed") + HDassert(file_ud.idx == (uint64_t)num_elem); + + /* Write data to dataset */ + /* Note cast to unsigned reduces width to 32 bits. Should eventually + * check for overflow and iterate over 2^32 size blocks */ + if(0 != (ret = daos_obj_update(dset->obj.obj_oh, dset->obj.item.file->epoch, &dkey, (unsigned)num_elem, iods, sgls, NULL /*event*/))) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data to dataset: %d", ret) } /* end if */ - else { - /* Check for memory space is H5S_ALL, use file space in this case */ - if(mem_space_id == H5S_ALL) { - /* Build write op from file space */ - if(H5VL_rados_build_io_op_match(file_space, file_type_size, (size_t)num_elem, NULL, buf, NULL, write_op) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + else +#endif + { + H5S_t *chunk_fspace = NULL; + H5S_t *chunk_mspace = NULL; + htri_t match_select = FALSE; + + /* Get file dataspace object */ + if(NULL == (chunk_fspace = (H5S_t *) H5I_object_verify(chunk_info[i].fspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Check if the types are equal */ + if(types_equal) { + /* No type conversion necessary */ + /* Check if we should match the file and memory sequence lists + * (serialized selections). We can do this if the memory space + * is H5S_ALL and the chunk extent equals the file extent. If + * the number of chunks selected is more than one we do not need + * to check the extents because they cannot be the same. We + * could also allow the case where the memory space is not + * H5S_ALL but is equivalent. */ + if(mem_space_id == H5S_ALL && chunk_info_len == 1) + if((match_select = H5Sextent_equal(real_file_space_id, chunk_info[i].fspace_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check if file and chunk dataspaces are equal") + + /* Check for matching selections */ + if(match_select) { + /* Build write op from file space */ + if(H5VL_rados_build_io_op_match(chunk_fspace, file_type_size, (size_t)num_elem, NULL, buf, NULL, write_op) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + } /* end if */ + else { + /* Get memory dataspace object */ + if(NULL == (chunk_mspace = (H5S_t *)H5I_object_verify(chunk_info[i].mspace_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "not a dataspace") + + /* Build write op from file space and mem space */ + if(H5VL_rados_build_io_op_merge(chunk_mspace, chunk_fspace, file_type_size, (size_t)num_elem, NULL, buf, NULL, write_op) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + } /* end else */ } /* end if */ else { - /* Get memory dataspace object */ - if(NULL == (mem_space = (H5S_t *)H5I_object(real_mem_space_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + /* Type conversion necessary */ + /* Check if we need to fill background buffer */ + if(fill_bkg) { + HDassert(bkg_buf); + + /* Create read op */ + read_op = rados_create_read_op(); + read_op_init = TRUE; + + /* Build io ops (to read to bkg_buf and write from tconv_buf) + * from file space */ + if(H5VL_rados_build_io_op_contig(chunk_fspace, file_type_size, (size_t)num_elem, bkg_buf, tconv_buf, read_op, write_op) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + + /* Read data from dataset to background buffer */ + if((ret = rados_read_op_operate(read_op, ioctx_g, chunk_oid, LIBRADOS_OPERATION_NOFLAG)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data from dataset: %s", strerror(-ret)) + + rados_release_read_op(read_op); + read_op_init = FALSE; + } /* end if */ + else + /* Build write op from file space */ + if(H5VL_rados_build_io_op_contig(chunk_fspace, file_type_size, (size_t)num_elem, NULL, tconv_buf, NULL, write_op) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") - /* Build write op from file space and mem space */ - if(H5VL_rados_build_io_op_merge(mem_space, file_space, file_type_size, (size_t)num_elem, NULL, buf, NULL, write_op) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't generate RADOS write op") + /* Gather data to conversion buffer */ + if(H5Dgather(chunk_info[i].mspace_id, buf, mem_type_id, (size_t)num_elem * mem_type_size, tconv_buf, NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't gather data to conversion buffer") + + /* Perform type conversion */ + if(H5Tconvert(mem_type_id, dset->type_id, (size_t)num_elem, tconv_buf, bkg_buf, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't perform type conversion") } /* end else */ + + /* Write data to dataset */ + if((ret = rados_write_op_operate(write_op, ioctx_g, chunk_oid, NULL, LIBRADOS_OPERATION_NOFLAG)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data to dataset: %s", strerror(-ret)) } /* end else */ - /* Write data to dataset */ - if((ret = rados_write_op_operate(write_op, ioctx_g, chunk_oid, NULL, LIBRADOS_OPERATION_NOFLAG)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data to dataset: %s", strerror(-ret)) - } /* end else */ + rados_release_write_op(write_op); + write_op_init = FALSE; + } /* end for */ done: /* Free memory */ @@ -3967,6 +4413,19 @@ done: if(H5I_dec_app_ref(base_type_id) < 0) HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close base type id")*/ + if(chunk_info) { + if(close_spaces) { + for(i = 0; i < chunk_info_len; i++) { + if(H5Sclose(chunk_info[i].mspace_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "can't close memory space"); + if(H5Sclose(chunk_info[i].fspace_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "can't close file space"); + } /* end for */ + } /* end if */ + + H5MM_free(chunk_info); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_rados_dataset_write() */ |