diff options
-rw-r--r-- | examples/h5ff_client_obj.c | 10 | ||||
-rw-r--r-- | examples/h5ff_client_vl_data.c | 4 | ||||
-rwxr-xr-x | examples/run_ff_tests.sh.in | 8 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/H5VLiod.c | 175 | ||||
-rw-r--r-- | src/H5VLiod_attr.c | 9 | ||||
-rw-r--r-- | src/H5VLiod_client.c | 864 | ||||
-rw-r--r-- | src/H5VLiod_client.h | 50 | ||||
-rw-r--r-- | src/H5VLiod_common.c | 1016 | ||||
-rw-r--r-- | src/H5VLiod_common.h | 59 | ||||
-rw-r--r-- | src/H5VLiod_dset.c | 927 | ||||
-rw-r--r-- | src/H5VLiod_dtype.c | 6 | ||||
-rw-r--r-- | src/H5VLiod_obj.c | 4 | ||||
-rw-r--r-- | src/H5VLiod_server.c | 8 | ||||
-rw-r--r-- | src/H5checksum.c | 64 | ||||
-rw-r--r-- | src/H5public.h | 3 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/Makefile.in | 33 |
18 files changed, 2181 insertions, 1062 deletions
diff --git a/examples/h5ff_client_obj.c b/examples/h5ff_client_obj.c index 1159c19..e902f4f 100644 --- a/examples/h5ff_client_obj.c +++ b/examples/h5ff_client_obj.c @@ -142,17 +142,17 @@ int main(int argc, char **argv) { ret = H5TRfinish(tid2, H5P_DEFAULT, &rid2, e_stack);
assert(0 == ret);
+ assert(H5Gclose_ff(gid, e_stack) == 0);
+ assert(H5Mclose_ff(map, e_stack) == 0);
+ assert(H5Tclose_ff(dtid, e_stack) == 0);
+ assert(H5Dclose_ff(did, e_stack) == 0);
+
/* release container version 2. This is async. */
ret = H5RCrelease(rid_temp, e_stack);
assert(0 == ret);
ret = H5RCclose(rid_temp);
assert(0 == ret);
- assert(H5Gclose_ff(gid, e_stack) == 0);
- assert(H5Dclose_ff(did, e_stack) == 0);
- assert(H5Tclose_ff(dtid, e_stack) == 0);
- assert(H5Mclose_ff(map, e_stack) == 0);
-
version = 2;
}
diff --git a/examples/h5ff_client_vl_data.c b/examples/h5ff_client_vl_data.c index 79184b6..b82f40c 100644 --- a/examples/h5ff_client_vl_data.c +++ b/examples/h5ff_client_vl_data.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) { "Four score and seven years ago our forefathers brought forth on this continent a new nation,", "conceived in liberty and dedicated to the proposition that all men are created equal.", "Now we are engaged in a great civil war,", - "testing whether that nation or any nation so conceived and so dedicated can long endure." + "testing whether that nation or any nation so conceived and so dedicated can long endure.", "Abraham Lincoln" }; /* Information to write */ char *str_rdata[5]; @@ -287,7 +287,7 @@ int main(int argc, char **argv) { H5Dvlen_reclaim(vl_dtid, sid, H5P_DEFAULT, wdata); fprintf(stderr, "Reading VL Strings: \n"); - for(i=0 ; i<4 ; i++) { + for(i=0 ; i<5 ; i++) { fprintf(stderr, "%s\n", str_rdata[i]); } diff --git a/examples/run_ff_tests.sh.in b/examples/run_ff_tests.sh.in index bfc8c87..c691b00 100755 --- a/examples/run_ff_tests.sh.in +++ b/examples/run_ff_tests.sh.in @@ -63,5 +63,13 @@ echo "Finished object test-----------------------------------------------" [ $RETVAL -ne 0 ] && echo "FAILED-----------------------------------------------" sleep 2 +echo "Starting VL datatypes for datasets test-----------------------------------------------" +mpiexec -np $1 ./h5ff_server &> ff_output/server_obj & +sleep 2 && +mpiexec -np $2 ./h5ff_client_vl_data +RETVAL=$? +echo "Finished object test-----------------------------------------------" +[ $RETVAL -ne 0 ] && echo "FAILED-----------------------------------------------" + echo "FF tests DONE ---------------------------------------------------" exit diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f11f2ed..4a734bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -656,6 +656,7 @@ IF (HDF5_ENABLE_EFF) SET (H5VL_SRCS ${H5VL_SRCS} ${HDF5_SRC_DIR}/H5VLiod.c + ${HDF5_SRC_DIR}/H5VLiod_common.c ${HDF5_SRC_DIR}/H5VLiod_client.c ${HDF5_SRC_DIR}/H5VLiod_server.c ${HDF5_SRC_DIR}/H5VLiod_util.c diff --git a/src/H5VLiod.c b/src/H5VLiod.c index 6c7fca2..05f31d6 100644 --- a/src/H5VLiod.c +++ b/src/H5VLiod.c @@ -551,8 +551,7 @@ H5VL__iod_create_and_forward(hg_id_t op_id, H5RQ_type_t op_type, hg_status_t status; /* test the operation status */ - ret = HG_Wait(*((hg_request_t *)request->req), HG_MAX_IDLE_TIME, - &status); + ret = HG_Wait(*((hg_request_t *)request->req), HG_MAX_IDLE_TIME, &status); if(HG_FAIL == ret) { fprintf(stderr, "failed to wait on request\n"); request->status = H5ES_STATUS_FAIL; @@ -564,10 +563,11 @@ H5VL__iod_create_and_forward(hg_id_t op_id, H5RQ_type_t op_type, request->state = H5VL_IOD_COMPLETED; } } - } else { - /* Synchronously wait on the request */ - if(H5VL_iod_request_wait(request_obj->file, request) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on HG request"); + } + else { + /* Synchronously wait on the request */ + if(H5VL_iod_request_wait(request_obj->file, request) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on HG request"); } /* Since the operation is synchronous, return FAIL if the status failed */ @@ -723,8 +723,7 @@ EFF_init(MPI_Comm comm, MPI_Info UNUSED info) H5VL_DSET_CREATE_ID = MERCURY_REGISTER("dset_create", dset_create_in_t, dset_create_out_t); H5VL_DSET_OPEN_ID = MERCURY_REGISTER("dset_open", dset_open_in_t, dset_open_out_t); H5VL_DSET_READ_ID = MERCURY_REGISTER("dset_read", dset_io_in_t, dset_read_out_t); - H5VL_DSET_GET_VL_SIZE_ID = MERCURY_REGISTER("dset_get_vl_size", - dset_get_vl_size_in_t, dset_read_out_t); + H5VL_DSET_GET_VL_SIZE_ID = MERCURY_REGISTER("dset_get_vl_size", dset_io_in_t, dset_read_out_t); H5VL_DSET_WRITE_ID = MERCURY_REGISTER("dset_write", dset_io_in_t, ret_t); H5VL_DSET_SET_EXTENT_ID = MERCURY_REGISTER("dset_set_extent", dset_set_extent_in_t, ret_t); @@ -1779,6 +1778,7 @@ done: if(file->comm || file->info) if(H5FD_mpi_comm_info_free(&file->comm, &file->info) < 0) HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "Communicator/Info free failed") + if(file->fapl_id != FAIL && H5I_dec_ref(file->fapl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); if(file->remote_file.fcpl_id != FAIL && @@ -2914,21 +2914,22 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, { H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; dset_io_in_t input; - dset_get_vl_size_in_t input_vl; H5P_genplist_t *plist = NULL; hg_bulk_t *bulk_handle = NULL; - H5VL_iod_read_status_t *status = NULL; H5S_t *mem_space = NULL; H5S_t *file_space = NULL; char fake_char; size_t type_size; /* size of mem type */ hssize_t nelmts; /* num elements in mem dataspace */ - H5VL_iod_io_info_t *info = NULL; - hbool_t is_vl_data = FALSE; + H5VL_iod_read_info_t *info = NULL; + H5VL_iod_read_status_t *status = NULL; hid_t rcxt_id; H5RC_t *rc = NULL; size_t num_parents = 0; H5VL_iod_request_t **parent_reqs = NULL; + H5VL_iod_type_info_t *type_info = NULL; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -3039,10 +3040,32 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); - /* compute checksum and create bulk handle */ - if(H5VL_iod_pre_read(mem_type_id, mem_space, buf, - bulk_handle, &is_vl_data) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't generate read parameters"); + if(NULL == (type_info = (H5VL_iod_type_info_t *)H5MM_malloc(sizeof(H5VL_iod_type_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate type info struct"); + + /* Get type info */ + if(H5VL_iod_get_type_info(mem_type_id, type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + /* Check if there are any vlen types. If so, guess number of vl + * lengths, allocate array, and register with bulk buffer. Otherwise, + * register data buffer. */ + if(type_info->vls) { + /* For now, just guess one segment for each vl in top level */ + vl_lengths_size = 8 * nelmts * type_info->num_vls; + + /* Allocate vl_lengths */ + if(NULL == (vl_lengths = (char *)HDmalloc(vl_lengths_size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate vlen lengths buffer"); + + /* Register vl_lengths buffer */ + HG_Bulk_handle_create(vl_lengths, vl_lengths_size, HG_BULK_READWRITE, bulk_handle); + } /* end if */ + else { + /* for non vlen data, create the bulk handle to recieve the data in */ + if(H5VL_iod_pre_read(mem_type_id, mem_space, buf, nelmts, bulk_handle) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't generate read parameters"); + } if(NULL == (parent_reqs = (H5VL_iod_request_t **) H5MM_malloc(sizeof(H5VL_iod_request_t *)))) @@ -3053,56 +3076,46 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, parent_reqs, &num_parents) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); - if(!is_vl_data) { - /* Fill input structure for reading data */ - input.coh = dset->common.file->remote_file.coh; - input.iod_oh = dset->remote_dset.iod_oh; - input.iod_id = dset->remote_dset.iod_id; - input.mdkv_id = dset->remote_dset.mdkv_id; - input.bulk_handle = *bulk_handle; - input.checksum = 0; - input.dxpl_id = dxpl_id; - if(H5S_ALL == file_space_id) - input.space_id = dset->remote_dset.space_id; - else - input.space_id = file_space_id; - input.dset_type_id = dset->remote_dset.type_id; - input.mem_type_id = mem_type_id; - input.rcxt_num = rc->c_version; - input.cs_scope = dset->common.file->md_integrity_scope; - input.trans_num = 0; - } - else { - /* Fill input structure for retrieving the buffer size needed to read */ - input_vl.coh = dset->common.file->remote_file.coh; - input_vl.iod_oh = dset->remote_dset.iod_oh; - input_vl.iod_id = dset->remote_dset.iod_id; - input_vl.mdkv_id = dset->remote_dset.mdkv_id; - input_vl.dxpl_id = dxpl_id; - if(H5S_ALL == file_space_id) - input_vl.space_id = dset->remote_dset.space_id; - else - input_vl.space_id = file_space_id; - input_vl.mem_type_id = mem_type_id; - input_vl.rcxt_num = rc->c_version; - input_vl.cs_scope = dset->common.file->md_integrity_scope; - } + /* Fill input structure for reading data */ + input.coh = dset->common.file->remote_file.coh; + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; + input.bulk_handle = *bulk_handle; + input.vl_len_bulk_handle = HG_BULK_NULL; + input.checksum = 0; + input.dxpl_id = dxpl_id; + if(H5S_ALL == file_space_id) + input.space_id = dset->remote_dset.space_id; + else + input.space_id = file_space_id; + input.dset_type_id = dset->remote_dset.type_id; + input.mem_type_id = mem_type_id; + input.trans_num = 0; + input.rcxt_num = rc->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + input.axe_id = g_axe_id; /* allocate structure to receive status of read operation (contains return value, checksum, and buffer size) */ - status = (H5VL_iod_read_status_t *)malloc(sizeof(H5VL_iod_read_status_t)); + if(NULL == (status = (H5VL_iod_read_status_t *)H5MM_malloc(sizeof(H5VL_iod_read_status_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate Read status struct"); /* setup info struct for I/O request. This is to manage the I/O operation once the wait is called. */ - if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_calloc(sizeof(H5VL_iod_io_info_t)))) + if(NULL == (info = (H5VL_iod_read_info_t *)H5MM_calloc(sizeof(H5VL_iod_read_info_t)))) HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); info->status = status; info->bulk_handle = bulk_handle; + info->type_info = type_info; + info->vl_lengths = vl_lengths; + info->vl_lengths_size = vl_lengths_size; info->buf_ptr = buf; info->nelmts = nelmts; info->type_size = type_size; info->cs_ptr = NULL; + info->axe_id = g_axe_id; /* store a copy of the dataspace selection to be able to calculate the checksum later */ if(NULL == (info->space = H5S_copy(mem_space, FALSE, TRUE))) @@ -3117,27 +3130,27 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, /* If the read is of VL data, then we need the read parameters to perform the actual read when the wait is called (i.e. when we retrieve the buffer size) */ - if(is_vl_data) { - if((info->file_space_id = H5Scopy(input_vl.space_id)) < 0) + if(type_info->vls) { + if((info->file_space_id = H5Scopy(input.space_id)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace"); if((info->mem_type_id = H5Tcopy(mem_type_id)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype"); if((info->dxpl_id = H5P_copy_plist((H5P_genplist_t *)plist, TRUE)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy dxpl"); - info->peer = PEER; + info->ion_target = PEER; info->read_id = H5VL_DSET_READ_ID; } #if H5VL_IOD_DEBUG - if(!is_vl_data) + if(!type_info->vls) printf("Dataset Read, axe id %"PRIu64"\n", g_axe_id); else - printf("Dataset GET size, axe id %"PRIu64"\n", g_axe_id); + printf("Dataset GET size, axe id %"PRIu64"\n", g_axe_id + 1); #endif /* forward the call to the IONs */ - if(!is_vl_data) { + if(!type_info->vls) { if(H5VL__iod_create_and_forward(H5VL_DSET_READ_ID, HG_DSET_READ, (H5VL_iod_object_t *)dset, 0, num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, @@ -3145,10 +3158,13 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset read"); } else { + /* allocate an axe_id for the read operation to follow */ + g_axe_id ++; + if(H5VL__iod_create_and_forward(H5VL_DSET_GET_VL_SIZE_ID, HG_DSET_GET_VL_SIZE, (H5VL_iod_object_t *)dset, 0, num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, - &input_vl, status, info, req) < 0) + &input, status, info, req) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset get VL size"); } @@ -3178,18 +3194,20 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, dset_io_in_t input; H5P_genplist_t *plist = NULL; hg_bulk_t *bulk_handle = NULL; + hg_bulk_t *vl_len_bulk_handle = NULL; + hg_bulk_segment_t *vl_segments = NULL; + char *vl_lengths = NULL; H5S_t *mem_space = NULL; H5S_t *file_space = NULL; char fake_char; int *status = NULL; - H5VL_iod_io_info_t *info; /* info struct used to manage I/O parameters once the operation completes*/ + H5VL_iod_write_info_t *info; /* info struct used to manage I/O parameters once the operation completes*/ uint64_t internal_cs; /* internal checksum calculated in this function */ - size_t *vl_string_len = NULL; /* array that will contain lengths of strings if the datatype is a VL string type */ H5VL_iod_request_t **parent_reqs = NULL; size_t num_parents = 0; hid_t trans_id; H5TR_t *tr = NULL; - uint64_t user_cs; + uint64_t user_cs, vl_len_cs; uint32_t raw_cs_scope = 0; herr_t ret_value = SUCCEED; @@ -3291,11 +3309,13 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, /* allocate a bulk data transfer handle */ if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + if(NULL == (vl_len_bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); if(raw_cs_scope) { /* compute checksum and create bulk handle */ - if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, - &internal_cs, bulk_handle, &vl_string_len) < 0) + if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, &internal_cs, &vl_len_cs, + bulk_handle, vl_len_bulk_handle, &vl_segments, &vl_lengths) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't generate write parameters"); } else { @@ -3303,8 +3323,8 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, printf("NO DATA INTEGRITY CHECKS ON RAW DATA WRITTEN\n"); #endif /* compute checksum and create bulk handle */ - if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, - NULL, bulk_handle, &vl_string_len) < 0) + if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, NULL, NULL, bulk_handle, + vl_len_bulk_handle, &vl_segments, &vl_lengths) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't generate write parameters"); internal_cs = 0; } @@ -3335,6 +3355,7 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, input.iod_id = dset->remote_dset.iod_id; input.mdkv_id = dset->remote_dset.mdkv_id; input.bulk_handle = *bulk_handle; + input.vl_len_bulk_handle = *vl_len_bulk_handle; input.checksum = internal_cs; input.dxpl_id = dxpl_id; if(H5S_ALL == file_space_id) @@ -3355,16 +3376,16 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, /* setup info struct for I/O request This is to manage the I/O operation once the wait is called. */ - if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_calloc(sizeof(H5VL_iod_io_info_t)))) + if(NULL == (info = (H5VL_iod_write_info_t *)H5MM_calloc(sizeof(H5VL_iod_write_info_t)))) HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); - info->status = status; info->bulk_handle = bulk_handle; - info->vl_string_len = vl_string_len; + info->vl_len_bulk_handle = vl_len_bulk_handle; + info->vl_lengths = vl_lengths; + info->vl_segments = vl_segments; if(H5VL__iod_create_and_forward(H5VL_DSET_WRITE_ID, HG_DSET_WRITE, - (H5VL_iod_object_t *)dset, 0, - num_parents, parent_reqs, + (H5VL_iod_object_t *)dset, 0, num_parents, parent_reqs, (H5VL_iod_req_info_t *)tr, &input, status, info, req) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset write"); @@ -4491,9 +4512,9 @@ H5VL_iod_attribute_read(void *_attr, hid_t type_id, void *buf, hid_t dxpl_id, vo H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)_attr; attr_io_in_t input; hg_bulk_t *bulk_handle = NULL; - H5VL_iod_read_status_t *status = NULL; + int *status = NULL; size_t size; - H5VL_iod_io_info_t *info = NULL; + H5VL_iod_attr_io_info_t *info = NULL; hid_t rcxt_id; H5RC_t *rc = NULL; size_t num_parents = 0; @@ -4575,11 +4596,11 @@ H5VL_iod_attribute_read(void *_attr, hid_t type_id, void *buf, hid_t dxpl_id, vo input.trans_num = 0; /* allocate structure to receive status of read operation (contains return value and checksum */ - status = (H5VL_iod_read_status_t *)malloc(sizeof(H5VL_iod_read_status_t)); + status = (int *)malloc(sizeof(int)); /* setup info struct for I/O request. This is to manage the I/O operation once the wait is called. */ - if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_io_info_t)))) + if(NULL == (info = (H5VL_iod_attr_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_attr_io_info_t)))) HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a request"); info->status = status; info->bulk_handle = bulk_handle; @@ -4623,7 +4644,7 @@ H5VL_iod_attribute_write(void *_attr, hid_t type_id, const void *buf, hid_t dxpl int *status = NULL; size_t size; uint64_t internal_cs; /* internal checksum calculated in this function */ - H5VL_iod_io_info_t *info; + H5VL_iod_attr_io_info_t *info; size_t num_parents = 0; hid_t trans_id; H5TR_t *tr = NULL; @@ -4710,7 +4731,7 @@ H5VL_iod_attribute_write(void *_attr, hid_t type_id, const void *buf, hid_t dxpl /* setup info struct for I/O request This is to manage the I/O operation once the wait is called. */ - if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_io_info_t)))) + if(NULL == (info = (H5VL_iod_attr_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_attr_io_info_t)))) HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a request"); info->status = status; info->bulk_handle = bulk_handle; diff --git a/src/H5VLiod_attr.c b/src/H5VLiod_attr.c index 99dfbf4..602060d 100644 --- a/src/H5VLiod_attr.c +++ b/src/H5VLiod_attr.c @@ -531,7 +531,8 @@ H5VL_iod_server_attr_read_cb(AXE_engine_t UNUSED axe_engine, file_desc = hslabs; /* read from array object */ - ret = iod_array_read(iod_oh, rtid, NULL, mem_desc, &file_desc, &iod_cs, NULL); + ret = iod_array_read(iod_oh, rtid, NULL, mem_desc, &file_desc, + NULL/* MSC - need IOD -&iod_cs*/, NULL); if(ret < 0) { fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); @@ -734,7 +735,7 @@ H5VL_iod_server_attr_write_cb(AXE_engine_t UNUSED axe_engine, /* set the file descriptor */ file_desc = hslabs; - if(cs_scope & H5_CHECKSUM_IOD) { + if(0) {// MSC - IOD fix - cs_scope & H5_CHECKSUM_IOD) { attr_cs = H5_checksum_crc64(buf, size); /* write from array object */ @@ -983,7 +984,7 @@ H5VL_iod_server_attr_rename_cb(AXE_engine_t UNUSED axe_engine, kv.key = (void *)old_name; kv.key_len = strlen(old_name); kvs.kv = &kv; - kvs.cs = &cs; + kvs.cs = NULL; //MSC - need IOD - &cs; kvs.ret = &ret; if(iod_kv_unlink_keys(attr_kv_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); @@ -1139,7 +1140,7 @@ H5VL_iod_server_attr_remove_cb(AXE_engine_t UNUSED axe_engine, kv.key = (void *)attr_name; kv.key_len = strlen(attr_name); kvs.kv = &kv; - kvs.cs = &cs; + kvs.cs = NULL; //MSC - need IOD - &cs; kvs.ret = &ret; if(iod_kv_unlink_keys(attr_kv_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); diff --git a/src/H5VLiod_client.c b/src/H5VLiod_client.c index 629ce7f..dabf780 100644 --- a/src/H5VLiod_client.c +++ b/src/H5VLiod_client.c @@ -53,12 +53,6 @@ typedef struct { size_t *str_len; /* used only for VL strings */ } H5VL_iod_pre_write_t; -static herr_t H5VL__iod_pre_write_cb(void UNUSED *elem, hid_t type_id, unsigned ndim, - const hsize_t *point, void *_udata); - -static herr_t H5VL__iod_vl_read_finalize(size_t buf_size, void *read_buf, void *user_buf, - H5S_t *mem_space, hid_t mem_type_id, hid_t dset_type_id); - static herr_t H5VL__iod_vl_map_get_finalize(size_t buf_size, void *read_buf, void *user_buf, hid_t mem_type_id); @@ -651,9 +645,8 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) break; } case HG_DSET_WRITE: - case HG_DSET_READ: { - H5VL_iod_io_info_t *info = (H5VL_iod_io_info_t *)req->data; + H5VL_iod_write_info_t *info = (H5VL_iod_write_info_t *)req->data; /* Free memory handle */ if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { @@ -661,22 +654,59 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) req->status = H5ES_STATUS_FAIL; req->state = H5VL_IOD_COMPLETED; } - if(HG_DSET_WRITE == req->type && SUCCEED != *((int *)info->status)) { + + if(*info->vl_len_bulk_handle != HG_BULK_NULL && + HG_SUCCESS != HG_Bulk_handle_free(*info->vl_len_bulk_handle)) { + fprintf(stderr, "failed to free dataset bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(SUCCEED != *((int *)info->status)) { HERROR(H5E_FUNC, H5E_CANTINIT, "Errrr! Dataset Write Failure Reported from Server\n"); req->status = H5ES_STATUS_FAIL; req->state = H5VL_IOD_COMPLETED; } - else if(HG_DSET_READ == req->type) { - H5VL_iod_read_status_t *read_status = (H5VL_iod_read_status_t *)info->status; - if(SUCCEED != read_status->ret) { - HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); - req->status = H5ES_STATUS_FAIL; - req->state = H5VL_IOD_COMPLETED; - } - else { + if(info->vl_segments) { + free(info->vl_segments); + info->vl_segments = NULL; + } + if(info->vl_lengths) { + free(info->vl_lengths); + info->vl_lengths = NULL; + } + + free(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info->vl_len_bulk_handle = (hg_bulk_t *)H5MM_xfree(info->vl_len_bulk_handle); + info = (H5VL_iod_write_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_READ: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + H5VL_iod_read_status_t *read_status = (H5VL_iod_read_status_t *)info->status; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free dataset bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + if(SUCCEED != read_status->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + uint32_t raw_cs_scope = info->raw_cs_scope; + + if(raw_cs_scope) { uint64_t internal_cs = 0; - uint32_t raw_cs_scope = info->raw_cs_scope; /* calculate a checksum for the data recieved */ internal_cs = H5S_checksum(info->buf_ptr, info->type_size, @@ -696,8 +726,6 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) printf("NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA READ\n"); } #endif - if(info->space && H5S_close(info->space) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); /* If the app gave us a buffer to store the checksum, then put it there */ if(info->cs_ptr) @@ -705,46 +733,69 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) } } - free(info->status); - info->status = NULL; + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + read_status = (H5VL_iod_read_status_t *)H5MM_xfree(read_status); info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); - - if(info->vl_string_len) - free(info->vl_string_len); - - info = (H5VL_iod_io_info_t *)H5MM_xfree(info); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); req->data = NULL; H5VL_iod_request_delete(file, req); break; } case HG_DSET_GET_VL_SIZE: { - H5VL_iod_io_info_t *info = (H5VL_iod_io_info_t *)req->data; + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; H5VL_iod_read_status_t *status = (H5VL_iod_read_status_t *)info->status; - if(SUCCEED != status->ret) { + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle) || + SUCCEED != status->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); req->status = H5ES_STATUS_FAIL; req->state = H5VL_IOD_COMPLETED; + + if(H5Sclose(info->file_space_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(H5Tclose(info->mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + status = (H5VL_iod_read_status_t *)H5MM_xfree(status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); } else { dset_io_in_t input; - void *read_buf; H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; - uint64_t internal_cs = 0; - size_t buf_size = status->buf_size; hid_t rcxt_id; H5RC_t *rc; H5P_genplist_t *plist = NULL; - H5VL_iod_read_status_t vl_status; - - if(NULL == (read_buf = (void *)HDmalloc(buf_size))) - HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate VL recieve buffer"); - - /* Register memory with bulk_handle */ - if(HG_SUCCESS != HG_Bulk_handle_create(read_buf, buf_size, - HG_BULK_READWRITE, info->bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + hg_request_t hg_req; + hg_status_t hg_status; + + /* MSC - Need to fix this to allow for nested VLs */ + HDassert(info->vl_lengths_size == status->buf_size); + + /* Create segments from vl lengths */ + if(H5VL_iod_create_segments_recv((char *)info->buf_ptr, info->type_info, + (size_t)info->nelmts, &segments, &num_segments, + info->vl_lengths, info->vl_lengths_size, + NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create segments for bulk data transfer"); + HDassert(segments); + + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READWRITE, + info->bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data handle"); /* get the context ID */ if(NULL == (plist = (H5P_genplist_t *)H5I_object(info->dxpl_id))) @@ -754,76 +805,66 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) /* get the RC object */ if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); /* Fill input structure for reading data */ input.coh = file->remote_file.coh; input.iod_oh = dset->remote_dset.iod_oh; input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; input.bulk_handle = *info->bulk_handle; + input.vl_len_bulk_handle = HG_BULK_NULL; input.checksum = 0; input.dxpl_id = info->dxpl_id; input.space_id = info->file_space_id; input.mem_type_id = info->mem_type_id; input.dset_type_id = dset->remote_dset.type_id; - - if(H5VL__iod_create_and_forward(info->read_id, HG_DSET_READ, - (H5VL_iod_object_t *)dset, 0, 0, NULL, - (H5VL_iod_req_info_t *)rc, - &input, &vl_status, NULL, NULL) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset read"); - - /* Free memory handle */ - if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { - HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free dataset bulk handle\n"); - req->status = H5ES_STATUS_FAIL; - req->state = H5VL_IOD_COMPLETED; - } - - if(SUCCEED != vl_status.ret) { - HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); + input.rcxt_num = rc->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + input.trans_num = 0; + input.axe_id = info->axe_id + 1; + input.axe_info.axe_id = info->axe_id; + input.axe_info.start_range = 0; + input.axe_info.count = 0; + input.axe_info.num_parents = 0; + input.axe_info.parent_axe_ids = NULL; + + /* forward the call to the ION */ + if(HG_Forward(info->ion_target, info->read_id, &input, info->status, &hg_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + + if(HG_FAIL == HG_Wait(hg_req, HG_MAX_IDLE_TIME, &hg_status)) { + fprintf(stderr, "failed to wait on request\n"); req->status = H5ES_STATUS_FAIL; req->state = H5VL_IOD_COMPLETED; } - /* calculate a checksum for the data recieved */ - internal_cs = H5_checksum_crc64(read_buf, buf_size); + HG_Request_free(hg_req); + HG_Bulk_handle_free(*info->bulk_handle); - /* scatter the data into the user's buffer */ - if(H5VL__iod_vl_read_finalize(buf_size, read_buf, (void *)info->buf_ptr, - info->space, info->mem_type_id, - dset->remote_dset.type_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to store VL data in user buffer"); - - HDfree(read_buf); - - /* verify data integrity */ - if(internal_cs != vl_status.cs) { - HERROR(H5E_FUNC, H5E_CANTINIT, - "Errrrr! Dataset Read integrity failure (expecting %"PRIu64" got %"PRIu64").\n", - internal_cs, status->cs); - req->status = H5ES_STATUS_FAIL; - req->state = H5VL_IOD_COMPLETED; + if(segments) { + free(segments); + segments = NULL; } - - /* If the app gave us a buffer to store the checksum, then put it there */ - if(info->cs_ptr) - *info->cs_ptr = internal_cs; } - if(info->space && H5S_close(info->space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(info->vl_lengths) { + HDfree(info->vl_lengths); + info->vl_lengths = NULL; + } if(H5Sclose(info->file_space_id) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); if(H5Tclose(info->mem_type_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); if(H5Pclose(info->dxpl_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); - - free(info->status); - info->status = NULL; + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + status = (H5VL_iod_read_status_t *)H5MM_xfree(status); info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); - info = (H5VL_iod_io_info_t *)H5MM_xfree(info); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); req->data = NULL; H5VL_iod_request_delete(file, req); break; @@ -831,7 +872,7 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) case HG_ATTR_WRITE: case HG_ATTR_READ: { - H5VL_iod_io_info_t *info = (H5VL_iod_io_info_t *)req->data; + H5VL_iod_attr_io_info_t *info = (H5VL_iod_attr_io_info_t *)req->data; /* Free memory handle */ if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { @@ -845,10 +886,10 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) req->state = H5VL_IOD_COMPLETED; } - free(info->status); + HDfree(info->status); info->status = NULL; info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); - info = (H5VL_iod_io_info_t *)H5MM_xfree(info); + info = (H5VL_iod_attr_io_info_t *)H5MM_xfree(info); req->data = NULL; H5VL_iod_request_delete(file, req); break; @@ -1605,23 +1646,72 @@ H5VL_iod_request_cancel(H5VL_iod_file_t *file, H5VL_iod_request_t *req) break; } case HG_DSET_WRITE: - case HG_DSET_READ: - case HG_ATTR_WRITE: - case HG_ATTR_READ: + { + H5VL_iod_write_info_t *info = (H5VL_iod_write_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + fprintf(stderr, "failed to free bulk handle\n"); + } + + if(info->vl_segments) { + HDfree(info->vl_segments); + info->vl_segments = NULL; + } + if(info->vl_lengths) { + HDfree(info->vl_lengths); + info->vl_lengths = NULL; + } + + HDfree(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info->vl_len_bulk_handle = (hg_bulk_t *)H5MM_xfree(info->vl_len_bulk_handle); + info = (H5VL_iod_write_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } case HG_DSET_GET_VL_SIZE: { - H5VL_iod_io_info_t *info = (H5VL_iod_io_info_t *)req->data; + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + + if(H5Sclose(info->file_space_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(H5Tclose(info->mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + } + case HG_DSET_READ: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; /* Free memory handle */ if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free bulk handle\n"); } - free(info->status); + + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + info->status = (H5VL_iod_read_status_t *)H5MM_xfree(info->status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_WRITE: + case HG_ATTR_READ: + { + H5VL_iod_attr_io_info_t *info = (H5VL_iod_attr_io_info_t *)req->data; + + HDfree(info->status); info->status = NULL; info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); - if(info->vl_string_len) - free(info->vl_string_len); - info = (H5VL_iod_io_info_t *)H5MM_xfree(info); + info = (H5VL_iod_attr_io_info_t *)H5MM_xfree(info); req->data = NULL; H5VL_iod_request_delete(file, req); break; @@ -2107,7 +2197,8 @@ H5VL_iod_gen_obj_id(int myrank, int nranks, uint64_t cur_index, FUNC_ENTER_NOAPI_NOINIT - /* determine first the rank of the object with the first 59 bits */ + /* determine first the rank of the object with the first 60 bits + (IOD owns 60,61,62,63). */ tmp_id = (uint32_t)myrank + ((uint32_t)nranks * cur_index); /* toggle the object type bits */ @@ -2119,6 +2210,8 @@ H5VL_iod_gen_obj_id(int myrank, int nranks, uint64_t cur_index, IOD_OBJID_SETTYPE(tmp_id, IOD_OBJ_KV) break; case IOD_OBJ_BLOB: + /* This is for HDF5 committed datatypes and not for VLEN BLOBs */ + tmp_id &= ~(((uint64_t)0x1) << 59); IOD_OBJID_SETTYPE(tmp_id, IOD_OBJ_BLOB) break; case IOD_OBJ_ANY: @@ -2137,110 +2230,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5VL__iod_pre_write_cb - * - * The callback to the H5Diterate routine called in - * H5VL__iod_pre_write. This will generate the offset,length pair for - * the serialzed form of the VL data. - * - * Return: Success: SUCCEED - * Failure: Negative - * - * Programmer: Mohamad Chaarawi - * August, 2013 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5VL__iod_pre_write_cb(void UNUSED *elem, hid_t type_id, unsigned UNUSED ndim, - const hsize_t UNUSED *point, void *_udata) -{ - H5VL_iod_pre_write_t *udata = (H5VL_iod_pre_write_t *)_udata; - H5T_t *dt = NULL; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT - - /* Check args */ - if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") - - switch(H5T_get_class(dt, FALSE)) { - case H5T_INTEGER: - case H5T_FLOAT: - case H5T_TIME: - case H5T_BITFIELD: - case H5T_OPAQUE: - case H5T_ENUM: - case H5T_ARRAY: - case H5T_NO_CLASS: - case H5T_REFERENCE: - case H5T_NCLASSES: - case H5T_COMPOUND: - HDassert(0 && fprintf(stderr, "Should not be here \n")); - break; - - case H5T_STRING: - { - char **buf; - int i = udata->curr_seq/2; - - HDassert(H5T_is_variable_str(dt)); - - buf = (char **)udata->buf_ptr; - - udata->str_len[i] = HDstrlen(buf[i]) + 1; - udata->buf_size += udata->str_len[i] + sizeof(size_t); - - udata->off[udata->curr_seq] = (void *)(udata->str_len+i); - udata->len[udata->curr_seq] = sizeof(size_t); - udata->curr_seq ++; - - udata->off[udata->curr_seq] = (void *)buf[i]; - udata->len[udata->curr_seq] = udata->str_len[i]; - udata->curr_seq ++; - - break; - } - case H5T_VLEN: - { - H5T_t *super = NULL; - size_t elmt_size; - hvl_t *vl; - - vl = (hvl_t *)udata->buf_ptr; - - if(NULL == (super = H5T_get_super(dt))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); - - elmt_size = H5T_get_size(super) * vl->len; - udata->buf_size += elmt_size + sizeof(size_t); - - udata->off[udata->curr_seq] = (void *)udata->buf_ptr; - udata->len[udata->curr_seq] = sizeof(size_t); - udata->curr_seq ++; - - udata->off[udata->curr_seq] = (void *)(vl->p); - udata->len[udata->curr_seq] = elmt_size; - udata->curr_seq ++; - - vl ++; - udata->buf_ptr = (uint8_t *)vl; - - H5T_close(super); - - break; - } - default: - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL_iod_pre_write_cb */ - - -/*------------------------------------------------------------------------- * Function: H5VL_iod_pre_write * * Depending on the type, this routine generates all the necessary @@ -2258,218 +2247,127 @@ done: herr_t H5VL_iod_pre_write(hid_t type_id, H5S_t *space, const void *buf, /*out*/uint64_t *_checksum, + /*out*/uint64_t *_vlen_checksum, /*out*/hg_bulk_t *bulk_handle, - /*out*/size_t **vl_str_len) + /*out*/hg_bulk_t *vl_len_bulk_handle, + /*out*/hg_bulk_segment_t **_vl_segments, + /*out*/char **_vl_lengths) { hsize_t buf_size = 0; uint64_t checksum = 0; - H5T_t *dt = NULL; size_t nelmts; - H5T_class_t dt_class; + H5VL_iod_type_info_t type_info; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT - if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + /* Get type info */ + if(H5VL_iod_get_type_info(type_id, &type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); nelmts = (size_t)H5S_GET_SELECT_NPOINTS(space); - dt_class = H5T_get_class(dt, FALSE); - *vl_str_len = NULL; - - switch(dt_class) { - case H5T_STRING: - /* If this is a variable length string, serialize it - through a Mercury Segmented handle */ - if(H5T_is_variable_str(dt)) { - char bogus; /* bogus value to pass to H5Diterate() */ - H5VL_iod_pre_write_t udata; - hg_bulk_segment_t *bulk_segments = NULL; - int u; - - /* allocate array that hold every string's length */ - udata.str_len = (size_t *)malloc(sizeof(size_t) * nelmts); - - /* set H5Diterate op_data */ - udata.buf_size = 0; - udata.buf_ptr = (uint8_t *)buf; - udata.off = (void **)malloc(nelmts * 2 * sizeof(void *)); - udata.len = (size_t *)malloc(nelmts * 2 * sizeof(size_t)); - udata.curr_seq = 0; - - /* iterate over every element and compute it's size adding it to - the udata buf_size */ - if(H5D__iterate(&bogus, type_id, space, H5VL__iod_pre_write_cb, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to compute buffer size"); - - buf_size = udata.buf_size; - - /* Register memory with segmented HG handle */ - bulk_segments = (hg_bulk_segment_t *)malloc((size_t)udata.curr_seq * - sizeof(hg_bulk_segment_t)); - - for (u = 0; u <udata.curr_seq ; u++) { - bulk_segments[u].address = udata.off[u]; - bulk_segments[u].size = udata.len[u]; - } - - /* create Bulk handle */ - if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, (size_t)udata.curr_seq, - HG_BULK_READWRITE, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); - - free(bulk_segments); - bulk_segments = NULL; - - if(_checksum) - checksum = H5_checksum_crc64_fragments(udata.off, udata.len, - (size_t)udata.curr_seq); - /* cleanup */ - if(udata.curr_seq) { - free(udata.len); - udata.len = NULL; - free(udata.off); - udata.off = NULL; - } - - *vl_str_len = udata.str_len; - - break; - } - case H5T_INTEGER: - case H5T_FLOAT: - case H5T_TIME: - case H5T_BITFIELD: - case H5T_OPAQUE: - case H5T_ENUM: - case H5T_ARRAY: - case H5T_NO_CLASS: - case H5T_REFERENCE: - case H5T_NCLASSES: - case H5T_COMPOUND: - /* Data is not variable length, so no need to iterate over - every element in selection */ - /* MSC - This is not correct. Compound/Array can contian - VL datatypes, but for now we don't support that. Need - to check for that too */ - { - size_t type_size; - - type_size = H5T_get_size(dt); + if(type_info.vls) { + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; + + HDassert(_vl_segments); + HDassert(_vl_lengths); + + /* Create segments and vl lengths */ + if(H5VL_iod_create_segments_send((char *)buf, &type_info, nelmts, &segments, &num_segments, + &vl_lengths, &vl_lengths_size, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create segments for bulk data transfer"); + HDassert(segments); + HDassert(vl_lengths); + + /* Register vl lengths */ + if(HG_SUCCESS != HG_Bulk_handle_create(vl_lengths, vl_lengths_size, + HG_BULK_READ_ONLY, vl_len_bulk_handle)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data Handle for vlen lengths"); + + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data handle"); + + if(_checksum) + checksum = H5_checksum_crc64_segments(segments, num_segments); + if(_vlen_checksum) + *_vlen_checksum = H5_checksum_crc64(vl_lengths, vl_lengths_size); + + *_vl_segments = segments; + *_vl_lengths = vl_lengths; + } + else { + H5T_t *dt = NULL; + size_t type_size; - buf_size = type_size * nelmts; + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") - if(_checksum) { - checksum = H5S_checksum(buf, type_size, nelmts, space); - } + *vl_len_bulk_handle = HG_BULK_NULL; + type_size = H5T_get_size(dt); - /* If the memory selection is contiguous, create simple HG Bulk Handle */ - if(H5S_select_is_contiguous(space)) { - /* Register memory with bulk_handle */ - if(HG_SUCCESS != HG_Bulk_handle_create(buf, (size_t)buf_size, - HG_BULK_READ_ONLY, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); - } + buf_size = type_size * nelmts; - /* if the memory selection is non-contiguous, create a segmented selection */ - else { - hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ - size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ - size_t count = 0; /* number of offset/length entries in selection */ - size_t i; - hg_bulk_segment_t *bulk_segments = NULL; - uint8_t *start_offset = (uint8_t *) buf; - - /* generate the offsets/lengths pair arrays from the memory dataspace selection */ - if(H5S_get_offsets(space, type_size, nelmts, &off, &len, &count) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); - - /* Register memory with segmented HG handle */ - bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); - for (i = 0; i < count ; i++) { - bulk_segments[i].address = (void *)(start_offset + off[i]); - bulk_segments[i].size = len[i]; - } - - /* create Bulk handle */ - if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, - HG_BULK_READWRITE, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); - - /* cleanup */ - if(count) { - free(bulk_segments); - bulk_segments = NULL; - free(len); - len = NULL; - free(off); - off = NULL; - } - } - break; - } - /* If this is a variable length datatype, serialize it - through a Mercury Segmented handle */ - case H5T_VLEN: - { - char bogus; /* bogus value to pass to H5Diterate() */ - H5VL_iod_pre_write_t udata; - hg_bulk_segment_t *bulk_segments = NULL; - int u; - - udata.buf_size = 0; - udata.buf_ptr = (uint8_t *)buf; - udata.off = (void **)malloc(nelmts * 2 * sizeof(void *)); - udata.len = (size_t *)malloc(nelmts * 2 * sizeof(size_t)); - udata.curr_seq = 0; - - /* iterate over every element and compute it's size adding it to - the udata buf_size */ - if(H5D__iterate(&bogus, type_id, space, H5VL__iod_pre_write_cb, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to compute buffer size"); - - buf_size = udata.buf_size; - - /* Register memory with segmented HG handle */ - bulk_segments = (hg_bulk_segment_t *)malloc((size_t)udata.curr_seq * - sizeof(hg_bulk_segment_t)); - for (u = 0; u < udata.curr_seq ; u++) { - bulk_segments[u].address = udata.off[u]; - bulk_segments[u].size = udata.len[u]; - } + if(_checksum) { + checksum = H5S_checksum(buf, type_size, nelmts, space); + } - /* create Bulk handle */ - if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, - (size_t)udata.curr_seq, - HG_BULK_READWRITE, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + /* If the memory selection is contiguous, create simple HG Bulk Handle */ + if(H5S_select_is_contiguous(space)) { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, (size_t)buf_size, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + } + /* if the memory selection is non-contiguous, create a segmented selection */ + else { + hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ + size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ + size_t count = 0; /* number of offset/length entries in selection */ + size_t i; + hg_bulk_segment_t *bulk_segments = NULL; + uint8_t *start_offset = (uint8_t *) buf; + + /* generate the offsets/lengths pair arrays from the memory dataspace selection */ + if(H5S_get_offsets(space, type_size, nelmts, &off, &len, &count) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); + + /* Register memory with segmented HG handle */ + bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); + for (i = 0; i < count ; i++) { + bulk_segments[i].address = (void *)(start_offset + off[i]); + bulk_segments[i].size = len[i]; + } + + /* create Bulk handle */ + if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + + /* cleanup */ + if(count) { free(bulk_segments); bulk_segments = NULL; - - if(_checksum) { - checksum = H5_checksum_crc64_fragments(udata.off, udata.len, - (size_t)udata.curr_seq); - } - - /* cleanup */ - if(udata.curr_seq) { - free(udata.len); - udata.len = NULL; - free(udata.off); - udata.off = NULL; - } - - break; + free(len); + len = NULL; + free(off); + off = NULL; } - default: - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); + } } if(_checksum) { *_checksum = checksum; } + + H5VL_iod_type_info_reset(&type_info); + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_iod_pre_write */ @@ -2480,9 +2378,7 @@ done: * * Depending on the type, this routine generates all the necessary * parameters for forwarding a write call to IOD. It sets up the - * Mercury Bulk handle and checksums the data. If the type is of - * variable length, then just return that it is, because special - * processing is required. + * Mercury Bulk handle and checksums the data. * * Return: Success: SUCCEED * Failure: Negative @@ -2493,186 +2389,55 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_iod_pre_read(hid_t type_id, H5S_t *space, const void *buf, - /*out*/hg_bulk_t *bulk_handle, hbool_t *is_vl_data) +H5VL_iod_pre_read(hid_t type_id, H5S_t *space, const void *buf, hssize_t nelmts, + /*out*/hg_bulk_t *bulk_handle) { size_t buf_size = 0; H5T_t *dt = NULL; - size_t nelmts; + size_t type_size; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") - nelmts = (size_t)H5S_GET_SELECT_NPOINTS(space); + type_size = H5T_get_size(dt); + buf_size = type_size * nelmts; - switch(H5T_get_class(dt, FALSE)) { - case H5T_INTEGER: - case H5T_FLOAT: - case H5T_TIME: - case H5T_BITFIELD: - case H5T_OPAQUE: - case H5T_ENUM: - case H5T_ARRAY: - case H5T_NO_CLASS: - case H5T_STRING: - if(H5T_is_variable_str(dt)) { - *is_vl_data = TRUE; - break; - } - case H5T_REFERENCE: - case H5T_NCLASSES: - case H5T_COMPOUND: - { - size_t type_size; - - *is_vl_data = FALSE; - - type_size = H5T_get_size(dt); - buf_size = type_size * nelmts; - - /* If the memory selection is contiguous, create simple HG Bulk Handle */ - if(H5S_select_is_contiguous(space)) { - /* Register memory with bulk_handle */ - if(HG_SUCCESS != HG_Bulk_handle_create(buf, buf_size, - HG_BULK_READWRITE, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); - } - - /* if the memory selection is non-contiguous, create a segmented selection */ - else { - hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ - size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ - size_t count = 0; /* number of offset/length entries in selection */ - size_t i; - hg_bulk_segment_t *bulk_segments = NULL; - uint8_t *start_offset = (uint8_t *) buf; - - /* generate the offsets/lengths pair arrays from the memory dataspace selection */ - if(H5S_get_offsets(space, type_size, nelmts, &off, &len, &count) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); - - /* Register memory with segmented HG handle */ - bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); - for (i = 0; i < count ; i++) { - bulk_segments[i].address = (void *)(start_offset + off[i]); - bulk_segments[i].size = len[i]; - } - - /* create Bulk handle */ - if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, - HG_BULK_READWRITE, bulk_handle)) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); - - /* cleanup */ - if(count) { - free(bulk_segments); - bulk_segments = NULL; - free(len); - len = NULL; - free(off); - off = NULL; - } - } - break; - } - case H5T_VLEN: - *is_vl_data = TRUE; - break; - default: - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); + /* If the memory selection is contiguous, create simple HG Bulk Handle */ + if(H5S_select_is_contiguous(space)) { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, buf_size, + HG_BULK_READWRITE, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); } -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL_iod_pre_read */ - - -/*------------------------------------------------------------------------- - * Function: H5VL__iod_vl_read_finalize - * - * Finalize the data read by deserializing it into the user's buffer. - * - * Return: Success: SUCCEED - * Failure: Negative - * - * Programmer: Mohamad Chaarawi - * August, 2013 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5VL__iod_vl_read_finalize(size_t UNUSED buf_size, void *read_buf, void *user_buf, - H5S_t *mem_space, hid_t mem_type_id, hid_t UNUSED dset_type_id) -{ - H5T_t *mem_dt = NULL; - H5T_t *super = NULL; - size_t super_size; - hsize_t nelmts; - size_t elmt_size = 0; - H5T_class_t dt_class; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT - - if(NULL == (mem_dt = (H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") - if(NULL == (super = H5T_get_super(mem_dt))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); - - super_size = H5T_get_size(super); - nelmts = (hsize_t)H5S_GET_SELECT_NPOINTS(mem_space); - dt_class = H5T_get_class(mem_dt, FALSE); - - /* If the memory selection is contiguous, simply iterate over - every element and store the VL data */ - if(H5S_select_is_contiguous(mem_space)) { - uint8_t *buf_ptr = (uint8_t *)read_buf; - unsigned u; - - if(H5T_VLEN == dt_class) { - size_t seq_len; - hvl_t *vl = (hvl_t *)user_buf; - - for(u=0 ; u<nelmts ; u++) { - seq_len = *((size_t *)buf_ptr); - buf_ptr += sizeof(size_t); - - elmt_size = super_size * seq_len; - - vl[u].len = seq_len; - vl[u].p = malloc(super_size * seq_len); - HDmemcpy(vl[u].p, buf_ptr, elmt_size); - buf_ptr += elmt_size; - } - } - else if(H5T_STRING == dt_class) { - char **buf = (char **)user_buf; - - for(u=0 ; u<nelmts ; u++) { - elmt_size = *((size_t *)buf_ptr); - buf_ptr += sizeof(size_t); - - buf[u] = HDstrdup((char *)buf_ptr); - buf_ptr += elmt_size; - } - } - } -#if 0 + /* if the memory selection is non-contiguous, create a segmented selection */ else { hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ size_t count = 0; /* number of offset/length entries in selection */ size_t i; hg_bulk_segment_t *bulk_segments = NULL; - uint8_t *start_offset = (uint8_t *) read_buf; + uint8_t *start_offset = (uint8_t *) buf; /* generate the offsets/lengths pair arrays from the memory dataspace selection */ if(H5S_get_offsets(space, type_size, nelmts, &off, &len, &count) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); + /* Register memory with segmented HG handle */ + bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); + for (i = 0; i < count ; i++) { + bulk_segments[i].address = (void *)(start_offset + off[i]); + bulk_segments[i].size = len[i]; + } + + /* create Bulk handle */ + if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, + HG_BULK_READWRITE, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + /* cleanup */ if(count) { free(bulk_segments); @@ -2683,13 +2448,10 @@ H5VL__iod_vl_read_finalize(size_t UNUSED buf_size, void *read_buf, void *user_bu off = NULL; } } -#endif done: - if(super && H5T_close(super) < 0) - HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't close super type") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL__iod_vl_read_finalize */ +} /* end H5VL_iod_pre_read */ /*------------------------------------------------------------------------- diff --git a/src/H5VLiod_client.h b/src/H5VLiod_client.h index 556e918..99f74e3 100644 --- a/src/H5VLiod_client.h +++ b/src/H5VLiod_client.h @@ -21,6 +21,7 @@ #include "H5FFprivate.h" /* FastForward wrappers */ #include "H5Mpublic.h" +#include "H5Sprivate.h" #include "H5RCprivate.h" /* Read contexts */ #include "H5TRprivate.h" /* Transactions */ #include "H5VLiod_common.h" @@ -268,17 +269,36 @@ typedef struct H5VL_iod_dtype_t { hid_t tapl_id; } H5VL_iod_dtype_t; -/* information about a dataset read/write request */ -typedef struct H5VL_iod_io_info_t { - /* read & write params */ - void *status; +/* information about an attr IO request */ +typedef struct H5VL_iod_attr_io_info_t { + int *status; hg_bulk_t *bulk_handle; +} H5VL_iod_attr_io_info_t; - /* write params */ - size_t *vl_string_len; - - /* read params */ +/* information about a dataset write request */ +typedef struct H5VL_iod_write_info_t { + void *status; + hg_bulk_t *bulk_handle; + hg_bulk_t *vl_len_bulk_handle; + hg_bulk_segment_t *vl_segments; + char *vl_lengths; +} H5VL_iod_write_info_t; + +/* status of a read operation after it completes */ +typedef struct H5VL_iod_read_status_t { + int ret; + uint64_t cs; + size_t buf_size; +} H5VL_iod_read_status_t; + +/* information about a dataset read request */ +typedef struct H5VL_iod_read_info_t { + void *status; + hg_bulk_t *bulk_handle; void *buf_ptr; + char *vl_lengths; + size_t vl_lengths_size; + H5VL_iod_type_info_t *type_info; hssize_t nelmts; size_t type_size; struct H5S_t *space; @@ -288,10 +308,9 @@ typedef struct H5VL_iod_io_info_t { hid_t mem_type_id; hid_t dxpl_id; uint64_t axe_id; - na_addr_t peer; + na_addr_t ion_target; hg_id_t read_id; - -} H5VL_iod_io_info_t; +} H5VL_iod_read_info_t; typedef struct H5VL_iod_map_set_info_t { void *status; @@ -365,12 +384,15 @@ H5_DLL herr_t H5VL_iod_map_get_size(hid_t type_id, const void *buf, /*out*/size_t *size, /*out*/H5T_class_t *dt_class); H5_DLL herr_t H5VL_iod_gen_obj_id(int myrank, int nranks, uint64_t cur_index, iod_obj_type_t type, uint64_t *id); -H5_DLL herr_t H5VL_iod_pre_write(hid_t type_id, struct H5S_t *space, const void *buf, +H5_DLL herr_t H5VL_iod_pre_write(hid_t type_id, H5S_t *space, const void *buf, /*out*/uint64_t *_checksum, + /*out*/uint64_t *_vlen_checksum, /*out*/hg_bulk_t *bulk_handle, - /*out*/size_t **vl_str_len); + /*out*/hg_bulk_t *vl_len_bulk_handle, + /*out*/hg_bulk_segment_t **_vl_segments, + /*out*/char **_vl_lengths); H5_DLL herr_t H5VL_iod_pre_read(hid_t type_id, struct H5S_t *space, const void *buf, - /*out*/hg_bulk_t *bulk_handle, hbool_t *is_vl_data); + hssize_t nelmts, /*out*/hg_bulk_t *bulk_handle); /* private routines for map objects */ H5_DLL herr_t H5M_init(void); diff --git a/src/H5VLiod_common.c b/src/H5VLiod_common.c new file mode 100644 index 0000000..afb6089 --- /dev/null +++ b/src/H5VLiod_common.c @@ -0,0 +1,1016 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of h5netvol. The full h5netvol copyright notice, * + * including terms governing use, modification, and redistribution, is * + * contained in the file COPYING at the root of the source code distribution * + * tree. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <mchecksum.h> /* Mercury Checksum library */ +#include "H5VLiod_common.h" + +/* + * Local typedefs + */ +/* Structure for a compound member type */ +typedef struct H5VL_iod_cmpd_info_t { + size_t offset; + hid_t type_id; +} H5VL_iod_cmpd_info_t; + +/* Macros for error handling */ +#define SUCCEED 0 +#define FAIL -1 +#define PRINT_ERROR(MSG) \ +do { \ + fprintf(stderr, "ERROR at %s:%d in %s()...\n%s\n", __FILE__, __LINE__, __FUNCTION__,MSG); \ +} while(0) +#define ERROR(MSG) \ +do { \ + PRINT_ERROR(MSG); \ + goto error; \ +} while(0) + +#define TRUE 1 +#define FALSE 0 + +/* Macros to encode and decode a uint64_t */ +# define UINT64ENCODE(p, n) \ + do { \ + uint64_t _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t*)(p); \ +\ + for (_i = 0; _i < sizeof(uint64_t); _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + for (/*void*/; _i < 8; _i++) \ + *_p++ = 0; \ + } while(0) + +# define UINT64DECODE(p, n) \ + do { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + size_t _i; \ + uint8_t *_p = (uint8_t*)(p); \ +\ + n = 0; \ + (_p) += 8; \ + for (_i = 0; _i < sizeof(uint64_t); _i++) \ + n = (n << 8) | *(--_p); \ + } while(0) + +/* + * Local functions + */ +static int H5VL_iod_cmpd_qsort_cb(const void *_memb1, const void *_memb2); +static int H5VL_iod_get_type_info_helper(hid_t type_id, + H5VL_iod_type_info_t *type_info, size_t offset, size_t *vls_nalloc); +static int H5VL_iod_cs_send_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char **vl_lengths, size_t *vl_lengths_nused, + size_t *vl_lengths_nalloc, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc); +static int H5VL_iod_cs_recv_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char *vl_lengths, size_t *vl_lengths_loc, + size_t vl_lengths_nused, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc); + + +/* + * Local macros + */ +#define H5VL_IOD_ARR_ADD(TYPE, ARR, NUSED, NALLOC, DEF_ALLOC) \ + do { \ + size_t _tmp_nalloc; \ + TYPE *_tmp_arr; \ +\ + assert((NALLOC) >= (NUSED)); \ +\ + if((NALLOC) == (NUSED)) { \ + _tmp_nalloc = (NALLOC) ? (NALLOC) * 2 : (DEF_ALLOC); \ +\ + if(NULL == (_tmp_arr = (TYPE *)realloc(ARR, _tmp_nalloc * sizeof(TYPE)))) \ + ERROR("failed to reallocate array"); \ + (ARR) = _tmp_arr; \ + (NALLOC) = _tmp_nalloc; \ + } /* end if */ \ + } while(0) + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cmpd_qsort_cb + * + * Purpose: qsort callback for sorting compound type members by + * offset. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cmpd_qsort_cb(const void *_memb1, const void *_memb2) +{ + const H5VL_iod_cmpd_info_t *memb1 = (const H5VL_iod_cmpd_info_t *)_memb1; + const H5VL_iod_cmpd_info_t *memb2 = (const H5VL_iod_cmpd_info_t *)_memb2; + + if(memb1->offset < memb2->offset) + return -1; + else if(memb1->offset > memb2->offset) + return 1; + else + return 0; +} /* end H5VL_iod_cmpd_qsort_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_type_info_helper + * + * Purpose: Recursively searches for variable-length datatypes in the + * provided type, filling in the fields in type_info. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 18, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_get_type_info_helper(hid_t type_id, H5VL_iod_type_info_t *type_info, + size_t offset, size_t *vls_nalloc) +{ + hid_t super_type = -1; + hsize_t *dims = NULL; + size_t num_cmpd_membs = 0; + H5VL_iod_cmpd_info_t *cmpd_membs = NULL; + H5T_class_t type_class; + int i; + + assert(type_info); + assert(vls_nalloc); + + /* Get type class */ + if(H5T_NO_CLASS == (type_class = H5Tget_class(type_id))) + ERROR("failed to get datatype class"); + + /* Take different actions depending on class */ + switch(type_class) { + case H5T_COMPOUND: + { + int nmemb; + + /* Get number of members */ + if((nmemb = H5Tget_nmembers(type_id)) < 0) + ERROR("failed to get number of compound datatype members"); + + /* Allocate array of members */ + if(NULL == (cmpd_membs = (H5VL_iod_cmpd_info_t *)malloc(nmemb * sizeof(H5VL_iod_cmpd_info_t)))) + ERROR("failed ot allocate array of compound type members"); + + /* Get offset and type for all members */ + for(i = 0; i < nmemb; i++) { + cmpd_membs[i].offset = H5Tget_member_offset(type_id, (unsigned)i); + + if((cmpd_membs[i].type_id = H5Tget_member_type(type_id, (unsigned)i)) < 0) + ERROR("failed to get compound datatype member type"); + num_cmpd_membs++; + } /* end for */ + + /* Sort members by offset */ + qsort(cmpd_membs, num_cmpd_membs, sizeof(cmpd_membs[0]), H5VL_iod_cmpd_qsort_cb); + + /* Get info for all members */ + for(i = 0; i < nmemb; i++) + if(H5VL_iod_get_type_info_helper(cmpd_membs[i].type_id, type_info, offset + cmpd_membs[i].offset, vls_nalloc) < 0) + ERROR("failed to get compound datatype member type info"); + + /* Free cmpd_membs. Run in opposite order so if a failure + * occurs the error code doesn't try to free types twice */ + for(i = nmemb - 1; i >= 0; i--) { + num_cmpd_membs--; + if(H5Tclose(cmpd_membs[i].type_id) < 0) + ERROR("failed to close compound member type"); + } /* end for */ + free(cmpd_membs); + cmpd_membs = NULL; + + break; + } /* end block */ + + case H5T_ARRAY: + { + int ndims; + size_t array_nelem = 1; + size_t orig_num_vls = type_info->num_vls; + size_t elem_num_vls; + size_t super_type_size; + size_t i_size, j_size; + + /* Get array element type */ + if((super_type = H5Tget_super(type_id)) < 0) + ERROR("failed to get array datatype element type"); + + /* Get type info for element type (effectively only for the + * first element) */ + if(H5VL_iod_get_type_info_helper(super_type, type_info, offset, vls_nalloc) < 0) + ERROR("failed to get array datatype element type info"); + + /* If the element type contains any vlens, we must copy the vlen + * info for each element in the array */ + if(type_info->num_vls != orig_num_vls) { + assert(type_info->num_vls > orig_num_vls); + + /* Get number of dimensions in array */ + if((ndims = H5Tget_array_ndims(type_id)) < 0) + ERROR("failed to get array datatype number of dimensions"); + + /* Allocate array of dimensions */ + if(NULL == (dims = (hsize_t *)malloc(ndims * sizeof(hsize_t)))) + ERROR("failed to allocate array of dimensions"); + + /* Get array dimensions */ + if(H5Tget_array_dims2(type_id, dims) < 0) + ERROR("failed to get array datatype dimensions"); + + /* Calculate total number of elements */ + for(i = 0; i < ndims; i++) + array_nelem *= (size_t)dims[i]; + + /* Get size of element type */ + if(0 == (super_type_size = H5Tget_size(super_type))) + ERROR("failed to get array element type size"); + + /* Replicate all vls added during recursion into element + * type for each element in the array. Increment ref count + * on base types instead of copying. */ + elem_num_vls = type_info->num_vls; + for(i_size = 1; i_size < array_nelem; i_size++) + for(j_size = orig_num_vls; j_size < elem_num_vls; + j_size++) { + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + type_info->vls[type_info->num_vls].offset = type_info->vls[j_size].offset + (i_size * super_type_size); + type_info->vls[type_info->num_vls].base_type = type_info->vls[j_size].base_type; + if(type_info->vls[type_info->num_vls].base_type) + type_info->vls[type_info->num_vls].base_type->rc++; + type_info->num_vls++; + } /* end for */ + + free(dims); + dims = NULL; + } /* end if */ + + if(H5Tclose(super_type) < 0) + ERROR("failed to close array datatype element type"); + super_type = -1; + + break; + } /* end block */ + + case H5T_VLEN: + /* Add vlen to vls array */ + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + /* Get vlen base type */ + if((super_type = H5Tget_super(type_id)) < 0) + ERROR("failed to get vlen datatype base type"); + + /* Set vlen offset in type */ + type_info->vls[type_info->num_vls].offset = offset; + + /* Allocate type info for base type */ + if(NULL == (type_info->vls[type_info->num_vls].base_type = (H5VL_iod_type_info_t *)malloc(sizeof(H5VL_iod_type_info_t)))) + ERROR("failed to allocate vlen datatype base type info"); + type_info->num_vls++; + + /* Get type info for base type */ + if(H5VL_iod_get_type_info(super_type, type_info->vls[type_info->num_vls - 1].base_type) < 0) + ERROR("failed to get vlen datatype base type info"); + + if(H5Tclose(super_type) < 0) + ERROR("failed to close vlen datatype base type"); + super_type = -1; + + break; + + case H5T_STRING: + { + htri_t is_variable_str; + + /* Check if this string is variable length */ + if((is_variable_str = H5Tis_variable_str(type_id)) < 0) + ERROR("failed to determine if type is variable string"); + + if(is_variable_str) { + /* Add variable-length string to vls array. Set base_type + * to NULL. */ + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + type_info->vls[type_info->num_vls].offset = offset; + type_info->vls[type_info->num_vls].base_type = NULL; + type_info->num_vls++; + + break; + } /* end if */ + + /* Fall through if not variable string */ + } /* end block */ + + default: + /* Nothing to do currently */ + break; + } /* end switch */ + + return(SUCCEED); + +error: + if(super_type >= 0) + if(H5Tclose(super_type) < 0) + PRINT_ERROR("failed to close super type"); + if(dims) + free(dims); + if(cmpd_membs) { + for(i = 0; i < (int)num_cmpd_membs; i++) + if(H5Tclose(cmpd_membs[i].type_id) < 0) + PRINT_ERROR("failed to close compound member type"); + free(cmpd_membs); + } /* end if */ + + return(FAIL); +} /* end H5VL_iod_get_type_info_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_type_info + * + * Purpose: Builds the type_info struct given type_id. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 18, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_get_type_info(hid_t type_id, H5VL_iod_type_info_t *type_info) +{ + htri_t found_class; + + /* Initialize struct first, so a call to reset() won't cause problems if + * something in this function fails */ + type_info->num_fl_spans = 0; + type_info->fl_spans = NULL; + type_info->num_vls = 0; + type_info->vls = NULL; + type_info->rc = 1; + if(0 == (type_info->size = H5Tget_size(type_id))) + ERROR("H5Tget_size failed"); + + /* Check for a vl or string type */ + if((found_class = H5Tdetect_class(type_id, H5T_VLEN)) < 0) + ERROR("failed to search for vlen type class"); + if(!found_class) + if((found_class = H5Tdetect_class(type_id, H5T_STRING)) < 0) + ERROR("failed to search for string type class"); + + /* Only need to investigate further if the type contains a vlen or string */ + if(found_class) { + size_t vls_nalloc = 0; + + if(H5VL_iod_get_type_info_helper(type_id, type_info, 0, &vls_nalloc) < 0) + ERROR("failed to type info"); + } /* end if */ + + /* If any vlens were found, build fixed-length span info */ + if(type_info->num_vls) { + size_t cur_fl_offset = 0; + size_t fl_spans_nalloc = 0; + size_t i; + + /* Iterate over all vlens */ + for(i = 0; i < type_info->num_vls; i++) { + /* Check if this vlen left a fixed-length gap before it */ + assert(type_info->vls[i].offset >= cur_fl_offset); + if(type_info->vls[i].offset > cur_fl_offset) { + /* Create fixed-length span before vl */ + H5VL_IOD_ARR_ADD(H5VL_iod_fl_span_t, type_info->fl_spans, type_info->num_fl_spans, fl_spans_nalloc, 2); + + type_info->fl_spans[type_info->num_fl_spans].offset = cur_fl_offset; + type_info->fl_spans[type_info->num_fl_spans].size = type_info->vls[i].offset - cur_fl_offset; + type_info->num_fl_spans++; + } /* end if */ + + /* Update cur_fl_offset */ + cur_fl_offset = type_info->vls[i].offset + (type_info->vls[i].base_type ? sizeof(hvl_t) : sizeof(char *)); + } /* end for */ + + /* Add span at end */ + assert(type_info->size >= cur_fl_offset); + if(type_info->size > cur_fl_offset) { + H5VL_IOD_ARR_ADD(H5VL_iod_fl_span_t, type_info->fl_spans, type_info->num_fl_spans, fl_spans_nalloc, 2); + + type_info->fl_spans[type_info->num_fl_spans].offset = cur_fl_offset; + type_info->fl_spans[type_info->num_fl_spans].size = type_info->size - cur_fl_offset; + type_info->num_fl_spans++; + } /* end if */ + } /* end if */ + + return(SUCCEED); + +error: + H5VL_iod_type_info_reset(type_info); + + return(FAIL); +} /* end H5VL_iod_get_type_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_type_info_reset + * + * Purpose: Frees all fields fields in type_info, and anything + * referenced by those fields. Does not free type_info. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_type_info_reset(H5VL_iod_type_info_t *type_info) +{ + size_t i; + + /* Free fl spans */ + if(type_info->fl_spans) { + free(type_info->fl_spans); + type_info->fl_spans = NULL; + } /* end if */ + type_info->num_fl_spans = 0; + + /* Free vls */ + if(type_info->vls) { + /* Recurse into each vl's base type, and free the base type if its rc + * reaches 0 */ + for(i = 0; i < type_info->num_vls; i++) + if(type_info->vls[i].base_type + && (--type_info->vls[i].base_type->rc == 0)) { + H5VL_iod_type_info_reset(type_info->vls[i].base_type); + free(type_info->vls[i].base_type); + } /* end if */ + + free(type_info->vls); + type_info->vls = NULL; + } /* end if */ + type_info->num_vls = 0; + + return; +} /* end H5VL_iod_type_info_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cs_send_helper + * + * Purpose: Recursively builds the segments array and array of + * variable-length data lengths given buf, type_info and + * nelem. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cs_send_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char **vl_lengths, size_t *vl_lengths_nused, + size_t *vl_lengths_nalloc, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc) +{ + _Bool wrapped = FALSE; + _Bool wrappable; + size_t span_size; + size_t i; + size_t j; + + assert(nelem > 0); + + if(type_info->vls) { + /* Add segments for fixed-length spans */ + if(type_info->num_fl_spans > 0) { + assert(type_info->fl_spans); + + /* Check if we can combine the last span in each element with the first + * span in the next */ + wrappable = ((type_info->fl_spans[type_info->num_fl_spans - 1].offset + + type_info->fl_spans[type_info->num_fl_spans - 1].size) + == type_info->size) && (type_info->fl_spans[0].offset == 0); + + assert(!(wrappable && (type_info->num_fl_spans == 1))); + + /* Iterate over spans */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_fl_spans; j++) + if(wrapped) + wrapped = FALSE; + else { + /* Add fixed-length segment to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + /* Check if we can wrap this segment */ + if((j == (type_info->num_fl_spans - 1)) && wrappable + && (i != (nelem - 1))) { + span_size = type_info->fl_spans[0].size + type_info->fl_spans[j].size; + wrapped = TRUE; + } /* end if */ + else + span_size = type_info->fl_spans[j].size; + + /* Add segment */ + (*segments)[*num_segments].address = (hg_ptr_t)(buf + (i * type_info->size) + type_info->fl_spans[j].offset); + (*segments)[*num_segments].size = span_size; + (*num_segments)++; + } /* end else */ + } /* end if */ + + /* Analyze vlens */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_vls; j++) + if(type_info->vls[j].base_type) { + /* Standard vlen */ + hvl_t vl = *(hvl_t *)(buf + (i * type_info->size) + type_info->vls[j].offset); + + /* Add vl segment length to vl_lengths array */ + H5VL_IOD_ARR_ADD(char, *vl_lengths, *vl_lengths_nused, *vl_lengths_nalloc, 256); + assert(*vl_lengths_nused + 8 <= *vl_lengths_nalloc); + + UINT64ENCODE(&(*vl_lengths)[*vl_lengths_nused], (uint64_t)vl.len); + *vl_lengths_nused += 8; + + /* Handle vlen array if present */ + if(vl.len > 0) { + /* Add vlen buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl.p; + (*free_list_len)++; + } /* end if */ + + /* Recurse into vlen data */ + if(H5VL_iod_cs_send_helper(vl.p, type_info->vls[j].base_type, vl.len, segments, num_segments, segments_nalloc, vl_lengths, vl_lengths_nused, vl_lengths_nalloc, free_list, free_list_len, free_list_nalloc) < 0) + ERROR("failed to build segments"); + } /* end if */ + } /* end if */ + else { + /* Vlen string */ + char *vl_s = *(char **)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_s_len; + + /* Get size */ + if(vl_s) + vl_s_len = (uint64_t)strlen(vl_s) + 1; + else + vl_s_len = 0; + + /* Add vl string length to vl_lengths array. Include null + * terminator in length to distinguish between NULL pointer + * (len = 0) and null string (len = 1) */ + H5VL_IOD_ARR_ADD(char, *vl_lengths, *vl_lengths_nused, *vl_lengths_nalloc, 256); + assert(*vl_lengths_nused + 8 <= *vl_lengths_nalloc); + + UINT64ENCODE(&(*vl_lengths)[*vl_lengths_nused], vl_s_len); + *vl_lengths_nused += 8; + + /* Handle the vl string buffer if present */ + if(vl_s_len > 0) { + /* Add vl string buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl_s; + (*free_list_len)++; + } /* end if */ + + /* Add vl string length to segments array, if length is + * greater than 1 (including null terminator). Do not + * include null terminator in segment length so it is not + * transmitted. */ + if(vl_s_len > 1) { + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)vl_s; + (*segments)[*num_segments].size = vl_s_len - 1; + (*num_segments)++; + } /* end if */ + } /* end if */ + } /* end else */ + } /* end if */ + else { + /* No vlens, just add entire buffer to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)buf; + (*segments)[*num_segments].size = nelem * type_info->size; + (*num_segments)++; + } /* end else */ + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_cs_send_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_create_segments_send + * + * Purpose: Builds the segments array and array of variable-length + * data lengths given buf, type_info and nelem. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_create_segments_send(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char **vl_lengths, size_t *vl_lengths_size, void ***free_list, + size_t *free_list_len) +{ + size_t segments_nalloc = 0; + size_t vl_lengths_nalloc = 0; + size_t free_list_nalloc = 0; + + assert(buf); + assert(type_info); + assert(type_info->vls); + assert(nelem > 0); + assert(segments); + assert(!*segments); + assert(num_segments); + assert(*num_segments == 0); + assert(vl_lengths); + assert(!*vl_lengths); + assert(vl_lengths_size); + assert(*vl_lengths_size == 0); + assert(!free_list == !free_list_len); + assert(!free_list || !*free_list); + assert(!free_list_len || (*free_list_len == 0)); + + /* Call the real (recursive) function */ + if(H5VL_iod_cs_send_helper(buf, type_info, nelem, segments, num_segments, &segments_nalloc, vl_lengths, vl_lengths_size, &vl_lengths_nalloc, free_list, free_list_len, &free_list_nalloc) < 0) + ERROR("failed to build segments"); + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_create_segments_send() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cs_recv_helper + * + * Purpose: Recursively builds the segments array, allocates buffers + * for variable-length data, and writes vlen pointers given + * (empty) buf, type_info, nelem, and the vl_lengths array. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cs_recv_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char *vl_lengths, size_t *vl_lengths_loc, + size_t vl_lengths_size, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc) +{ + _Bool wrapped = FALSE; + _Bool wrappable; + size_t span_size; + size_t i; + size_t j; + + assert(nelem > 0); + + if(type_info->vls) { + /* Add segments for fixed-length spans */ + if(type_info->num_fl_spans > 0) { + assert(type_info->fl_spans); + + /* Check if we can combine the last span in each element with the first + * span in the next */ + wrappable = ((type_info->fl_spans[type_info->num_fl_spans - 1].offset + + type_info->fl_spans[type_info->num_fl_spans - 1].size) + == type_info->size) && (type_info->fl_spans[0].offset == 0); + + assert(!(wrappable && (type_info->num_fl_spans == 1))); + + /* Iterate over spans */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_fl_spans; j++) + if(wrapped) + wrapped = FALSE; + else { + /* Add fixed-length segment to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + /* Check if we can wrap this segment */ + if((j == (type_info->num_fl_spans - 1)) && wrappable + && (i != (nelem - 1))) { + span_size = type_info->fl_spans[0].size + type_info->fl_spans[j].size; + wrapped = TRUE; + } /* end if */ + else + span_size = type_info->fl_spans[j].size; + + /* Add segment */ + (*segments)[*num_segments].address = (hg_ptr_t)(buf + (i * type_info->size) + type_info->fl_spans[j].offset); + (*segments)[*num_segments].size = span_size; + (*num_segments)++; + } /* end else */ + } /* end if */ + + /* Analyze vlens */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_vls; j++) + if(type_info->vls[j].base_type) { + /* Standard vlen */ + hvl_t *vl = (hvl_t *)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_length; + + /* Retrieve vl segment length from vl_lengths array */ + if(*vl_lengths_loc + 8 > vl_lengths_size) + ERROR("vl_lengths array is too short"); + UINT64DECODE(&vl_lengths[*vl_lengths_loc], vl_length); + *vl_lengths_loc += 8; + vl->len = (size_t)vl_length; + + if(vl_length == 0) + vl->p = NULL; + else { + /* Allocate buffer for vlen data */ + if(NULL == (vl->p = malloc(vl_length * type_info->vls[j].base_type->size))) + ERROR("failed to allocate vlen buffer"); + + /* Add malloc'ed buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl->p; + (*free_list_len)++; + } /* end if */ + + /* Recurse into vlen data */ + if(H5VL_iod_cs_recv_helper(vl->p, type_info->vls[j].base_type, (size_t)vl_length, segments, num_segments, segments_nalloc, vl_lengths, vl_lengths_loc, vl_lengths_size, free_list, free_list_len, free_list_nalloc) < 0) + ERROR("failed to build segments"); + } /* end if */ + } /* end if */ + else { + /* Vlen string */ + char **vl_s = (char **)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_s_len; + + /* Retrieve vl string length from vl_lengths array */ + if(*vl_lengths_loc + 8 > vl_lengths_size) + ERROR("vl_lengths array is too short"); + UINT64DECODE(&vl_lengths[*vl_lengths_loc], vl_s_len); + *vl_lengths_loc += 8; + + if(vl_s_len == 0) + *vl_s = NULL; + else { + /* Allocate buffer for vlen string data */ + if(NULL == (*vl_s = malloc((size_t)vl_s_len))) + ERROR("failed to allocate vlen string buffer"); + + /* Add malloc'ed buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = *vl_s; + (*free_list_len)++; + } /* end if */ + + /* Add vl string to segments array, if length is greater + * than 1 (including null terminator) */ + if(vl_s_len > 1) { + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)*vl_s; + (*segments)[*num_segments].size = (size_t)vl_s_len - 1; + (*num_segments)++; + } /* end if */ + + /* Add null terminator */ + (*vl_s)[vl_s_len - 1] = '\0'; + } /* end if */ + } /* end else */ + } /* end if */ + else { + /* No vlens, just add entire buffer to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)buf; + (*segments)[*num_segments].size = nelem * type_info->size; + (*num_segments)++; + } /* end else */ + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_cs_recv_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_create_segments_recv + * + * Purpose: Builds the segments array, allocates buffers for + * variable-length data, and writes vlen pointers given + * (empty) buf, type_info, nelem, and the vl_lengths array. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_create_segments_recv(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char *vl_lengths, size_t vl_lengths_size, void ***free_list, + size_t *free_list_len) +{ + size_t segments_nalloc = 0; + size_t vl_lengths_loc = 0; + size_t free_list_nalloc = 0; + + assert(buf); + assert(type_info); + assert(type_info->vls); + assert(nelem > 0); + assert(segments); + assert(!*segments); + assert(num_segments); + assert(*num_segments == 0); + assert(vl_lengths); + assert(vl_lengths_size > 0); + assert(!free_list == !free_list_len); + assert(!free_list || !*free_list); + assert(!free_list_len || (*free_list_len == 0)); + + /* Call the real (recursive) function */ + if(H5VL_iod_cs_recv_helper(buf, type_info, nelem, segments, num_segments, &segments_nalloc, vl_lengths, &vl_lengths_loc, vl_lengths_size, free_list, free_list_len, &free_list_nalloc) < 0) + ERROR("failed to build segments"); + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_create_segments_recv() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_free_list_free + * + * Purpose: Frees all pointers on the provided free list and then + * frees the free list itself + * + * Return: void + * + * Programmer: Neil Fortner + * Dec 5, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_free_list_free(void **free_list, size_t free_list_len) +{ + size_t i; + + for(i = 0; i < free_list_len; i++) + free(free_list[i]); + free(free_list); +} /* end H5VL_iod_free_list_free() */ + +uint64_t +H5_checksum_crc64(const void *buf, size_t buf_size) +{ + const char *hash_method = "crc64"; + size_t hash_size; + uint64_t hash; + mchecksum_object_t checksum; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + mchecksum_update(checksum, buf, buf_size); + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &hash, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return hash; +} + +uint64_t +H5_checksum_crc64_segments(hg_bulk_segment_t *segments, size_t count) +{ + const char *hash_method = "crc64"; + size_t hash_size; + uint64_t hash; + size_t i; + mchecksum_object_t checksum; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + for (i = 0; i < count; i++) { + mchecksum_update(checksum, segments[i].address, segments[i].size); + } + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &hash, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return hash; +} + +uint64_t +H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count) +{ + const char *hash_method = "crc64"; + size_t hash_size; + uint64_t hash; + size_t i; + mchecksum_object_t checksum; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + for (i = 0; i < count; i++) { + mchecksum_update(checksum, buf[i], buf_size[i]); + } + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &hash, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return hash; +} diff --git a/src/H5VLiod_common.h b/src/H5VLiod_common.h index dcb01a4..0b959ec 100644 --- a/src/H5VLiod_common.h +++ b/src/H5VLiod_common.h @@ -32,18 +32,34 @@ #define IOD_COUNT_UNDEFINED ((uint64_t)(-1))//(pow(2.0,64.0) - 1) #define H5VL_IOD_DEBUG 1 +/* Structure for a span of fixed-length data in a type */ + typedef struct H5VL_iod_fl_span_t { + size_t offset; /* Offset of start of span in type */ + size_t size; /* Size of span */ +} H5VL_iod_fl_span_t; + +/* Structure for a variable-length type in a type */ +typedef struct H5VL_iod_vl_info_t { + size_t offset; /* Offset of vlen in type */ + struct H5VL_iod_type_info_t *base_type; /* Type info for vlen base type. Set to NULL if this vlen is a vl string. */ +} H5VL_iod_vl_info_t; + +/* Structure containing information about a type to use during I/O */ +typedef struct H5VL_iod_type_info_t { + size_t size; /* Size of one element of this type */ + size_t num_fl_spans; /* Size of fl_spans array */ + H5VL_iod_fl_span_t *fl_spans; /* Array of spans of fixed-length data in type */ + size_t num_vls; /* Size of vls array */ + H5VL_iod_vl_info_t *vls; /* Array of variable-length types in type */ + size_t rc; /* Number of references to this struct */ +} H5VL_iod_type_info_t; + typedef enum H5VL_iod_state_t { H5VL_IOD_PENDING, H5VL_IOD_COMPLETED, H5VL_IOD_CANCELLED } H5VL_iod_state_t; -typedef struct H5VL_iod_read_status_t { - int ret; - uint64_t cs; - size_t buf_size; -} H5VL_iod_read_status_t; - typedef struct dims_t { int rank; hsize_t *size; @@ -84,6 +100,22 @@ typedef struct iod_handles_t { iod_handle_t wr_oh; } iod_handles_t; +H5_DLL int H5VL_iod_get_type_info(hid_t type_id, H5VL_iod_type_info_t *type_info); +H5_DLL void H5VL_iod_type_info_reset(H5VL_iod_type_info_t *type_info); +H5_DLL int H5VL_iod_create_segments_send(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char **vl_lengths, size_t *vl_lengths_nused, void ***free_list, + size_t *free_list_len); +H5_DLL int H5VL_iod_create_segments_recv(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char *vl_lengths, size_t vl_lengths_nused, void ***free_list, + size_t *free_list_len); +H5_DLL void H5VL_iod_free_list_free(void **free_list, size_t free_list_len); + +H5_DLL uint64_t H5_checksum_crc64(const void *buf, size_t buf_size); +H5_DLL uint64_t H5_checksum_crc64_segments(hg_bulk_segment_t *segments, size_t count); +H5_DLL uint64_t H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count); + H5_DLL int hg_proc_ret_t(hg_proc_t proc, void *data); H5_DLL int hg_proc_axe_t(hg_proc_t proc, void *data); H5_DLL int hg_proc_size_t(hg_proc_t proc, void *data); @@ -447,18 +479,9 @@ MERCURY_GEN_PROC(dset_io_in_t, ((hid_t)(space_id)) ((hid_t)(dxpl_id)) ((uint64_t)(checksum)) - ((hg_bulk_t)(bulk_handle))) -MERCURY_GEN_PROC(dset_get_vl_size_in_t, - ((axe_t)(axe_info)) - ((uint32_t)(cs_scope)) - ((uint64_t)(rcxt_num)) - ((iod_handle_t)(coh)) - ((iod_handles_t)(iod_oh)) - ((iod_obj_id_t)(iod_id)) - ((iod_obj_id_t)(mdkv_id)) - ((hid_t)(mem_type_id)) - ((hid_t)(space_id)) - ((hid_t)(dxpl_id))) + ((hg_bulk_t)(bulk_handle)) + ((hg_bulk_t)(vl_len_bulk_handle)) + ((uint64_t)(axe_id))) MERCURY_GEN_PROC(dset_read_out_t, ((int32_t)(ret)) ((uint64_t)(cs)) diff --git a/src/H5VLiod_dset.c b/src/H5VLiod_dset.c index 0973ed6..735eed5 100644 --- a/src/H5VLiod_dset.c +++ b/src/H5VLiod_dset.c @@ -32,26 +32,68 @@ /* User data for VL traverssal */ typedef struct { iod_handle_t coh; - iod_handle_t iod_oh; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + hid_t space_id; uint8_t *buf_ptr; - hbool_t write_op; size_t buf_size; - hid_t mem_super_type; - hid_t dset_super_type; - size_t mem_type_size; - size_t dset_type_size; - hsize_t nelmts; - iod_trans_id_t tid; -} H5VL_iod_server_vl_io_t; + size_t nelmts; + size_t cur_seg; + hg_bulk_segment_t *segments; + iod_trans_id_t wtid; + iod_trans_id_t rtid; +} H5VL_iod_server_vl_write_t; static herr_t -H5VL__iod_server_vl_data_io(iod_handle_t coh, iod_handle_t iod_oh, hid_t space_id, - hid_t mem_type_id, hid_t dset_type_id, hbool_t write_op, - void *buf, size_t buf_size, hid_t dxpl_id, iod_trans_id_t tid); +H5VL__iod_server_vl_data_write(iod_handle_t coh, iod_obj_id_t iod_id, iod_handles_t iod_oh, + hid_t space_id, hid_t mem_type_id, hid_t dset_type_id, + H5VL_iod_type_info_t type_info, size_t nelmts, + size_t num_segments, hg_bulk_segment_t *segments, + hid_t dxpl_id, iod_trans_id_t wtid, iod_trans_id_t rtid, + na_addr_t source, hg_bulk_t bulk_handle, uint32_t cs_scope); static herr_t -H5VL__iod_server_vl_data_io_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, - const hsize_t *point, void *_udata); +H5VL__iod_server_vl_data_read(iod_handle_t coh, AXE_engine_t axe_engine, AXE_task_t axe_id, + size_t nelmts, void *buf, + hid_t dxpl_id, iod_trans_id_t rtid); + +static herr_t +H5VL__iod_server_vl_data_write_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, + const hsize_t *point, void *_udata); + +static iod_obj_id_t +H5VL__iod_get_vl_blob_oid(iod_obj_id_t dset_id, hid_t space_id, const hsize_t *point) +{ + hsize_t dims[H5S_MAX_RANK]; + uint64_t cur; + int ndims, i; + iod_obj_id_t blob_id = 0; + + ndims = H5Sget_simple_extent_dims(space_id, dims, NULL); + + /* set the BLOB ID algorithmically from the coordinate */ + cur = 1; + for(i=0 ; i<ndims ; i++) { + blob_id += cur*point[i]; + cur *= dims[i]; + } + + /* copy the last 20 bits of the dataset ID into bits 58->38 of the BLOB ID */ + for(i=0 ; i<20 ; i++) { + (dset_id & (((uint64_t)0x1) << i)) ? + (blob_id |= (((uint64_t)0x1) << (38+i+1))) : + (blob_id &= ~(((uint64_t)0x1) << (38+i+1))); + } + + /* set the BLOB for dset elements ID */ + blob_id |= (((uint64_t)0x1) << 59); + + /* Set IOD bit parameters for the BLOB ID */ + IOD_OBJID_SETTYPE(blob_id, IOD_OBJ_BLOB); + IOD_OBJID_SETOWNER_APP(blob_id); + + return blob_id; +} /*------------------------------------------------------------------------- @@ -425,7 +467,7 @@ done: *------------------------------------------------------------------------- */ void -H5VL_iod_server_dset_read_cb(AXE_engine_t UNUSED axe_engine, +H5VL_iod_server_dset_read_cb(AXE_engine_t axe_engine, size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], void *_op_data) @@ -445,7 +487,7 @@ H5VL_iod_server_dset_read_cb(AXE_engine_t UNUSED axe_engine, uint32_t cs_scope = input->cs_scope; hg_bulk_block_t bulk_block_handle; /* HG block handle */ hg_bulk_request_t bulk_request; /* HG request */ - size_t size, buf_size; + size_t size, buf_size = 0; void *buf = NULL; /* buffer to hold outgoing data */ iod_checksum_t cs = 0; /* checksum value */ uint32_t raw_cs_scope; @@ -485,7 +527,6 @@ H5VL_iod_server_dset_read_cb(AXE_engine_t UNUSED axe_engine, /* get the number of points selected */ nelmts = (size_t)H5Sget_select_npoints(space_id); - buf_size = 0; /* Adjust buffer is type conversion is needed. If the data elements are of variable length, just return that they are in @@ -533,14 +574,9 @@ H5VL_iod_server_dset_read_cb(AXE_engine_t UNUSED axe_engine, } else { /* If the data is of variable length, special access is required */ - if(H5VL__iod_server_vl_data_io(coh, iod_oh.rd_oh, space_id, dst_id, src_id, - FALSE, buf, buf_size, dxpl_id, rtid) < 0) + if(H5VL__iod_server_vl_data_read(coh, axe_engine, input->axe_id, nelmts, + buf, dxpl_id, rtid) < 0) HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); - - if(!(raw_cs_scope & H5_CHECKSUM_NONE)) { - /* calculate a checksum for the data to be sent */ - cs = H5_checksum_crc64(buf, buf_size); - } } /* Create a new block handle to write the data */ @@ -606,17 +642,22 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, void *_op_data) { op_data_t *op_data = (op_data_t *)_op_data; - dset_get_vl_size_in_t *input = (dset_get_vl_size_in_t *)op_data->input; + //dset_get_vl_size_in_t *input = (dset_get_vl_size_in_t *)op_data->input; + dset_io_in_t *input = (dset_io_in_t *)op_data->input; dset_read_out_t output; iod_handle_t coh = input->coh; /* container handle */ iod_handles_t iod_oh = input->iod_oh; /* dset object handle */ iod_obj_id_t iod_id = input->iod_id; /* dset ID */ + hid_t type_id = input->mem_type_id; /* the datatype of the dataset's element */ hid_t space_id = input->space_id; /* file space selection */ hid_t dxpl_id = input->dxpl_id; /* transfer property list */ iod_trans_id_t rtid = input->rcxt_num; uint32_t cs_scope = input->cs_scope; - size_t buf_size; - void *buf = NULL; /* buffer to hold blob IDs */ + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hg_bulk_block_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + size_t buf_size, elmt_size; + void *buf = NULL; /* buffer to hold blob IDs and sizes */ size_t nelmts; /* number of elements selected to read */ hssize_t num_descriptors = 0, n; /* number of IOD file descriptors needed to describe filespace selection */ iod_mem_desc_t *mem_desc; /* memory descriptor used for reading array */ @@ -627,6 +668,7 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, iod_array_io_t *io_array = NULL; /* arary for list I/O */ uint8_t *buf_ptr = NULL; int ndims, i; /* dataset's rank/number of dimensions */ + na_addr_t dest = HG_Handler_get_addr(op_data->hg_handle); /* destination address to push data to */ hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the dset here or if it was already open */ herr_t ret_value = SUCCEED; @@ -641,37 +683,62 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, /* get the number of points selected */ nelmts = (size_t)H5Sget_select_npoints(space_id); - ndims = H5Sget_simple_extent_ndims(space_id); + + /* get the rank of the dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + elmt_size = sizeof(iod_obj_id_t) + sizeof(iod_size_t); /* allocate buffer to hold blob IDs */ - if(NULL == (buf = malloc(nelmts * sizeof(iod_obj_id_t) + sizeof(iod_size_t)))) + if(NULL == (buf = malloc(nelmts * elmt_size))) HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); /* buffer always contains the length of each sequence, so initialize it to the size required to store those lengths */ - buf_size = nelmts * sizeof(size_t); + buf_size = nelmts * 8;//sizeof(size_t); - /* get the number of decriptors required, i.e. the numbers of iod - I/O operations needed */ - if(H5VL_iod_get_file_desc(space_id, &num_descriptors, NULL) < 0) - HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + /* handle scalar dataspace */ + if(0 == ndims) { + ndims = 1; + /* allocate the IOD hyperslab descriptors needed */ + if(NULL == (hslabs = (iod_hyperslab_t *)malloc(sizeof(iod_hyperslab_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate iod array descriptors"); - /* allocate the IOD hyperslab descriptors needed */ - if(NULL == (hslabs = (iod_hyperslab_t *)malloc - (sizeof(iod_hyperslab_t) * (size_t)num_descriptors))) - HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate iod array descriptors"); + hslabs[0].start = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].stride = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].block = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].count = (iod_size_t *)malloc(sizeof(iod_size_t)); - for(n=0 ; n<num_descriptors ; n++) { - hslabs[n].start = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); - hslabs[n].stride = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); - hslabs[n].block = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); - hslabs[n].count = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + num_descriptors = 1; + hslabs[0].start[0] = 0; + hslabs[0].count[0] = 1; + hslabs[0].block[0] = 1; + hslabs[0].stride[0] = 1; } - - /* generate the descriptors after allocating the array */ - if(H5VL_iod_get_file_desc(space_id, &num_descriptors, hslabs) < 0) + else { + /* get the number of decriptors required, i.e. the numbers of iod + I/O operations needed */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, NULL) < 0) HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + /* allocate the IOD hyperslab descriptors needed */ + if(NULL == (hslabs = (iod_hyperslab_t *)malloc + (sizeof(iod_hyperslab_t) * (size_t)num_descriptors))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate iod array descriptors"); + + for(n=0 ; n<num_descriptors ; n++) { + hslabs[n].start = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslabs[n].stride = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslabs[n].block = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslabs[n].count = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + } + + /* generate the descriptors after allocating the array */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, hslabs) < 0) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + } + buf_ptr = (uint8_t *)buf; /* allocate the IOD array parameters for reading */ @@ -697,7 +764,7 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, /* determine how many bytes the current descriptor holds */ for(i=0 ; i<ndims ; i++) num_elems *= (hslabs[n].count[i] * hslabs[n].block[i]); - num_bytes = num_elems * sizeof(iod_obj_id_t) + sizeof(iod_size_t); + num_bytes = num_elems * elmt_size; /* set the memory descriptor */ mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); @@ -715,13 +782,12 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, io_array[n].hints = NULL; io_array[n].mem_desc = mem_desc; io_array[n].io_desc = &file_desc; - io_array[n].cs = &cs_list[n]; + io_array[n].cs = NULL; //MSC - need IOD - &cs_list[n]; io_array[n].ret = &ret_list[n]; } /* Read list IO */ - if(iod_array_read_list(coh, rtid, (int)num_descriptors, - io_array, NULL) < 0) + if(iod_array_read_list(coh, rtid, (int)num_descriptors, io_array, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); /* verify return values */ @@ -730,29 +796,87 @@ H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, if(ret_list[n] < 0) HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); - +#if 0 /* Verify checksum for that entry */ buf_ptr = (uint8_t *)buf; entry_cs = H5_checksum_crc64(buf_ptr, sizeof(iod_size_t) + sizeof(iod_obj_id_t)); /* MSC - no CS from IOD */ //if(entry_cs != *(io_array[n].cs)) //HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data Corruption detected when reading"); - buf_ptr += sizeof(iod_size_t) + sizeof(iod_obj_id_t); + buf_ptr += elmt_size; +#endif free(io_array[n].mem_desc); } - /* compute the buf size */ - buf_ptr = (uint8_t *)buf; - buf_ptr += sizeof(iod_obj_id_t); - for(n=0 ; n<num_descriptors ; n++) { - size_t seq_len; + /* MSC - create a bulk block handle. Mercury does not support + segmented handles yet, so we need a temporrary buffer. */ + { + size_t *temp_buf = NULL; + uint8_t *temp_ptr; + size_t temp_size; + unsigned u; + H5VL_iod_type_info_t type_info; + + if(NULL == (temp_buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate size buffer"); + + buf_ptr = (uint8_t *)buf; + temp_ptr = (uint8_t *)temp_buf; + + /* Get type info */ + if(H5VL_iod_get_type_info(type_id, &type_info) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + assert(1 == type_info.num_vls); + + /* copy just the size of each VL element into the temp buffer */ + for(u=0 ; u<nelmts ; u++) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %u with BLOB ID %"PRIx64" size %zu\n", + u, *((iod_obj_id_t *)buf_ptr),*((size_t *)(buf_ptr+sizeof(iod_obj_id_t)))); +#endif + + temp_size = *((size_t *)(buf_ptr+sizeof(iod_obj_id_t))); + + if(type_info.vls[0].base_type) { + /* Standard vlen */ + temp_size = temp_size / type_info.vls[0].base_type->size; + } + else { + /* VL string; add space for NULL termination */ + temp_size ++; + } + + UINT64ENCODE(temp_ptr, (uint64_t)temp_size); + buf_ptr += elmt_size; + } + + H5VL_iod_type_info_reset(&type_info); + + /* Create a new block handle to write the data */ + HG_Bulk_block_handle_create(temp_buf, buf_size, HG_BULK_READ_ONLY, &bulk_block_handle); - seq_len = *((size_t *)buf_ptr); - buf_ptr += sizeof(iod_size_t) + sizeof(iod_obj_id_t); - buf_size += seq_len; + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_block_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); + + if(temp_buf) { + free(temp_buf); + temp_buf = NULL; + } } + op_data->output = buf; + done: output.ret = ret_value; @@ -766,8 +890,8 @@ done: fprintf(stderr, "Done with dset get vl size (%zu), sending response to client\n", buf_size); #endif - input = (dset_get_vl_size_in_t *)H5MM_xfree(input); - op_data = (op_data_t *)H5MM_xfree(op_data); + input = (dset_io_in_t *)H5MM_xfree(input); + //op_data = (op_data_t *)H5MM_xfree(op_data); /* free allocated descriptors */ for(n=0 ; n<num_descriptors ; n++) { @@ -785,9 +909,6 @@ done: if(ret_list) free(ret_list); - if(buf) - free(buf); - /* close the dataset if we opened it in this routine */ if(TRUE == opened_locally) { if(iod_obj_close(iod_oh.rd_oh, NULL, NULL) < 0) @@ -822,6 +943,7 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine, iod_handles_t iod_oh = input->iod_oh; /* dset object handle */ iod_obj_id_t iod_id = input->iod_id; /* dset ID */ hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hg_bulk_t vl_len_bulk_handle = input->vl_len_bulk_handle; /* bulk handle for vlen length */ hid_t space_id = input->space_id; /* file space selection */ uint64_t cs = input->checksum; /* checksum recieved for data */ hid_t src_id = input->mem_type_id; /* the memory type of the elements */ @@ -837,6 +959,7 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine, iod_checksum_t data_cs = 0; uint32_t raw_cs_scope; unsigned u; + H5VL_iod_type_info_t type_info; void *buf = NULL; size_t nelmts; /* number of elements selected to read */ hbool_t flag = FALSE; /* temp flag to indicate whether corruption will be inserted */ @@ -849,7 +972,7 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine, /* open the dataset if we don't have the handle yet */ if(iod_oh.wr_oh.cookie == IOD_OH_UNDEFINED) { if (iod_obj_open_write(coh, iod_id, wtid, NULL /*hints*/, &iod_oh.wr_oh, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open dataset for write"); opened_locally = TRUE; } @@ -861,94 +984,208 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine, input->dxpl_id = H5Pcopy(H5P_DATASET_XFER_DEFAULT); dxpl_id = input->dxpl_id; - /* retrieve size of incoming bulk data */ - size = HG_Bulk_handle_get_size(bulk_handle); + nelmts = (size_t)H5Sget_select_npoints(space_id); - /* allocate buffer to hold data */ - if(NULL == (buf = malloc(size))) - HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + /* Get type info */ + if(H5VL_iod_get_type_info(src_id, &type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + if(type_info.vls) { + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; + void **free_list = NULL; + size_t free_list_len = 0; + hg_bulk_block_t vl_len_handle; + + /* Get size of vl_lengths array and allocate local buffer */ + vl_lengths_size = HG_Bulk_handle_get_size(vl_len_bulk_handle); + if(vl_lengths_size == 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "no vlen lengths sent"); + if(NULL == (vl_lengths = (char *)malloc(vl_lengths_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate vlen lengths buffer"); + + /* Register local memory buffer */ + if(HG_SUCCESS != HG_Bulk_block_handle_create(vl_lengths, vl_lengths_size, + HG_BULK_READWRITE, &vl_len_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "create vlen bulk handle"); + + /* Receive vl length data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, vl_len_bulk_handle, + vl_len_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read vlen lengths bulk data"); + + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for vlen lengths bulk data operation"); + + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_block_handle_free(vl_len_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free vlen bulk handle"); + + if(NULL == (buf = malloc(nelmts * type_info.size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate data buffer"); + + /* Create segments from vl lengths */ + if(H5VL_iod_create_segments_recv((char *)buf, &type_info, nelmts, &segments, &num_segments, + vl_lengths, vl_lengths_size, &free_list, &free_list_len) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create segments for bulk data transfer"); + assert(segments); + +#if 1 + if(H5VL__iod_server_vl_data_write(coh, iod_id, iod_oh, space_id, src_id, dst_id, type_info, + nelmts, num_segments, segments, dxpl_id, wtid, rtid, + source, bulk_handle, raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write VL data to array object"); + +#else + { + int i; + size_t j = 0; + uint64_t *buf_ptr = (uint64_t *)vl_lengths; + + fprintf(stderr, "Buffer size: %zu\n", nelmts * type_info.size); + /* Print VL length DATA */ + for(i = 0; i < vl_lengths_size/sizeof(size_t); i++) { + fprintf(stderr, "Element %d size %lu segment %lu, size %zu\n", i, vl_lengths[j], + segments[i].address, segments[i].size); + j+=8; + } /* end for */ + } - /* create a Mercury block handle for transfer */ - HG_Bulk_block_handle_create(buf, size, HG_BULK_READWRITE, &bulk_block_handle); + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READWRITE, &vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data Handle"); - /* Write bulk data here and wait for the data to be there */ - if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, bulk_block_handle, &bulk_request)) - HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); - /* wait for it to complete */ - if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) - HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + /* Receive bulk data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, vl_data_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read bulk data"); - /* free the bds block handle */ - if(HG_SUCCESS != HG_Bulk_block_handle_free(bulk_block_handle)) - HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for bulk data operation"); - /* MSC - check if client requested to corrupt data */ - if(H5Pget_dxpl_inject_corruption(dxpl_id, &flag) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read property list"); - if(flag) { - ((int *)buf)[0] = 10; - } + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free bulk handle"); - /* get the scope for data integrity checks for raw data */ - if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) - HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + { + hvl_t *buf_ptr = (hvl_t *)buf; + int i, j; - /* verify data if transfer flag is set */ - if(raw_cs_scope & H5_CHECKSUM_TRANSFER) { - data_cs = H5_checksum_crc64(buf, size); - if(cs != data_cs) { - fprintf(stderr, - "Errrr.. Network transfer Data corruption. expecting %"PRIu64", got %"PRIu64"\n", - cs, data_cs); - ret_value = FAIL; - goto done; + /* Print VL DATA */ + for(i = 0; i < 5; i++) { + int temp = (int)buf_ptr[i].len; + + fprintf(stderr, "Element %d size %zu: ", i, temp); + for(j = 0; j < temp; j++) + fprintf(stderr, "%d ",((unsigned int *)buf_ptr[i].p)[j]); + fprintf(stderr, "\n"); + } /* end for */ + } +#endif + + /* Free segments */ + if(segments) { + free(segments); + segments = NULL; + num_segments = 0; + } /* end if */ + + if(free_list) { + H5VL_iod_free_list_free(free_list, free_list_len); + free_list = NULL; + free_list_len = 0; + } /* end if */ + + /* Free vl_lengths */ + if(vl_lengths) { + free(vl_lengths); + vl_lengths = NULL; + vl_lengths_size = 0; } } -#if H5VL_IOD_DEBUG else { - fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); - } + /* retrieve size of incoming bulk data */ + size = HG_Bulk_handle_get_size(bulk_handle); + + /* allocate buffer to hold data */ + if(NULL == (buf = malloc(size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* create a Mercury block handle for transfer */ + HG_Bulk_block_handle_create(buf, size, HG_BULK_READWRITE, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* free the bds block handle */ + if(HG_SUCCESS != HG_Bulk_block_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + + /* MSC - check if client requested to corrupt data */ + if(H5Pget_dxpl_inject_corruption(dxpl_id, &flag) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read property list"); + if(flag) { + ((int *)buf)[0] = 10; + } + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* verify data if transfer flag is set */ + if(raw_cs_scope & H5_CHECKSUM_TRANSFER) { + data_cs = H5_checksum_crc64(buf, size); + if(cs != data_cs) { + fprintf(stderr, + "Errrr.. Network transfer Data corruption. expecting %"PRIu64", got %"PRIu64"\n", + cs, data_cs); + ret_value = FAIL; + goto done; + } + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } #endif - nelmts = (size_t)H5Sget_select_npoints(space_id); - buf_size = 0; + buf_size = 0; - /* Adjust buffer is type conversion is needed. If the data - elements are of variable length, just return that they are in - is_vl_data for special processing */ - if(H5VL__iod_server_adjust_buffer(src_id, dst_id, nelmts, dxpl_id, - size, &buf, &is_vl_data, &buf_size) < 0) { - fprintf(stderr, "failed to setup write operation"); - ret_value = FAIL; - goto done; - } + /* Adjust buffer is type conversion is needed. If the data + elements are of variable length, just return that they are in + is_vl_data for special processing */ + if(H5VL__iod_server_adjust_buffer(src_id, dst_id, nelmts, dxpl_id, + size, &buf, &is_vl_data, &buf_size) < 0) { + fprintf(stderr, "failed to setup write operation"); + ret_value = FAIL; + goto done; + } - /* If the data is not VL, we can write the data to the array the normal way */ - if(!is_vl_data) { /* convert data if needed */ if(H5Tconvert(src_id, dst_id, nelmts, buf, NULL, dxpl_id) < 0) HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed") - if(H5VL__iod_server_final_io(coh, iod_oh.wr_oh, space_id, dst_id, - TRUE, buf, buf_size, cs, raw_cs_scope, wtid) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write to array object"); - #if 0 { int *ptr = (int *)buf; - - fprintf(stderr, "DWRITE Received a buffer of size %zu with values: ", size); + + fprintf(stderr, "DWRITE Received a buffer of size %zu with values: ", size); for(u=0 ; u<size/sizeof(int) ; ++u) fprintf(stderr, "%d ", ptr[u]); fprintf(stderr, "\n"); } #endif - } - else { - /* If the data is of variable length, special access is required */ - if(H5VL__iod_server_vl_data_io(coh, iod_oh.wr_oh, space_id, src_id, dst_id, - TRUE, buf, buf_size, dxpl_id, wtid) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + if(H5VL__iod_server_final_io(coh, iod_oh.wr_oh, space_id, dst_id, + TRUE, buf, buf_size, cs, raw_cs_scope, wtid) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write to array object"); } done: @@ -961,6 +1198,7 @@ done: input = (dset_io_in_t *)H5MM_xfree(input); op_data = (op_data_t *)H5MM_xfree(op_data); + H5VL_iod_type_info_reset(&type_info); if(buf) free(buf); @@ -1275,7 +1513,7 @@ H5VL__iod_server_final_io(iod_handle_t coh, iod_handle_t iod_oh, hid_t space_id, io_array[n].mem_desc = mem_desc; io_array[n].io_desc = &file_desc; if(cs_scope & H5_CHECKSUM_IOD) - io_array[n].cs = &cs_list[n]; + io_array[n].cs = NULL;// MSC - need IOD - &cs_list[n]; else io_array[n].cs = NULL; io_array[n].ret = &ret_list[n]; @@ -1357,7 +1595,144 @@ done: /*------------------------------------------------------------------------- - * Function: H5VL__iod_server_vl_data_io + * Function: H5VL__iod_server_vl_data_read + * + * Iterates over every (variable sized) element in the dataspace + * selection and reads it from IOD. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_server_vl_data_read(iod_handle_t coh, AXE_engine_t axe_engine, AXE_task_t axe_id, + size_t nelmts, void *buf, + hid_t UNUSED dxpl_id, iod_trans_id_t rtid) +{ + void *vlen_buf = NULL; + uint8_t *vlen_buf_ptr; + uint8_t *buf_ptr = (uint8_t *)buf; + void *get_size_op_data; + op_data_t *op_data = NULL; + iod_blob_io_t *io_blob = NULL; /* arary for list I/O */ + iod_checksum_t *cs_list = NULL; + iod_ret_t *ret_list = NULL; + iod_handle_t *blob_oh; + size_t u, elmt_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* retrieve the buffer that contains the blob IDs and their sizes + that was created in the get_size operation */ + if(AXE_SUCCEED != AXEget_op_data(axe_engine, axe_id, &get_size_op_data)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to get farm op_data"); + op_data = (op_data_t *)get_size_op_data; + + vlen_buf = op_data->output; + vlen_buf_ptr = (uint8_t *)vlen_buf; + + /* allocate a blob list to read the data */ + if(NULL == (io_blob = (iod_blob_io_t *)malloc(sizeof(iod_blob_io_t) * nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate blob io array"); + + /* allocate an array for the blob OHs */ + if(NULL == (blob_oh = (iod_handle_t *)malloc(sizeof(iod_handle_t) * nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate blob io array"); + + /* allocate cs array */ + if(NULL == (cs_list = (iod_checksum_t *)calloc(sizeof(iod_checksum_t), nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate checksum array"); + + /* allocate return array */ + if(NULL == (ret_list = (iod_ret_t *)calloc(sizeof(iod_ret_t), nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate return array"); + + elmt_size = sizeof(iod_obj_id_t) + sizeof(iod_size_t); + + for(u=0 ; u<nelmts; u++) { + size_t blob_size; + iod_obj_id_t blob_id; + iod_mem_desc_t *mem_desc; + iod_blob_iodesc_t *blob_desc; + + blob_id = *((iod_obj_id_t *)vlen_buf_ptr); + blob_size = *((size_t *)(vlen_buf_ptr+sizeof(iod_obj_id_t))); + vlen_buf_ptr += elmt_size; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %zu with BLOB ID %"PRIx64" size %zu\n", + u, blob_id, blob_size); +#endif + + if(iod_obj_open_read(coh, blob_id, rtid, NULL, &blob_oh[u], NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open BLOB for Read"); + + /* create memory descriptor for reading */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = (void *)buf_ptr; + mem_desc->frag[0].len = blob_size; + + /* create file descriptor for writing */ + blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + blob_desc->nfrag = 1; + blob_desc->frag[0].offset = 0; + blob_desc->frag[0].len = blob_size; + + /* setup list I/O parameters */ + io_blob[u].oh = blob_oh[u]; + io_blob[u].hints = NULL; + io_blob[u].mem_desc = mem_desc; + io_blob[u].io_desc = blob_desc; + io_blob[u].cs = NULL; //MSC - need IOD - &cs_list[u]; + io_blob[u].ret = &ret_list[u]; + + buf_ptr += blob_size; + } + + /* Read list IO */ + if(iod_blob_read_list(coh, rtid, (int)nelmts, io_blob, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from blob objects"); + + for(u=0 ; u<nelmts; u++) { + if(ret_list[u] < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + free(io_blob[u].mem_desc); + free(io_blob[u].io_desc); + + if(iod_obj_close(blob_oh[u], NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + +done: + + if(io_blob) + free(io_blob); + if(blob_oh) + free(blob_oh); + if(cs_list) + free(cs_list); + if(ret_list) + free(ret_list); + + vlen_buf = NULL; + free(op_data->output); + op_data->output = NULL; + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5VL__iod_server_vl_data_read */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_vl_data_write * * Iterates over every (variable sized) element in the dataspace * selection and read/write it from IOD. @@ -1371,68 +1746,81 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5VL__iod_server_vl_data_io(iod_handle_t coh, iod_handle_t iod_oh, hid_t space_id, - hid_t mem_type_id, hid_t dset_type_id, hbool_t write_op, - void *buf, size_t buf_size, hid_t UNUSED dxpl_id, - iod_trans_id_t tid) +H5VL__iod_server_vl_data_write(iod_handle_t coh, iod_obj_id_t iod_id, iod_handles_t iod_oh, + hid_t space_id, hid_t mem_type_id, hid_t UNUSED dset_type_id, + H5VL_iod_type_info_t type_info, size_t nelmts, + size_t num_segments, hg_bulk_segment_t *segments, + hid_t UNUSED dxpl_id, iod_trans_id_t wtid, iod_trans_id_t rtid, + na_addr_t source, hg_bulk_t bulk_handle, uint32_t cs_scope) { char bogus; /* bogus value to pass to H5Diterate() */ - H5VL_iod_server_vl_io_t udata; - H5T_class_t dt_class; + H5VL_iod_server_vl_write_t udata; + hg_bulk_block_t vl_data_handle; + hg_bulk_request_t bulk_request; + size_t buf_size = 0, u; + void *buf = NULL; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT - /* get number of elements selected in dataspace */ - udata.nelmts = (size_t)H5Sget_select_npoints(space_id); + /* Print VL length DATA */ + for(u = 0; u < num_segments; u++) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %zu size %zu \n", u, segments[u].size); +#endif + buf_size += segments[u].size; + } /* end for */ + + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate data buffer"); + + /* Register local memory buffer */ + if(HG_SUCCESS != HG_Bulk_block_handle_create(buf, buf_size, HG_BULK_READWRITE, &vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "create vlen bulk handle"); + + /* Receive vl length data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, vl_data_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read vlen lengths bulk data"); + + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for vlen lengths bulk data operation"); + + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_block_handle_free(vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free vlen bulk handle"); /* set other parameters needed to do IO */ udata.coh = coh; udata.iod_oh = iod_oh; + udata.nelmts = nelmts; udata.buf_ptr = (uint8_t *)buf; - udata.write_op = write_op; udata.buf_size = buf_size; - udata.tid = tid; - - dt_class = H5Tget_class(mem_type_id); - - if(H5T_VLEN == dt_class) { - if((udata.mem_super_type = H5Tget_super(mem_type_id)) < 0) - HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); - if((udata.dset_super_type = H5Tget_super(dset_type_id)) < 0) - HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); - - udata.mem_type_size = H5Tget_size(udata.mem_super_type); - udata.dset_type_size = H5Tget_size(udata.dset_super_type); - } - else if(H5T_STRING == dt_class) { - assert(H5Tis_variable_str(mem_type_id)); - - udata.mem_type_size = 1; - udata.dset_type_size = 1; - } + udata.wtid = wtid; + udata.rtid = rtid; + udata.segments = segments; + udata.cur_seg = 0; + udata.space_id = space_id; + udata.iod_id = iod_id; /* iterate over every element and read/write it as a BLOB object */ - if(H5Diterate(&bogus, mem_type_id, space_id, H5VL__iod_server_vl_data_io_cb, &udata) < 0) + if(H5Diterate(&bogus, mem_type_id, space_id, H5VL__iod_server_vl_data_write_cb, &udata) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to compute buffer size"); - if(H5T_VLEN == dt_class) { - if(H5Tclose(udata.mem_super_type) < 0) - HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "Can't close mem super type"); - if(H5Tclose(udata.dset_super_type) < 0) - HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "Can't close dset super type"); - } - done: + if(buf) { + free(buf); + buf = NULL; + } FUNC_LEAVE_NOAPI(ret_value) -}/* end H5VL__iod_server_vl_data_io */ +}/* end H5VL__iod_server_vl_data_write */ /*------------------------------------------------------------------------- - * Function: H5VL__iod_server_vl_data_io_cb + * Function: H5VL__iod_server_vl_data_write_cb * * The callback to the H5Diterate routine called in - * H5VL__iod_server_vl_data_io. This will access every element in the + * H5VL__iod_server_vl_data_write. This will access every element in the * array object and resolves it to a BLOB object. Then the actual data * is read/written from/to the BLOB object. * @@ -1445,22 +1833,29 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5VL__iod_server_vl_data_io_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, - const hsize_t *point, void *_udata) +H5VL__iod_server_vl_data_write_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, + const hsize_t *point, void *_udata) { - H5VL_iod_server_vl_io_t *udata = (H5VL_iod_server_vl_io_t *)_udata; + H5VL_iod_server_vl_write_t *udata = (H5VL_iod_server_vl_write_t *)_udata; iod_handle_t coh = udata->coh; /* container handle */ size_t nelmts = udata->nelmts; - iod_trans_id_t tid = udata->tid; + iod_trans_id_t wtid = udata->wtid; + iod_trans_id_t rtid = udata->rtid; + iod_handles_t iod_oh = udata->iod_oh; + iod_obj_id_t iod_id = udata->iod_id; iod_obj_id_t blob_id = 0; iod_handle_t blob_oh; iod_hyperslab_t hslab; iod_mem_desc_t *mem_desc; /* memory descriptor used for reading array */ iod_array_iodesc_t file_desc; /* file descriptor used to read array */ iod_blob_iodesc_t *blob_desc; /* blob descriptor */ + size_t buf_size; size_t old_seq_len = 0; unsigned u; + int i; iod_checksum_t entry_cs = 0, read_cs = 0; + hbool_t created = FALSE; + iod_ret_t ret; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT @@ -1471,117 +1866,83 @@ H5VL__iod_server_vl_data_io_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, hslab.block = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); hslab.count = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); +#if H5VL_IOD_DEBUG + fprintf(stderr, "Writing VL element # %zu\n", udata->cur_seg); +#endif + memcpy(hslab.start, point, sizeof(size_t) * ndims); for(u=0 ; u<ndims ; u++) { hslab.stride[u] = 1; hslab.block[u] = 1; hslab.count[u] = 1; } - - /* set the memory descriptor */ - mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t) * 2); - mem_desc->nfrag = 2; - mem_desc->frag[0].addr = &blob_id; - mem_desc->frag[0].len = sizeof(iod_obj_id_t); - mem_desc->frag[1].addr = &old_seq_len; - mem_desc->frag[1].len = sizeof(iod_size_t); - file_desc = hslab; - if(iod_array_read(udata->iod_oh, tid, NULL, - mem_desc, &file_desc, &read_cs, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); - - { - void *buffers[2]; - size_t buf_sizes[2]; - - buffers[0] = &blob_id; - buf_sizes[0] = sizeof(iod_obj_id_t); - buffers[1] = &old_seq_len; - buf_sizes[1] = sizeof(iod_size_t); - - entry_cs = H5_checksum_crc64_fragments(buffers, buf_sizes, 2); - } - - /* MSC - no CS from IOD */ - //if(entry_cs != read_cs) - //HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data Corruption detected when reading"); - - free(mem_desc); - - /* write operation */ - if(udata->write_op) { - size_t seq_len, buf_size; - - /* create a blob object if one has not been created yet */ - if(0 == blob_id) { - if(iod_obj_create(coh, tid, NULL/*hints*/, IOD_OBJ_BLOB, NULL, NULL, - &blob_id, NULL /*event*/) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to create BLOB object"); - } - /* Open blob object */ - if (iod_obj_open_write(coh, blob_id, tid, NULL, &blob_oh, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Datatype"); - - seq_len = *((size_t *)(udata->buf_ptr)); - udata->buf_ptr += sizeof(iod_size_t); - - buf_size = seq_len * udata->mem_type_size; - -#if H5VL_IOD_DEBUG - { - H5T_class_t dt_class; - - dt_class = H5Tget_class(type_id); - - if(H5T_STRING == dt_class) - fprintf(stderr, "String Length %zu: %s\n", seq_len, (char *)udata->buf_ptr); - else if(H5T_VLEN == dt_class) { - int *ptr = (int *)udata->buf_ptr; + /* calculate the BLOB oid for the current coordinate */ + blob_id = H5VL__iod_get_vl_blob_oid(iod_id, udata->space_id, point); - fprintf(stderr, "Sequence Count %zu: ", seq_len); - for(u=0 ; u<seq_len ; ++u) - fprintf(stderr, "%d ", ptr[u]); - fprintf(stderr, "\n"); + /* Attempt to Open the BLOB for write */ + ret = iod_obj_open_write(coh, blob_id, wtid, NULL, &blob_oh, NULL); + /* if the open fails, try and create the BLOB */ + if(ret != 0) { + ret = iod_obj_create(coh, wtid, NULL, IOD_OBJ_BLOB, NULL, NULL, &blob_id, NULL); + /* if the BLOB exists now, try to open it again */ + if(0 == ret || -EEXIST == ret) { + if(0 == ret) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "created BLOB with ID %"PRIx64"\n", blob_id); +#endif + created = TRUE; + } + ret = iod_obj_open_write(coh, blob_id, wtid, NULL, &blob_oh, NULL); + if(ret != 0) { + fprintf(stderr, "ret: %d error: %s %"PRIx64"\n", ret, strerror(-ret), blob_id); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to open BLOB object"); } } -#endif + else + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to create BLOB object"); + } - /* MSC - type conversion ?? */ + buf_size = udata->segments[udata->cur_seg].size; - /* create memory descriptor for writing */ - mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); - mem_desc->nfrag = 1; - mem_desc->frag[0].addr = (void *)udata->buf_ptr; - mem_desc->frag[0].len = (iod_size_t)buf_size; + /* MSC - type conversion ?? */ - /* create file descriptor for writing */ - blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + /* create memory descriptor for writing */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = (void *)udata->buf_ptr; + mem_desc->frag[0].len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + sizeof(iod_blob_iofrag_t)); - blob_desc->nfrag = 1; - blob_desc->frag[0].offset = 0; - blob_desc->frag[0].len = (iod_size_t)buf_size; + blob_desc->nfrag = 1; + blob_desc->frag[0].offset = 0; + blob_desc->frag[0].len = (iod_size_t)buf_size; - /* write the VL data to the blob */ - if(iod_blob_write(blob_oh, tid, NULL, mem_desc, blob_desc, NULL, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); + /* write the VL data to the blob */ + if(iod_blob_write(blob_oh, wtid, NULL, mem_desc, blob_desc, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); - free(mem_desc); - free(blob_desc); + free(mem_desc); + free(blob_desc); - /* close BLOB */ - if(iod_obj_close(blob_oh, NULL, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + /* close BLOB */ + if(iod_obj_close(blob_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if(created) { /* update the array element with the blob_id and sequence length */ mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t) * 2); mem_desc->nfrag = 2; mem_desc->frag[0].addr = &blob_id; mem_desc->frag[0].len = sizeof(iod_obj_id_t); - mem_desc->frag[1].addr = &seq_len; + mem_desc->frag[1].addr = &buf_size; mem_desc->frag[1].len = sizeof(iod_size_t); + /* MSC - no CS from IOD yet */ +#if 0 /* compute checksum of blob ID and sequence length */ { void *buffers[2]; @@ -1594,60 +1955,28 @@ H5VL__iod_server_vl_data_io_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, entry_cs = H5_checksum_crc64_fragments(buffers, buf_sizes, 2); } +#endif /* write the blob ID & size to the array element */ - if(iod_array_write(udata->iod_oh, tid, NULL, - mem_desc, &file_desc, &entry_cs, NULL) < 0) + if(iod_array_write(iod_oh.wr_oh, wtid, NULL, + mem_desc, &file_desc, NULL, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); free(mem_desc); - - /* advance buffer pointer */ - udata->buf_ptr += buf_size; } - /* read operation */ - else { - /* copy the sequence length as the first element in the buffer */ - memcpy(udata->buf_ptr, &old_seq_len, sizeof(size_t)); - udata->buf_ptr += sizeof(size_t); - /* Open blob object */ - if (iod_obj_open_write(coh, blob_id, tid, NULL, &blob_oh, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Datatype"); + /* advance buffer pointer */ + udata->buf_ptr += buf_size; + udata->cur_seg ++; - /* create memory descriptor for reading */ - mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); - mem_desc->nfrag = 1; - mem_desc->frag[0].addr = (void *)udata->buf_ptr; - mem_desc->frag[0].len = old_seq_len * udata->mem_type_size; - - /* create file descriptor for writing */ - blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + - sizeof(iod_blob_iofrag_t)); - blob_desc->nfrag = 1; - blob_desc->frag[0].offset = 0; - blob_desc->frag[0].len = old_seq_len * udata->mem_type_size; - - /* read the VL data from the blob */ - if(iod_blob_read(blob_oh, tid, NULL, mem_desc, blob_desc, NULL, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); - - udata->buf_ptr += old_seq_len * udata->mem_type_size; - - /* close BLOB */ - if(iod_obj_close(blob_oh, NULL, NULL) < 0) - HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); - - free(mem_desc); - free(blob_desc); - } +done: free(hslab.start); free(hslab.stride); free(hslab.block); free(hslab.count); -done: + FUNC_LEAVE_NOAPI(ret_value) -}/* end H5VL__iod_server_vl_data_io_cb */ +}/* end H5VL__iod_server_vl_data_write_cb */ #endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_dtype.c b/src/H5VLiod_dtype.c index 6b6448d..4b2a9dc 100644 --- a/src/H5VLiod_dtype.c +++ b/src/H5VLiod_dtype.c @@ -162,7 +162,8 @@ H5VL_iod_server_dtype_commit_cb(AXE_engine_t UNUSED axe_engine, dt_cs = H5_checksum_crc64(buf, buf_size); /* write the serialized type value to the BLOB object */ - if(iod_blob_write(dtype_oh.wr_oh, wtid, NULL, mem_desc, file_desc, &dt_cs, NULL) < 0) + if(iod_blob_write(dtype_oh.wr_oh, wtid, NULL, mem_desc, file_desc, NULL + /*MSC - IOD fix - &dt_cs*/, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); } else { @@ -366,7 +367,8 @@ H5VL_iod_server_dtype_open_cb(AXE_engine_t UNUSED axe_engine, file_desc->frag[0].len = (iod_size_t)buf_size; /* read the serialized type value from the BLOB object */ - if(iod_blob_read(dtype_oh.rd_oh, rtid, NULL, mem_desc, file_desc, &iod_cs, NULL) < 0) + if(iod_blob_read(dtype_oh.rd_oh, rtid, NULL, mem_desc, file_desc, NULL + /*MSC - IOD fix - &iod_cs*/, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read from BLOB object"); if(iod_cs && (cs_scope & H5_CHECKSUM_IOD)) { diff --git a/src/H5VLiod_obj.c b/src/H5VLiod_obj.c index 8920eb5..f543097 100644 --- a/src/H5VLiod_obj.c +++ b/src/H5VLiod_obj.c @@ -228,7 +228,7 @@ H5VL_iod_server_object_open_cb(AXE_engine_t UNUSED axe_engine, /* read the serialized type value from the BLOB object */ if(iod_blob_read(obj_oh.rd_oh, rtid, NULL, mem_desc, file_desc, - &iod_cs, NULL) < 0) + NULL /* MSC - IOD fix - &iod_cs*/, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); /* calculate a checksum for the datatype */ @@ -412,7 +412,7 @@ H5VL_iod_server_object_copy_cb(AXE_engine_t UNUSED axe_engine, file_desc.frag->len = (iod_size_t)buf_size; /* read the serialized type value from the BLOB object */ - if(iod_blob_read(obj_oh, rtid, NULL, &mem_desc, &file_desc, &iod_cs, NULL) < 0) + if(iod_blob_read(obj_oh, rtid, NULL, &mem_desc, &file_desc, NULL /* MSC - IOD fix - &iod_cs*/, NULL) < 0) HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); /* MSC - NEED IOD */ diff --git a/src/H5VLiod_server.c b/src/H5VLiod_server.c index 015c091..9bdc256 100644 --- a/src/H5VLiod_server.c +++ b/src/H5VLiod_server.c @@ -133,7 +133,7 @@ EFF__mercury_register_callbacks(void) MERCURY_HANDLER_REGISTER("dset_read", H5VL_iod_server_dset_read, dset_io_in_t, dset_read_out_t); MERCURY_HANDLER_REGISTER("dset_get_vl_size", H5VL_iod_server_dset_get_vl_size, - dset_get_vl_size_in_t, dset_read_out_t); + dset_io_in_t, dset_read_out_t); MERCURY_HANDLER_REGISTER("dset_write", H5VL_iod_server_dset_write, dset_io_in_t, ret_t); MERCURY_HANDLER_REGISTER("dset_set_extent", H5VL_iod_server_dset_set_extent, @@ -1646,7 +1646,7 @@ int H5VL_iod_server_dset_get_vl_size(hg_handle_t handle) { op_data_t *op_data = NULL; - dset_get_vl_size_in_t *input = NULL; + dset_io_in_t *input = NULL; int ret_value = HG_SUCCESS; FUNC_ENTER_NOAPI_NOINIT @@ -1654,8 +1654,8 @@ H5VL_iod_server_dset_get_vl_size(hg_handle_t handle) if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); - if(NULL == (input = (dset_get_vl_size_in_t *) - H5MM_malloc(sizeof(dset_get_vl_size_in_t)))) + if(NULL == (input = (dset_io_in_t *) + H5MM_malloc(sizeof(dset_io_in_t)))) HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); if(HG_FAIL == HG_Handler_get_input(handle, input)) diff --git a/src/H5checksum.c b/src/H5checksum.c index 153ce4d..727bdf7 100644 --- a/src/H5checksum.c +++ b/src/H5checksum.c @@ -33,9 +33,6 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ -#ifdef H5_HAVE_EFF -#include "mchecksum.h" /* Mercury Checksum library */ -#endif /* H5_HAVE_EFF */ /****************/ /* Local Macros */ @@ -665,64 +662,3 @@ H5_hash_string(const char *str) FUNC_LEAVE_NOAPI(hash) } /* end H5_hash_string() */ - -#ifdef H5_HAVE_EFF -uint64_t -H5_checksum_crc64(const void *buf, size_t buf_size) -{ - const char *hash_method = "crc64"; - size_t hash_size; - uint64_t hash; - mchecksum_object_t checksum; - - /* Initialize checksum */ - mchecksum_init(hash_method, &checksum); - - /* Update checksum */ - mchecksum_update(checksum, buf, buf_size); - - /* Get size of checksum */ - hash_size = mchecksum_get_size(checksum); - - assert(hash_size == sizeof(uint64_t)); - - /* get checksum value */ - mchecksum_get(checksum, &hash, hash_size, 1); - - /* Destroy checksum */ - mchecksum_destroy(checksum); - - return hash; -} - -uint64_t -H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count) -{ - const char *hash_method = "crc64"; - size_t hash_size; - uint64_t hash; - size_t i; - mchecksum_object_t checksum; - - /* Initialize checksum */ - mchecksum_init(hash_method, &checksum); - - /* Update checksum */ - for (i = 0; i < count; i++) { - mchecksum_update(checksum, buf[i], buf_size[i]); - } - - /* Get size of checksum */ - hash_size = mchecksum_get_size(checksum); - - assert(hash_size == sizeof(uint64_t)); - - /* get checksum value */ - mchecksum_get(checksum, &hash, hash_size, 1); - - /* Destroy checksum */ - mchecksum_destroy(checksum); - - return hash; -} -#endif /* H5_HAVE_EFF */ diff --git a/src/H5public.h b/src/H5public.h index f06d425..c4721a3 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -323,9 +323,6 @@ H5_DLL herr_t H5check_version(unsigned majnum, unsigned minnum, unsigned relnum); H5_DLL uint32_t H5checksum(const void *key, size_t length, H5_checksum_seed_t *cs); -H5_DLL uint64_t H5_checksum_crc64(const void *buf, size_t buf_size); -H5_DLL uint64_t H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count); - #ifdef __cplusplus } #endif diff --git a/src/Makefile.am b/src/Makefile.am index 3e44560..f07a7bf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,7 +59,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \ H5FAstat.c H5FAtest.c \ H5VL.c H5VLint.c H5VLnative.c \ - H5VLiod.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ + H5VLiod.c H5VLiod_common.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ H5VLiod_file.c H5VLiod_group.c H5VLiod_map.c H5VLiod_dset.c H5VLiod_dtype.c \ H5VLiod_attr.c H5VLiod_link.c H5VLiod_obj.c H5VLiod_trans.c H5VLiod_analysis.c \ H5FD.c H5FDcore.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 1b7b36d..d207a32 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -137,21 +137,21 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Fquery.lo H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo \ H5Ftest.lo H5FA.lo H5FAcache.lo H5FAdbg.lo H5FAdblock.lo \ H5FAdblkpage.lo H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5VL.lo \ - H5VLint.lo H5VLnative.lo H5VLiod.lo H5VLiod_client.lo \ - H5VLiod_server.lo H5VLiod_encdec.lo H5VLiod_util.lo \ - H5VLiod_file.lo H5VLiod_group.lo H5VLiod_map.lo \ - H5VLiod_dset.lo H5VLiod_dtype.lo H5VLiod_attr.lo \ - H5VLiod_link.lo H5VLiod_obj.lo H5VLiod_trans.lo \ - H5VLiod_analysis.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \ - H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ - H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \ - H5FDstdio.lo H5FF.lo H5ES.lo H5RC.lo H5TR.lo H5M.lo H5AS.lo \ - H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \ - H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.lo \ - H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \ - H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \ - H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo \ - H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \ + H5VLint.lo H5VLnative.lo H5VLiod.lo H5VLiod_common.lo \ + H5VLiod_client.lo H5VLiod_server.lo H5VLiod_encdec.lo \ + H5VLiod_util.lo H5VLiod_file.lo H5VLiod_group.lo \ + H5VLiod_map.lo H5VLiod_dset.lo H5VLiod_dtype.lo \ + H5VLiod_attr.lo H5VLiod_link.lo H5VLiod_obj.lo \ + H5VLiod_trans.lo H5VLiod_analysis.lo H5FD.lo H5FDcore.lo \ + H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo \ + H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo \ + H5FDspace.lo H5FDstdio.lo H5FF.lo H5ES.lo H5RC.lo H5TR.lo \ + H5M.lo H5AS.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \ + H5FSsection.lo H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo \ + H5Gcache.lo H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo \ + H5Gint.lo H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo \ + H5Goh.lo H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo \ + H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \ H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \ H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \ H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HGquery.lo \ @@ -583,7 +583,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \ H5FAstat.c H5FAtest.c \ H5VL.c H5VLint.c H5VLnative.c \ - H5VLiod.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ + H5VLiod.c H5VLiod_common.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ H5VLiod_file.c H5VLiod_group.c H5VLiod_map.c H5VLiod_dset.c H5VLiod_dtype.c \ H5VLiod_attr.c H5VLiod_link.c H5VLiod_obj.c H5VLiod_trans.c H5VLiod_analysis.c \ H5FD.c H5FDcore.c \ @@ -1054,6 +1054,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_analysis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_attr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_dset.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_dtype.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_encdec.Plo@am__quote@ |