diff options
Diffstat (limited to 'src')
39 files changed, 2367 insertions, 1030 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9730436..4cf4965 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -640,6 +640,8 @@ set (H5VL_SOURCES ${HDF5_SRC_DIR}/H5VLpassthru.c ) set (H5VL_HDRS + ${HDF5_SRC_DIR}/H5VLconnector.h + ${HDF5_SRC_DIR}/H5VLconnector_passthru.h ${HDF5_SRC_DIR}/H5VLnative.h ${HDF5_SRC_DIR}/H5VLpassthru.h ${HDF5_SRC_DIR}/H5VLpublic.h @@ -967,7 +969,7 @@ endif () if (NOT EXISTS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c) add_executable (H5detect ${HDF5_SRC_DIR}/H5detect.c) - target_include_directories(H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") + target_include_directories (H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") target_compile_definitions(H5detect PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) TARGET_C_PROPERTIES (H5detect STATIC) target_link_libraries (H5detect @@ -1057,7 +1059,7 @@ else () endif () add_executable (H5make_libsettings ${HDF5_SRC_DIR}/H5make_libsettings.c) -target_include_directories(H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") +target_include_directories (H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") target_compile_definitions(H5make_libsettings PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS}) TARGET_C_PROPERTIES (H5make_libsettings STATIC) target_link_libraries (H5make_libsettings @@ -1097,46 +1099,48 @@ option (HDF5_ENABLE_DEBUG_APIS "Turn on extra debug output in all packages" OFF) #----------------------------------------------------------------------------- # Add H5Tinit source to build - generated by H5detect/CMake at configure time #----------------------------------------------------------------------------- -set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c) -add_custom_target (gen_${HDF5_LIB_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2) - -add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) -target_include_directories(${HDF5_LIB_TARGET} - PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" - INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" -) -target_compile_definitions(${HDF5_LIB_TARGET} - PUBLIC - ${HDF_EXTRA_C_FLAGS} - ${HDF_EXTRA_FLAGS} - $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG> - PRIVATE - $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API - $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG> -) -TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC) -target_link_libraries (${HDF5_LIB_TARGET} - PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" - PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> -) -if (NOT WIN32) +if (NOT ONLY_SHARED_LIBS) + set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c) + add_custom_target (gen_${HDF5_LIB_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2) + + add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) + target_include_directories (${HDF5_LIB_TARGET} + PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" + INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" + ) + target_compile_definitions(${HDF5_LIB_TARGET} + PUBLIC + ${HDF_EXTRA_C_FLAGS} + ${HDF_EXTRA_FLAGS} + $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG> + PRIVATE + $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API + $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG> + ) + TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC) target_link_libraries (${HDF5_LIB_TARGET} - PRIVATE $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads> + PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" + PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> ) -endif () -set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET}) -H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0) -set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries) -add_dependencies (${HDF5_LIB_TARGET} gen_${HDF5_LIB_TARGET}) + if (NOT WIN32) + target_link_libraries (${HDF5_LIB_TARGET} + PRIVATE $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads> + ) + endif () + set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET}) + H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0) + set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries) + add_dependencies (${HDF5_LIB_TARGET} gen_${HDF5_LIB_TARGET}) -set (install_targets ${HDF5_LIB_TARGET}) + set (install_targets ${HDF5_LIB_TARGET}) +endif () if (BUILD_SHARED_LIBS) set (shared_gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c ${HDF5_BINARY_DIR}/shared/H5lib_settings.c) add_custom_target (gen_${HDF5_LIBSH_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp2) add_library (${HDF5_LIBSH_TARGET} SHARED ${common_SRCS} ${shared_gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS}) - target_include_directories(${HDF5_LIBSH_TARGET} + target_include_directories (${HDF5_LIBSH_TARGET} PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>" INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>" ) @@ -1187,7 +1191,9 @@ if (HDF5_EXPORTED_TARGETS) if (BUILD_SHARED_LIBS) INSTALL_TARGET_PDB (${HDF5_LIBSH_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries) endif () - INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries) + if (NOT ONLY_SHARED_LIBS) + INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries) + endif () install ( TARGETS @@ -1216,7 +1222,9 @@ foreach (libs ${LINK_LIBS} ${LINK_COMP_LIBS}) set (_PKG_CONFIG_LIBS_PRIVATE "${_PKG_CONFIG_LIBS_PRIVATE} -l${libs}") endforeach () -set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}") +if (NOT ONLY_SHARED_LIBS) + set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}") +endif () if (BUILD_SHARED_LIBS) set (_PKG_CONFIG_SH_LIBS "${_PKG_CONFIG_SH_LIBS} -l${HDF5_LIB_CORENAME}") endif () diff --git a/src/H5Adense.c b/src/H5Adense.c index 81e0dc5..bddfe31 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -325,14 +325,11 @@ H5A__dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr) */ if(*user_attr != NULL) { H5A_t *old_attr = *user_attr; - if(old_attr->shared) { - /* Free any dynamically allocated items */ - if(H5A__free(old_attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") - /* Destroy shared attribute struct */ - old_attr->shared = H5FL_FREE(H5A_shared_t, old_attr->shared); - } /* end if */ + /* Free any dynamically allocated items */ + if(old_attr->shared) + if(H5A__shared_free(old_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") old_attr = H5FL_FREE(H5A_t, old_attr); } /* end if */ diff --git a/src/H5Aint.c b/src/H5Aint.c index d8ba92a..808d9b3 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -771,7 +771,7 @@ H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf) if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Copy the attribute data into the user's buffer */ + /* Copy the attribute data into the attribute data buffer */ H5MM_memcpy(attr->shared->data, buf, (dst_type_size * nelmts)); } /* end else */ @@ -1092,48 +1092,55 @@ done: /*------------------------------------------------------------------------- - * Function: H5A__free + * Function: H5A__shared_free * - * Purpose: Frees all memory associated with an attribute, but does not - * free the H5A_t structure (which should be done in H5T_close). + * Purpose: Cleans up the shared attribute data. This will free + * the attribute's shared structure as well. + * + * attr and attr->shared must not be NULL * * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * Monday, November 15, 2004 + * Programmer: Quincey Koziol + * Monday, November 15, 2004 * *------------------------------------------------------------------------- */ herr_t -H5A__free(H5A_t *attr) +H5A__shared_free(H5A_t *attr) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE HDassert(attr); + HDassert(attr->shared); - /* Free dynamically allocated items */ + /* Free dynamically allocated items. + * When possible, keep trying to shut things down (via HDONE_ERROR). + */ if(attr->shared->name) { H5MM_xfree(attr->shared->name); attr->shared->name = NULL; } if(attr->shared->dt) { if(H5T_close_real(attr->shared->dt) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") attr->shared->dt = NULL; } if(attr->shared->ds) { if(H5S_close(attr->shared->ds) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") + HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") attr->shared->ds = NULL; } if(attr->shared->data) attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); -done: + /* Destroy shared attribute struct */ + attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A__free() */ +} /* end H5A__shared_free() */ /*------------------------------------------------------------------------- @@ -1197,11 +1204,9 @@ H5A__close(H5A_t *attr) /* Reference count can be 0. It only happens when H5A__create fails. */ if(attr->shared->nrefs <= 1) { /* Free dynamically allocated items */ - if(H5A__free(attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") - - /* Destroy shared attribute struct */ - attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); + if(attr->shared) + if(H5A__shared_free(attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") } /* end if */ else { /* There are other references to the shared part of the attribute. @@ -2396,9 +2401,13 @@ H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src, /* Check for expanding references */ if(cpy_info->expand_ref) { size_t ref_count; + size_t dst_dt_size; /* Destination datatype size */ + /* Determine size of the destination datatype */ + if(0 == (dst_dt_size = H5T_get_size(attr_dst->shared->dt))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size") /* Determine # of reference elements to copy */ - ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt); + ref_count = attr_dst->shared->data_size / dst_dt_size; /* Copy objects referenced in source buffer to destination file and set destination elements */ if(H5O_copy_expand_ref(file_src, attr_dst->shared->data, file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_dst->shared->dt), cpy_info) < 0) diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 91061cd..f3870c0 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -196,7 +196,7 @@ H5_DLL H5A_t *H5A__copy(H5A_t *new_attr, const H5A_t *old_attr); H5_DLL hid_t H5A__get_type(H5A_t *attr); H5_DLL herr_t H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo); H5_DLL hid_t H5A__get_create_plist(H5A_t* attr); -H5_DLL herr_t H5A__free(H5A_t *attr); +H5_DLL herr_t H5A__shared_free(H5A_t *attr); H5_DLL herr_t H5A__close(H5A_t *attr); H5_DLL herr_t H5A__close_cb(H5VL_object_t *attr_vol_obj); H5_DLL htri_t H5A__get_ainfo(H5F_t *f, H5O_t *oh, H5O_ainfo_t *ainfo); @@ -982,18 +982,9 @@ H5CX_free_state(H5CX_state_t *api_state) /* Release the VOL connector property, if it was set */ if(api_state->vol_connector_prop.connector_id) { /* Clean up any VOL connector info */ - if(api_state->vol_connector_prop.connector_info) { - H5VL_class_t *connector; /* Pointer to connector */ - - /* Retrieve the connector for the ID */ - if(NULL == (connector = (H5VL_class_t *)H5I_object(api_state->vol_connector_prop.connector_id))) - HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a VOL connector ID") - - /* Free the connector info */ - if(H5VL_free_connector_info(connector, api_state->vol_connector_prop.connector_info) < 0) + if(api_state->vol_connector_prop.connector_info) + if(H5VL_free_connector_info(api_state->vol_connector_prop.connector_id, api_state->vol_connector_prop.connector_info) < 0) HGOTO_ERROR(H5E_CONTEXT, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object") - } /* end if */ - /* Decrement connector ID */ if(H5I_dec_ref(api_state->vol_connector_prop.connector_id) < 0) HDONE_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't close VOL connector ID") diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 60f2d8b..a8dc398 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -707,15 +707,18 @@ H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, /* Compute the # of chunks in dataset dimensions */ for(u = 0, layout->nchunks = 1, layout->max_nchunks = 1; u < ndims; u++) { - /* Sanity check */ - HDassert(layout->dim[u] > 0); - /* Round up to the next integer # of chunks, to accommodate partial chunks */ layout->chunks[u] = ((curr_dims[u] + layout->dim[u]) - 1) / layout->dim[u]; if(H5S_UNLIMITED == max_dims[u]) layout->max_chunks[u] = H5S_UNLIMITED; else + { + /* Sanity check */ + if(layout->dim[u] == 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimension size must be > 0, dim = %u ", u) + layout->max_chunks[u] = ((max_dims[u] + layout->dim[u]) - 1) / layout->dim[u]; + } /* Accumulate the # of chunks */ layout->nchunks *= layout->chunks[u]; diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index df61856..29401f8 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -559,9 +559,14 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds /* Check for expanding references */ if(cpy_info->expand_ref) { size_t ref_count; + size_t src_dt_size; /* Source datatype size */ + + /* Determine largest datatype size */ + if(0 == (src_dt_size = H5T_get_size(dt_src))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size") /* Determine # of reference elements to copy */ - ref_count = storage_src->size / H5T_get_size(dt_src); + ref_count = storage_src->size / src_dt_size; /* Copy objects referenced in source buffer to destination file and set destination elements */ if(H5O_copy_expand_ref(f_src, storage_src->buf, f_dst, diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index e3e0aa5..53640e7 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -35,6 +35,13 @@ * until the virtual dataset is closed. */ +/* + * Note: H5S_select_project_intersection has been updated to no longer require + * that the source and source intersect spaces have the same extent. This file + * should therefore be updated to remove code that ensures this condition, which + * should improve both maintainability and performance. + */ + /****************/ /* Module Setup */ /****************/ @@ -866,7 +866,7 @@ H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg_str, size_t size) H5E_msg_t *msg; /* Pointer to error message */ ssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_API((-1)) + FUNC_ENTER_API_NOCLEAR((-1)) H5TRACE4("Zs", "i*Et*sz", msg_id, type, msg_str, size); /* Get the message object */ diff --git a/src/H5Eint.c b/src/H5Eint.c index 7818879..e76db82 100644 --- a/src/H5Eint.c +++ b/src/H5Eint.c @@ -883,11 +883,11 @@ H5E__clear_entries(H5E_t *estack, size_t nentries) /* Release strings */ if(error->func_name) - H5MM_xfree((void *)error->func_name); /* Casting away const OK - QAK */ + error->func_name = (const char *) H5MM_xfree((void *)error->func_name); /* Casting away const OK - QAK */ if(error->file_name) - H5MM_xfree((void *)error->file_name); /* Casting away const OK - QAK */ + error->file_name = (const char *) H5MM_xfree((void *)error->file_name); /* Casting away const OK - QAK */ if(error->desc) - H5MM_xfree((void *)error->desc); /* Casting away const OK - QAK */ + error->desc = (const char *) H5MM_xfree((void *)error->desc); /* Casting away const OK - QAK */ } /* end for */ /* Decrement number of errors on stack */ @@ -560,20 +560,21 @@ done: * * Purpose: Check if the file can be opened with the given fapl. * - * Return: TRUE/FALSE/FAIL + * Return: Succeed: TRUE/FALSE + * Failure: FAIL (includes file does not exist) * *------------------------------------------------------------------------- */ htri_t -H5Fis_accessible(const char *name, hid_t fapl_id) +H5Fis_accessible(const char *filename, hid_t fapl_id) { htri_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) - H5TRACE2("t", "*si", name, fapl_id); + H5TRACE2("t", "*si", filename, fapl_id); /* Check args */ - if(!name || !*name) + if(!filename || !*filename) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") /* Check the file access property list */ @@ -584,7 +585,7 @@ H5Fis_accessible(const char *name, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") /* Check if file is accessible */ - if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, name, &ret_value) < 0) + if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0) HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5") done: @@ -838,6 +839,68 @@ done: /*------------------------------------------------------------------------- + * Function: H5Fdelete + * + * Purpose: Deletes an HDF5 file. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fdelete(const char *filename, hid_t fapl_id) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ + htri_t is_hdf5 = FAIL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "*si", filename, fapl_id); + + /* Check args */ + if(!filename || !*filename) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") + + /* Check the file access property list */ + if(H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + + /* Get the VOL info from the fapl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(fapl_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list") + if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info") + + /* Stash a copy of the "top-level" connector property, before any pass-through + * connectors modify or unwrap it. + */ + if(H5CX_set_vol_connector_prop(&connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context") + + /* Make sure this is HDF5 storage for this VOL connector */ + if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &is_hdf5) < 0) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5") + if(!is_hdf5) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "not an HDF5 file") + + /* Delete the file */ + if(H5VL_file_specific(NULL, H5VL_FILE_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTDELETEFILE, FAIL, "unable to delete the file") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fdelete() */ + + +/*------------------------------------------------------------------------- * Function: H5Freopen * * Purpose: Reopen a file. The new file handle which is returned points diff --git a/src/H5Fint.c b/src/H5Fint.c index 2e8771c..ee9afed 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -863,7 +863,7 @@ H5F__is_hdf5(const char *name, hid_t fapl_id) * should work with arbitrary VFDs, unlike H5Fis_hdf5(). */ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF))) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to open file") /* The file is an hdf5 file if the hdf5 file signature can be found */ if(H5FD_locate_signature(file, &sig_addr) < 0) @@ -874,7 +874,7 @@ done: /* Close the file */ if(file) if(H5FD_close(file) < 0 && TRUE == ret_value) - HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file") FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__is_hdf5() */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 52f1ee2..dd794e4 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -233,6 +233,7 @@ H5_DLL hid_t H5Fopen(const char *filename, unsigned flags, H5_DLL hid_t H5Freopen(hid_t file_id); H5_DLL herr_t H5Fflush(hid_t object_id, H5F_scope_t scope); H5_DLL herr_t H5Fclose(hid_t file_id); +H5_DLL herr_t H5Fdelete(const char *filename, hid_t fapl_id); H5_DLL hid_t H5Fget_create_plist(hid_t file_id); H5_DLL hid_t H5Fget_access_plist(hid_t file_id); H5_DLL herr_t H5Fget_intent(hid_t file_id, unsigned *intent); diff --git a/src/H5Glink.c b/src/H5Glink.c index 82a2dcf..04ccbc5 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -402,15 +402,14 @@ done: /*------------------------------------------------------------------------- - * Function: H5G__link_sort_table + * Function: H5G__link_sort_table * * Purpose: Sort table containing a list of links for a group * - * Return: Success: Non-negative - * Failure: Negative + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * Nov 20, 2006 + * Programmer: Quincey Koziol + * Nov 20, 2006 * *------------------------------------------------------------------------- */ @@ -418,11 +417,20 @@ herr_t H5G__link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, H5_iter_order_t order) { + herr_t ret_value = SUCCEED; + FUNC_ENTER_PACKAGE_NOERR /* Sanity check */ HDassert(ltable); + /* Can't sort when empty since the links table will be NULL */ + if(0 == ltable->nlinks) + HGOTO_DONE(ret_value); + + /* This should never be NULL if the number of links is non-zero */ + HDassert(ltable->lnks); + /* Pick appropriate sorting routine */ if(idx_type == H5_INDEX_NAME) { if(order == H5_ITER_INC) @@ -442,6 +450,7 @@ H5G__link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, HDassert(order == H5_ITER_NATIVE); } /* end else */ +done: FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G__link_sort_table() */ @@ -2186,7 +2186,7 @@ H5Iget_name(hid_t id, char *name/*out*/, size_t size) loc_params.obj_type = H5I_get_type(id); /* Retrieve object's name */ - if(H5VL_object_get(vol_obj, &loc_params, H5VL_ID_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value, name, size) < 0) + if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value, name, size) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name") done: diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 56873ec..def785f 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -46,6 +46,7 @@ typedef enum H5I_type_t { H5I_ERROR_CLASS, /* type ID for error classes */ H5I_ERROR_MSG, /* type ID for error messages */ H5I_ERROR_STACK, /* type ID for error stacks */ + H5I_SPACE_SEL_ITER, /* type ID for dataspace selection iterator */ H5I_NTYPES /* number of library types, MUST BE LAST! */ } H5I_type_t; diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 0a7c4bf..f685a00c 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -200,7 +200,7 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, * What's actually shared, though, is only the extent. */ if(NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Decode attribute's dataspace extent */ if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, open_oh, @@ -253,15 +253,11 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, done: if(NULL == ret_value) if(attr) { - if(attr->shared) { - /* Free any dynamically allocated items */ - if(H5A__free(attr) < 0) + /* Free any dynamically allocated items */ + if(attr->shared) + if(H5A__shared_free(attr) < 0) HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't release attribute info") - /* Destroy shared attribute struct */ - attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); - } /* end if */ - attr = H5FL_FREE(H5A_t, attr); } /* end if */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index d87dc84..53abff3 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -156,7 +156,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ /* Format version bounds for fill value */ const unsigned H5O_fill_ver_bounds[] = { H5O_FILL_VERSION_1, /* H5F_LIBVER_EARLIEST */ - H5O_FILL_VERSION_2, /* H5F_LIBVER_V18 */ + H5O_FILL_VERSION_3, /* H5F_LIBVER_V18 */ H5O_FILL_VERSION_3, /* H5F_LIBVER_V110 */ H5O_FILL_VERSION_LATEST /* H5F_LIBVER_LATEST */ }; diff --git a/src/H5Pint.c b/src/H5Pint.c index b07f42d..04411a5 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -127,62 +127,65 @@ static herr_t H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H * Predefined property list classes. These are initialized at runtime by * H5P__init_package() in this source file. */ -hid_t H5P_CLS_ROOT_ID_g = FAIL; +hid_t H5P_CLS_ROOT_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ROOT_g = NULL; -hid_t H5P_CLS_OBJECT_CREATE_ID_g = FAIL; +hid_t H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g = NULL; -hid_t H5P_CLS_FILE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_CREATE_g = NULL; -hid_t H5P_CLS_FILE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_ACCESS_g = NULL; -hid_t H5P_CLS_DATASET_CREATE_ID_g = FAIL; +hid_t H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_CREATE_g = NULL; -hid_t H5P_CLS_DATASET_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_DATASET_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_ACCESS_g = NULL; -hid_t H5P_CLS_DATASET_XFER_ID_g = FAIL; +hid_t H5P_CLS_DATASET_XFER_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_XFER_g = NULL; -hid_t H5P_CLS_FILE_MOUNT_ID_g = FAIL; +hid_t H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_MOUNT_g = NULL; -hid_t H5P_CLS_GROUP_CREATE_ID_g = FAIL; +hid_t H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_GROUP_CREATE_g = NULL; -hid_t H5P_CLS_GROUP_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_GROUP_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g = NULL; -hid_t H5P_CLS_DATATYPE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g = NULL; -hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g = NULL; -hid_t H5P_CLS_OBJECT_COPY_ID_g = FAIL; +hid_t H5P_CLS_OBJECT_COPY_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_OBJECT_COPY_g = NULL; -hid_t H5P_CLS_LINK_CREATE_ID_g = FAIL; +hid_t H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_LINK_CREATE_g = NULL; -hid_t H5P_CLS_LINK_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_LINK_ACCESS_g = NULL; -hid_t H5P_CLS_STRING_CREATE_ID_g = FAIL; +hid_t H5P_CLS_STRING_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_STRING_CREATE_g = NULL; +hid_t H5P_CLS_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_VOL_INITIALIZE_g = NULL; /* * Predefined property lists for each predefined class. These are initialized * at runtime by H5P__init_package() in this source file. */ -hid_t H5P_LST_FILE_CREATE_ID_g = FAIL; -hid_t H5P_LST_FILE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATASET_CREATE_ID_g = FAIL; -hid_t H5P_LST_DATASET_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATASET_XFER_ID_g = FAIL; -hid_t H5P_LST_FILE_MOUNT_ID_g = FAIL; -hid_t H5P_LST_GROUP_CREATE_ID_g = FAIL; -hid_t H5P_LST_GROUP_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATATYPE_CREATE_ID_g = FAIL; -hid_t H5P_LST_DATATYPE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = FAIL; -hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_OBJECT_COPY_ID_g = FAIL; -hid_t H5P_LST_LINK_CREATE_ID_g = FAIL; -hid_t H5P_LST_LINK_ACCESS_ID_g = FAIL; +hid_t H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_XFER_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_GROUP_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_OBJECT_COPY_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; /* Root property list class library initialization object */ const H5P_libclass_t H5P_CLS_ROOT[1] = {{ @@ -283,6 +286,26 @@ const H5P_libclass_t H5P_CLS_TACC[1] = {{ NULL /* Class close callback info */ }}; +/* VOL initialization property list class library initialization object */ +/* (move to proper source code file when used for real) */ +const H5P_libclass_t H5P_CLS_VINI[1] = {{ + "VOL initialization", /* Class name for debugging */ + H5P_TYPE_VOL_INITIALIZE, /* Class type */ + + &H5P_CLS_ROOT_g, /* Parent class */ + &H5P_CLS_VOL_INITIALIZE_g, /* Pointer to class */ + &H5P_CLS_VOL_INITIALIZE_ID_g, /* Pointer to class ID */ + &H5P_LST_VOL_INITIALIZE_ID_g, /* Pointer to default property list ID */ + NULL, /* Default property registration routine */ + + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + /* Library property list classes defined in other code modules */ /* (And not present in src/H5Pprivate.h) */ @@ -331,7 +354,8 @@ static H5P_libclass_t const * const init_class[] = { H5P_CLS_TACC, /* Datatype access */ H5P_CLS_ACRT, /* Attribute creation */ H5P_CLS_AACC, /* Attribute access */ - H5P_CLS_LCRT /* Link creation */ + H5P_CLS_LCRT, /* Link creation */ + H5P_CLS_VINI /* VOL initialization */ }; /* Declare a free list to manage the H5P_genclass_t struct */ @@ -525,7 +549,8 @@ H5P_term_package(void) H5P_LST_OBJECT_COPY_ID_g = H5P_LST_LINK_CREATE_ID_g = H5P_LST_LINK_ACCESS_ID_g = - H5P_LST_FILE_MOUNT_ID_g = (-1); + H5P_LST_VOL_INITIALIZE_ID_g = + H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; } /* end if */ } /* end if */ @@ -552,6 +577,7 @@ H5P_term_package(void) H5P_CLS_OBJECT_COPY_g = H5P_CLS_LINK_CREATE_g = H5P_CLS_LINK_ACCESS_g = + H5P_CLS_VOL_INITIALIZE_g = H5P_CLS_FILE_MOUNT_g = NULL; H5P_CLS_ROOT_ID_g = @@ -571,7 +597,8 @@ H5P_term_package(void) H5P_CLS_OBJECT_COPY_ID_g = H5P_CLS_LINK_CREATE_ID_g = H5P_CLS_LINK_ACCESS_ID_g = - H5P_CLS_FILE_MOUNT_ID_g = (-1); + H5P_CLS_VOL_INITIALIZE_ID_g = + H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; } /* end if */ } /* end if */ @@ -5408,7 +5435,7 @@ H5P__new_plist_of_type(H5P_plist_type_t type) FUNC_ENTER_PACKAGE /* Sanity checks */ - HDcompile_assert(H5P_TYPE_ATTRIBUTE_ACCESS == (H5P_TYPE_MAX_TYPE - 1)); + HDcompile_assert(H5P_TYPE_VOL_INITIALIZE == (H5P_TYPE_MAX_TYPE - 1)); HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_LINK_ACCESS); /* Check arguments */ @@ -5487,6 +5514,10 @@ H5P__new_plist_of_type(H5P_plist_type_t type) class_id = H5P_CLS_LINK_ACCESS_ID_g; break; + case H5P_TYPE_VOL_INITIALIZE: + class_id = H5P_CLS_VOL_INITIALIZE_ID_g; + break; + case H5P_TYPE_USER: /* shut compiler warnings up */ case H5P_TYPE_ROOT: case H5P_TYPE_MAX_TYPE: diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 49f7a12..07910c3 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -78,6 +78,7 @@ typedef enum H5P_plist_type_t { H5P_TYPE_LINK_CREATE = 16, H5P_TYPE_LINK_ACCESS = 17, H5P_TYPE_ATTRIBUTE_ACCESS = 18, + H5P_TYPE_VOL_INITIALIZE = 19, H5P_TYPE_MAX_TYPE } H5P_plist_type_t; diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 90e6618..cad2071 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -68,6 +68,7 @@ #define H5P_OBJECT_COPY (H5OPEN H5P_CLS_OBJECT_COPY_ID_g) #define H5P_LINK_CREATE (H5OPEN H5P_CLS_LINK_CREATE_ID_g) #define H5P_LINK_ACCESS (H5OPEN H5P_CLS_LINK_ACCESS_ID_g) +#define H5P_VOL_INITIALIZE (H5OPEN H5P_CLS_VOL_INITIALIZE_ID_g) /* * The library's default property lists @@ -87,6 +88,7 @@ #define H5P_OBJECT_COPY_DEFAULT (H5OPEN H5P_LST_OBJECT_COPY_ID_g) #define H5P_LINK_CREATE_DEFAULT (H5OPEN H5P_LST_LINK_CREATE_ID_g) #define H5P_LINK_ACCESS_DEFAULT (H5OPEN H5P_LST_LINK_ACCESS_ID_g) +#define H5P_VOL_INITIALIZE_DEFAULT (H5OPEN H5P_LST_VOL_INITIALIZE_ID_g) /* Common creation order flags (for links in groups and attributes on objects) */ #define H5P_CRT_ORDER_TRACKED 0x0001 @@ -195,6 +197,7 @@ H5_DLLVAR hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g; H5_DLLVAR hid_t H5P_CLS_OBJECT_COPY_ID_g; H5_DLLVAR hid_t H5P_CLS_LINK_CREATE_ID_g; H5_DLLVAR hid_t H5P_CLS_LINK_ACCESS_ID_g; +H5_DLLVAR hid_t H5P_CLS_VOL_INITIALIZE_ID_g; /* Default roperty list IDs */ /* (Internal to library, do not use! Use macros above) */ @@ -213,6 +216,7 @@ H5_DLLVAR hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g; H5_DLLVAR hid_t H5P_LST_OBJECT_COPY_ID_g; H5_DLLVAR hid_t H5P_LST_LINK_CREATE_ID_g; H5_DLLVAR hid_t H5P_LST_LINK_ACCESS_ID_g; +H5_DLLVAR hid_t H5P_LST_VOL_INITIALIZE_ID_g; /*********************/ /* Public Prototypes */ @@ -93,6 +93,14 @@ static const H5I_class_t H5I_DATASPACE_CLS[1] = {{ (H5I_free_t)H5S_close /* Callback routine for closing objects of this class */ }}; +/* Dataspace selection iterator ID class */ +static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{ + H5I_SPACE_SEL_ITER, /* ID class value */ + 0, /* Class flags */ + 0, /* # of reserved IDs for class */ + (H5I_free_t)H5S_sel_iter_close /* Callback routine for closing objects of this class */ +}}; + /* Flag indicating "top" of interface has been initialized */ static hbool_t H5S_top_package_initialize_s = FALSE; @@ -120,6 +128,10 @@ H5S__init_package(void) if(H5I_register_type(H5I_DATASPACE_CLS) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class") + /* Initialize the atom group for the dataspace selction iterator IDs */ + if(H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace selection iterator ID class") + /* Mark "top" of interface as initialized, too */ H5S_top_package_initialize_s = TRUE; @@ -159,6 +171,11 @@ H5S_top_term_package(void) n++; /*H5I*/ } /* end if */ + if(H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) { + (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE); + n++; /*H5I*/ + } /* end if */ + /* Mark "top" of interface as closed */ if(0 == n) H5S_top_package_initialize_s = FALSE; @@ -198,11 +215,15 @@ H5S_term_package(void) if(H5_PKG_INIT_VAR) { /* Sanity checks */ HDassert(0 == H5I_nmembers(H5I_DATASPACE)); + HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER)); HDassert(FALSE == H5S_top_package_initialize_s); /* Destroy the dataspace object id group */ n += (H5I_dec_type_ref(H5I_DATASPACE) > 0); + /* Destroy the dataspace selection iterator object id group */ + n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0); + /* Mark interface as closed */ if(0 == n) H5_PKG_INIT_VAR = FALSE; @@ -448,10 +469,14 @@ H5S_close(H5S_t *ds) if(H5S__extent_release(&ds->extent) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent") - /* Release the main structure */ - ds = H5FL_FREE(H5S_t, ds); - done: + /* Release the main structure. + * Always do this to ensure that we don't leak memory when calling this + * function on partially constructed dataspaces (which will fail one or + * both of the above calls) + */ + H5FL_FREE(H5S_t, ds); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_close() */ diff --git a/src/H5Shyper.c b/src/H5Shyper.c index c2cdf2b..4c8e458 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -44,25 +44,13 @@ /* Macro for checking if two ranges overlap one another */ /* - * Three possible conditions for overlapping: - * 1. The lower bound of range #1 is between the lower and - * higher bounds of range #2. In other words, the low - * part of range #1 will at least overlap with range #2. - * 2. The higher bound of range #1 is between the lower and - * higher bounds of range #2. In other words, the upper - * part of range #1 will at least overlap with range #2. - * 3. Range #1 includes range #2, i.e. the lower bound - * is smaller than that of range #2 and the higher bound - * is larger than that of range #2. + * Check for the inverse of whether the ranges are disjoint. If they are + * disjoint, then the low bound of one of the ranges must be greater than the + * high bound of the other. */ /* (Assumes that low & high bounds are _inclusive_) */ #define H5S_RANGE_OVERLAP(L1, H1, L2, H2) \ - /* condition 1 */ \ - (((L1) >= (L2) && (L1) <= (H2)) || \ - /* condition 2 */ \ - ((H1) >= (L2) && (H1) <= (H2)) || \ - /* condition 3 */ \ - ((L1) <= (L2) && (H1) >= (H2))) + (!((L1) > (H2) || (L2) > (H1))) /* Flags for which hyperslab fragments to compute */ #define H5S_HYPER_COMPUTE_B_NOT_A 0x01 @@ -84,6 +72,18 @@ (curr_span) = saved_next_span; \ } while(0) +/* Macro to add "skipped" elements to projection during the execution of + * H5S__hyper_project_intersect() */ +#define H5S_HYPER_PROJ_INT_ADD_SKIP(UDATA, ADD, ERR) \ + do { \ + /* If there are any elements to add, we must add them \ + * to the projection first before adding skip */ \ + if((UDATA)->nelem > 0) \ + if(H5S__hyper_proj_int_build_proj(UDATA) < 0) \ + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, ERR, "can't add elements to projected selection") \ + (UDATA)->skip += (ADD); \ + } while(0) /* end H5S_HYPER_PROJ_INT_ADD_SKIP() */ + /******************/ /* Local Typedefs */ @@ -93,6 +93,28 @@ /* (Makes it easier to understand the alloc / free calls) */ typedef hsize_t hbounds_t; +/* Struct for holding persistent information during iteration for + * H5S__hyper_project_intersect() */ +typedef struct { + const H5S_hyper_span_t *ds_span[H5S_MAX_RANK]; /* Array of the current spans in the destination space in each dimension */ + hsize_t ds_low[H5S_MAX_RANK]; /* Array of current low bounds (of iteration) for each element in ds_span */ + H5S_hyper_span_info_t *ps_span_info[H5S_MAX_RANK]; /* Array of span info structs for projected space during iteration */ + uint32_t ps_clean_bitmap; /* Bitmap of whether the nth rank has a clean projected space since the last time it was set to 1 */ + unsigned ss_rank; /* Rank of source space */ + unsigned ds_rank; /* Rank of destination space */ + unsigned depth; /* Current depth of iterator in destination space */ + hsize_t skip; /* Number of elements to skip in projected space */ + hsize_t nelem; /* Number of elements to add to projected space (after skip) */ + uint64_t op_gen; /* Operation generation for counting elements */ +} H5S_hyper_project_intersect_ud_t; + +/* Assert that H5S_MAX_RANK is <= 32 so our trick with using a 32 bit bitmap + * (ps_clean_bitmap) works. If H5S_MAX_RANK increases either increase the size + * of ps_clean_bitmap or change the algorithm to use an array. */ +#if H5S_MAX_RANK > 32 +#error H5S_MAX_RANK too large for ps_clean_bitmap field in H5S_hyper_project_intersect_ud_t struct +#endif + /********************/ /* Local Prototypes */ @@ -119,6 +141,8 @@ static herr_t H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, unsigned ndims, H5S_hyper_span_info_t **a_not_b, H5S_hyper_span_info_t **a_and_b, H5S_hyper_span_info_t **b_not_a); static herr_t H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); +static hsize_t H5S__hyper_spans_nelem_helper(H5S_hyper_span_info_t *spans, + uint64_t op_gen); static hsize_t H5S__hyper_spans_nelem(H5S_hyper_span_info_t *spans); static herr_t H5S__hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); static H5S_hyper_span_info_t *H5S__hyper_make_spans(unsigned rank, @@ -147,6 +171,10 @@ static herr_t H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxs size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len); static herr_t H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len); +static herr_t H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata); +static herr_t H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info, + const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth, + H5S_hyper_project_intersect_ud_t *udata); static void H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count, hsize_t *block, hsize_t clip_size); static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, @@ -698,10 +726,27 @@ H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) else { /* Initialize the information needed for non-regular hyperslab I/O */ H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */ - /* Share the source dataspace's span tree by incrementing the reference count on it */ - HDassert(space->select.sel_info.hslab->span_lst); - iter->u.hyp.spans = space->select.sel_info.hslab->span_lst; - iter->u.hyp.spans->count++; + /* If this iterator is created from an API call, by default we clone the + * selection now, as the dataspace could be modified or go out of scope. + * + * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given, + * the selection is shared between the selection iterator and the + * dataspace. In this case, the application _must_not_ modify or + * close the dataspace that the iterator is operating on, or undefined + * behavior will occur. + */ + if((iter->flags & H5S_SEL_ITER_API_CALL) && + !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) { + /* Copy the span tree */ + if(NULL == (iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst, space->extent.rank))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy span tree") + } /* end if */ + else { + /* Share the source dataspace's span tree by incrementing the reference count on it */ + HDassert(space->select.sel_info.hslab->span_lst); + iter->u.hyp.spans = space->select.sel_info.hslab->span_lst; + iter->u.hyp.spans->count++; + } /* end else */ /* Initialize the starting span_info's and spans */ spans = iter->u.hyp.spans; @@ -3403,7 +3448,7 @@ H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref) /* Check each dimension */ for(ret_value = 1, u = 0; u < space->extent.rank; u++) ret_value *= (app_ref ? space->select.sel_info.hslab->diminfo.app[u].count : - space->select.sel_info.hslab->diminfo.opt[u].count); + space->select.sel_info.hslab->diminfo.opt[u].count); } /* end if */ else ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst); @@ -10380,6 +10425,213 @@ done: } /* end H5S__fill_in_select() */ +/*-------------------------------------------------------------------------- + NAME + H5Scombine_hyperslab + PURPOSE + Specify a hyperslab to combine with the current hyperslab selection and + return a new dataspace with the combined selection as the selection in the + new dataspace. + USAGE + hid_t H5Scombine_hyperslab(dsid, op, start, stride, count, block) + hid_t dsid; IN: Dataspace ID of selection to use + H5S_seloper_t op; IN: Operation to perform on current selection + const hsize_t *start; IN: Offset of start of hyperslab + const hsize_t *stride; IN: Hyperslab stride + const hsize_t *count; IN: Number of blocks included in hyperslab + const hsize_t *block; IN: Size of block in hyperslab + RETURNS + Dataspace ID on success / H5I_INVALID_HID on failure + DESCRIPTION + Combines a hyperslab selection with the current selection for a dataspace, + creating a new dataspace to return the generated selection. + If the current selection is not a hyperslab, it is freed and the hyperslab + parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a + selection composing the entire current extent). If STRIDE or BLOCK is + NULL, they are assumed to be set to all '1'. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t +H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], + const hsize_t stride[], const hsize_t count[], const hsize_t block[]) +{ + H5S_t *space; /* Dataspace to modify selection of */ + H5S_t *new_space = NULL; /* New dataspace created */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block); + + /* Check args */ + if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace") + if(start == NULL || count == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "hyperslab not specified") + if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA)) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation") + + /* Generate new space, with combination of selections */ + if(H5S_combine_hyperslab(space, op, start, stride, count, block, &new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to set hyperslab selection") + + /* Atomize */ + if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom") + +done: + if(ret_value < 0 && new_space) + H5S_close(new_space); + + FUNC_LEAVE_API(ret_value) +} /* end H5Scombine_hyperslab() */ + + +/*------------------------------------------------------------------------- + * Function: H5S__combine_select + * + * Purpose: Internal version of H5Scombine_select(). + * + * Return: New dataspace on success/NULL on failure + * + * Programmer: Quincey Koziol + * Tuesday, October 30, 2001 + * + *------------------------------------------------------------------------- + */ +static H5S_t * +H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2) +{ + H5S_t *new_space = NULL; /* New dataspace generated */ + H5S_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check args */ + HDassert(space1); + HDassert(space2); + HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA); + + /* Check if space1 selections has span trees */ + if(NULL == space1->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans(space1) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree") + + if(NULL == space2->select.sel_info.hslab->span_lst) { + hsize_t tmp_start[H5S_MAX_RANK]; + hsize_t tmp_stride[H5S_MAX_RANK]; + hsize_t tmp_count[H5S_MAX_RANK]; + hsize_t tmp_block[H5S_MAX_RANK]; + unsigned u; + + for(u = 0; u < space2->extent.rank; u++) { + tmp_start[u] = space2->select.sel_info.hslab->diminfo.opt[u].start; + tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride; + tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count; + tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block; + } /* end for */ + + /* Combine hyperslab selection with regular selection directly */ + if(H5S_combine_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block, &new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to set hyperslab selection") + } /* end if */ + else{ + /* Combine new_space (a copy of space 1) & space2, with the result in new_space */ + if(H5S__fill_in_select(space1, op, space2, &new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information") + } /* end else */ + + /* Set unlim_dim */ + new_space->select.sel_info.hslab->unlim_dim = -1; + + /* Set return value */ + ret_value = new_space; + +done: + if(ret_value == NULL && new_space) + H5S_close(new_space); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__combine_select() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Scombine_select + PURPOSE + Combine two hyperslab selections with an operation, returning a dataspace + with the resulting selection. + USAGE + hid_t H5Scombine_select(space1, op, space2) + hid_t space1; IN: First Dataspace ID + H5S_seloper_t op; IN: Selection operation + hid_t space2; IN: Second Dataspace ID + RETURNS + Dataspace ID on success / H5I_INVALID_HID on failure + DESCRIPTION + Combine two existing hyperslab selections with an operation, returning + a new dataspace with the resulting selection. The dataspace extent from + space1 is copied for the dataspace extent of the newly created dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t +H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id) +{ + H5S_t *space1; /* First Dataspace */ + H5S_t *space2; /* Second Dataspace */ + H5S_t *new_space = NULL; /* New Dataspace */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "iSsi", space1_id, op, space2_id); + + /* Check args */ + if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace") + if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace") + if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA)) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation") + + /* Check that both dataspaces have the same rank */ + if(space1->extent.rank != space2->extent.rank) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same rank") + + /* Note: currently, the offset of each dataspace is ignored */ +#if 0 + /* Check that both dataspaces have the same offset */ + /* Same note as in H5Smodify_select */ + for(u=0; u<space1->extent.rank; u++) { + if(space1->select.offset[u] != space2->select.offset[u]) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same offset") + } /* end for */ +#endif + + /* Check that both dataspaces have hyperslab selections */ + if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces don't have hyperslab selections") + + /* Go combine the dataspaces */ + if(NULL == (new_space = H5S__combine_select(space1, op, space2))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create hyperslab selection") + + /* Atomize */ + if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom") + +done: + if(ret_value < 0 && new_space) + H5S_close(new_space); + + FUNC_LEAVE_API(ret_value) +} /* end H5Scombine_select() */ + + /*------------------------------------------------------------------------- * Function: H5S__modify_select * @@ -10442,6 +10694,661 @@ done: /*-------------------------------------------------------------------------- NAME + H5Smodify_select + PURPOSE + Refine a hyperslab selection with an operation using a second hyperslab + to modify it + USAGE + herr_t H5Smodify_select(space1, op, space2) + hid_t space1; IN/OUT: First Dataspace ID + H5S_seloper_t op; IN: Selection operation + hid_t space2; IN: Second Dataspace ID + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Refine an existing hyperslab selection with an operation, using a second + hyperslab. The first selection is modified to contain the result of + space1 operated on by space2. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id) +{ + H5S_t *space1; /* First Dataspace */ + H5S_t *space2; /* Second Dataspace */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iSsi", space1_id, op, space2_id); + + /* Check args */ + if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA)) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") + + /* Check that both dataspaces have the same rank */ + if(space1->extent.rank != space2->extent.rank) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank") + + /* Check that both dataspaces have the same offset */ + /** Note that this is a tricky part of this function. It's + * possible that two dataspaces have different "offset". If the + * space2 has smaller offset value than that of space1 in a + * dimension, then the span elements of this dimension in + * space2 could have negative "low" and "high" values relative + * to the offset in space1. In other words, if the bounds of + * span elements in space2 are adjusted relative to the offset + * in space1, then every span element's bound is computed as + * "origin_bound+offset2-offset1". Therefore, if offset2 (the + * offset of space2) is smaller, then + * "origin_bound+offset2-offset1" could be negative which is + * not allowed by the bound type declaration as hsize_t! + * As a result, if the op is an OR selection, then the final + * result may contain span elements that have negative bound! + * So right now, the difference in the offset is totally + * ignored!! + */ +#if 0 + for(u=0; u<space1->extent.rank; u++) { + if(space1->select.offset[u] != space2->select.offset[u]) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset") + } /* end for */ +#endif + + /* Check that both dataspaces have hyperslab selections */ + if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections") + + /* Go refine the first selection */ + if(H5S__modify_select(space1, op, space2) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Smodify_select() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__hyper_proj_int_build_proj + PURPOSE + Secondary iteration routine for H5S__hyper_project_intersection + USAGE + herr_t H5S__hyper_proj_int_build_proj(udata) + H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Takes the skip and nelem amounts listed in udata and converts them to + span trees in the projected space, using the destination space. This + is a non-recursive algorithm by necessity, it saves the current state + of iteration in udata and resumes in the same location on subsequent + calls. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata) { + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + HDassert(udata->nelem > 0); + + /* + * Skip over skipped elements + */ + if(udata->skip > 0) { + /* Work upwards, finishing each span tree before moving up */ + HDassert(udata->ds_span[udata->depth]); + do { + /* Check for lowest dimension */ + if(udata->ds_span[udata->depth]->down) { + if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) { + /* If we will run out of elements to skip in this span, + * advance to the first not fully skipped span and break + * out of this loop (start moving downwards) */ + if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts; + udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + } /* end if */ + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + + /* If we will run out of elements to skip in this span, + * skip the remainder of the skipped elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip; + udata->skip = 0; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + } /* end else */ + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + if(udata->ds_span[udata->depth]) + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + else if(udata->depth > 0) { + /* If present, append this span tree to the higher dimension's, + * and release ownership of it */ + if(udata->ps_span_info[udata->depth]) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1], + udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1], + udata->ds_low[udata->depth - 1], + udata->ps_span_info[udata->depth]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]); + udata->ps_span_info[udata->depth] = NULL; + } /* end if */ + + /* Ran out of spans, move up one dimension */ + udata->depth--; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth]++; + } /* end if */ + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection") + } while((udata->skip > 0) + || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high)); + + /* Work downwards until skip is 0 */ + HDassert(udata->ds_span[udata->depth]); + while(udata->skip > 0) { + HDassert(udata->ds_span[udata->depth]->down); + udata->depth++; + udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head; + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + if(udata->ds_span[udata->depth]->down) { + do { + /* If we will run out of elements to skip in this span, + * advance to the first not fully skipped span and + * continue down */ + if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts; + udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->skip > 0); + } /* end if */ + else { + do { + /* If we will run out of elements to skip in this span, + * skip the remainder of the skipped elements */ + if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip; + udata->skip = 0; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->skip > 0); + } /* end else */ + } /* end while */ + } /* end if */ + + /* + * Add requested number of elements to projected space + */ + /* Work upwards, adding all elements of each span tree until it can't fit + * all elements */ + HDassert(udata->ds_span[udata->depth]); + do { + /* Check for lowest dimension */ + if(udata->ds_span[udata->depth]->down) { + if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) { + /* If we will run out of elements to add in this span, add + * any complete spans, advance to the first not fully added + * span, and break out of this loop (start moving downwards) + */ + if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts; + udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts; + } /* end if */ + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_span[udata->depth]->high, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + } /* end if */ + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + + /* If we will run out of elements to add in this span, add the + * remainder of the elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem; + udata->nelem = 0; + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + } /* end else */ + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + if(udata->ds_span[udata->depth]) + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + else if(udata->depth > 0) { + /* Append this span tree to the higher dimension's, and release + * ownership of it */ + HDassert(udata->ps_span_info[udata->depth]); + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1], + udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1], + udata->ds_low[udata->depth - 1], + udata->ps_span_info[udata->depth]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]); + udata->ps_span_info[udata->depth] = NULL; + + /* Ran out of spans, move up one dimension */ + udata->depth--; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth]++; + } /* end if */ + else { + /* We have finished the entire destination span tree. If there are + * still elements to add, issue an error. */ + if(udata->nelem > 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection") + break; + } /* end else */ + } while((udata->nelem > 0) + || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high)); + + /* Work downwards until nelem is 0 */ + HDassert(udata->ds_span[udata->depth] || (udata->nelem == 0)); + while(udata->nelem > 0) { + HDassert(udata->ds_span[udata->depth]->down); + udata->depth++; + udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head; + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + if(udata->ds_span[udata->depth]->down) { + do { + /* If we will run out of elements to add in this span, add + * any complete spans, advance to the first not fully added + * span and continue down + */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts; + udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts; + } /* end if */ + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_span[udata->depth]->high, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->nelem > 0); + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + do { + /* If we will run out of elements to add in this span, add + * the remainder of the elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem; + udata->nelem = 0; + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->nelem > 0); + } /* end else */ + } /* end while */ + + HDassert(udata->skip == 0); + HDassert(udata->nelem == 0); + + /* Mark projected space as changed (for all ranks) */ + udata->ps_clean_bitmap = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__hyper_proj_int_build_proj() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__hyper_proj_int_iterate + PURPOSE + Main iteration routine for H5S__hyper_project_intersection + USAGE + herr_t H5S__hyper_proj_int_iterate(ss_span_info,sis_span_info,count,depth,udata) + const H5S_hyper_span_info_t *ss_span_info; IN: Span tree for source selection + const H5S_hyper_span_info_t *sis_span_info; IN: Span tree for source intersect selection + hsize_t count; IN: Number of times to compute the intersection of ss_span_info and sis_span_info + unsigned depth; IN: Depth of iteration (in terms of rank) + H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Computes the intersection of ss_span_info and sis_span_info and projects it + to the projected space (held in udata). It accomplishes this by iterating + over both spaces and computing the number of elements to skip (in + ss_span_info) and the number of elements to add (the intersection) in a + sequential fashion (similar to run length encoding). As necessary, this + function both recurses into lower dimensions and calls + H5S__hyper_proj_int_build_proj to convert the skip/nelem pairs to the + projected span tree. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info, + const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth, + H5S_hyper_project_intersect_ud_t *udata) +{ + const H5S_hyper_span_t *ss_span; /* Current span in source space */ + const H5S_hyper_span_t *sis_span; /* Current span in source intersect space */ + hsize_t ss_low; /* Current low bounds of source span */ + hsize_t sis_low; /* Current low bounds of source intersect span */ + hsize_t high; /* High bounds of current intersection */ + hsize_t low; /* Low bounds of current intersection */ + hsize_t old_skip; /* Value of udata->skip before main loop */ + hsize_t old_nelem; /* Value of udata->nelem before main loop */ + hbool_t check_intersect; /* Whether to check for intersecting elements */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check for non-overlapping bounds */ + check_intersect = TRUE; + for(u = 0; u < (udata->ss_rank - depth); u++) + if(!H5S_RANGE_OVERLAP(ss_span_info->low_bounds[u], + ss_span_info->high_bounds[u], + sis_span_info->low_bounds[u], + sis_span_info->high_bounds[u])) { + check_intersect = FALSE; + break; + } /* end if */ + + /* Only enter main loop if there's something to do */ + if(check_intersect) { + /* Set ps_clean_bitmap */ + udata->ps_clean_bitmap |= (((uint32_t)1) << depth); + + /* Save old skip and nelem */ + old_skip = udata->skip; + old_nelem = udata->nelem; + + /* Intersect spaces once per count */ + for(u = 0; u < count; u++) { + ss_span = ss_span_info->head; + sis_span = sis_span_info->head; + HDassert(ss_span && sis_span); + ss_low = ss_span->low; + sis_low = sis_span->low; + + /* Main loop */ + do { + /* Check if spans overlap */ + if(H5S_RANGE_OVERLAP(ss_low, ss_span->high, + sis_low, sis_span->high)) { + high = MIN(ss_span->high, sis_span->high); + if(ss_span->down) { + /* Add skipped elements if there's a pre-gap */ + if(ss_low < sis_low) { + low = sis_low; + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (sis_low - ss_low), FAIL); + } /* end if */ + else + low = ss_low; + + /* Recurse into next dimension down */ + if(H5S__hyper_proj_int_iterate(ss_span->down, sis_span->down, high - low + 1, depth + 1, udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't iterate over source selections") + } /* end if */ + else { + HDassert(depth == udata->ss_rank - 1); + + /* Add skipped elements if there's a pre-gap */ + if(ss_low < sis_low) { + low = sis_low; + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, sis_low - ss_low, FAIL); + } /* end if */ + else + low = ss_low; + + /* Add overlapping elements */ + udata->nelem += high - low + 1; + } /* end else */ + + /* Advance spans */ + if(ss_span->high == sis_span->high) { + /* Advance both spans */ + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end if */ + else if(ss_span->high == high) { + /* Advance source span */ + HDassert(ss_span->high < sis_span->high); + sis_low = high + 1; + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + } /* end if */ + else { + /* Advance source intersect span */ + HDassert(ss_span->high > sis_span->high); + ss_low = high + 1; + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end else */ + } /* end if */ + else { + /* Advance spans */ + if(ss_span->high < sis_low) { + /* Add skipped elements */ + if(ss_span->down) + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL); + else + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL); + + /* Advance source span */ + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + } /* end if */ + else { + /* Advance source intersect span */ + HDassert(ss_low > sis_span->high); + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end else */ + } /* end else */ + } while(ss_span && sis_span); + + if(ss_span && !((depth == 0) && (u == count - 1))) { + /* Count remaining elements in ss_span_info */ + if(ss_span->down) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL); + ss_span = ss_span->next; + while(ss_span) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_span->low + 1), FAIL); + ss_span = ss_span->next; + } /* end while */ + } /* end if */ + else { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL); + ss_span = ss_span->next; + while(ss_span) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_span->low + 1, FAIL); + ss_span = ss_span->next; + } /* end while */ + } /* end else */ + } /* end if */ + + /* Check if the projected space was not changed since we started the + * first iteration of the loop, if so we do not need to continue + * looping and can just copy the result */ + if(udata->ps_clean_bitmap & (((uint32_t)1) << depth)) { + HDassert(u == 0); + if(udata->skip == old_skip) { + /* First case: algorithm added only elements */ + HDassert(udata->nelem >= old_nelem); + udata->nelem += (count - 1) * (udata->nelem - old_nelem); + } /* end if */ + else if(udata->nelem == 0) { + /* Second case: algorithm added only skip. In this case, + * nelem must be 0 since otherwise adding skip would have + * triggered a change in the projected space */ + HDassert(old_nelem == 0); + HDassert(udata->skip > old_skip); + udata->skip += (count - 1) * (udata->skip - old_skip); + } /* end if */ + else { + /* Third case: agorithm added skip and nelem (in that + * order). Add the same skip and nelem once for each item + * remaining in count. */ + hsize_t skip_add; + hsize_t nelem_add; + + HDassert(udata->nelem > 0); + HDassert(udata->skip > old_skip); + HDassert(old_nelem == 0); + + skip_add = udata->skip - old_skip; + nelem_add = udata->nelem - old_nelem; + for(u = 1; u < count; u++) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, skip_add, FAIL); + udata->nelem += nelem_add; + } /* end for */ + } /* end else */ + + /* End loop since we already took care of it */ + break; + } /* end if */ + } /* end for */ + } /* end if */ + else if(depth > 0) + /* Just count skipped elements */ + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper((H5S_hyper_span_info_t *)ss_span_info, udata->op_gen) * count, FAIL); /* Casting away const OK -NAF */ + + /* Clean up if we are done */ + if(depth == 0) { + /* Add remaining elements */ + if(udata->nelem > 0) + if(H5S__hyper_proj_int_build_proj(udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't add elements to projected selection") + + /* Append remaining span trees */ + for(u = udata->ds_rank - 1; u > 0; u--) + if(udata->ps_span_info[u]) { + if(H5S__hyper_append_span(&udata->ps_span_info[u - 1], + udata->ds_rank - u + 1, udata->ds_low[u - 1], + udata->ds_low[u - 1], + udata->ps_span_info[u]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[u]); + udata->ps_span_info[u] = NULL; + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__hyper_proj_int_iterate() */ + + +/*-------------------------------------------------------------------------- + NAME H5S__hyper_project_intersection PURPOSE Projects the intersection of of the selections of src_space and @@ -10461,7 +11368,9 @@ done: within the selection of dst_space. The result is placed in the selection of proj_space. Note src_space, dst_space, and src_intersect_space do not need to use hyperslab selections, but they cannot use point selections. - The result is always a hyperslab selection. + The result is always a hyperslab or none selection. Note also that + proj_space can share some span trees with dst_space, so proj_space + must not be subsequently modified if dst_space must be preserved. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES @@ -10471,43 +11380,11 @@ herr_t H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, const H5S_t *src_intersect_space, H5S_t *proj_space) { - hsize_t ss_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_space */ - size_t ss_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_space */ - size_t ss_nseq; /* Number of sequences for src_space */ - size_t ss_nelem; /* Number of elements for src_space */ - size_t ss_i = (size_t)0; /* Index into offset/length arrays for src_space */ - hbool_t advance_ss = FALSE; /* Whether to advance ss_i on the next iteration */ - H5S_sel_iter_t *ss_iter = NULL; /* Selection iterator for src_space */ - hbool_t ss_iter_init = FALSE; /* Whether ss_iter is initialized */ - hsize_t ss_sel_off = (hsize_t)0; /* Offset within src_space selection */ - hsize_t ds_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for dst_space */ - size_t ds_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for dst_space */ - size_t ds_nseq; /* Number of sequences for dst_space */ - size_t ds_nelem; /* Number of elements for dst_space */ - size_t ds_i = (size_t)0; /* Index into offset/length arrays for dst_space */ - H5S_sel_iter_t *ds_iter = NULL; /* Selection iterator for dst_space */ - hbool_t ds_iter_init = FALSE; /* Whether ds_iter is initialized */ - hsize_t ds_sel_off = (hsize_t)0; /* Offset within dst_space selection */ - hsize_t sis_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_intersect_space */ - size_t sis_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_intersect_space */ - size_t sis_nseq; /* Number of sequences for src_intersect_space */ - size_t sis_nelem; /* Number of elements for src_intersect_space */ - size_t sis_i = (size_t)0; /* Index into offset/length arrays for src_intersect_space */ - hbool_t advance_sis = FALSE; /* Whether to advance sis_i on the next iteration */ - H5S_sel_iter_t *sis_iter = NULL; /* Selection iterator for src_intersect_space */ - hbool_t sis_iter_init = FALSE; /* Whether sis_iter is initialized */ - hsize_t int_sel_off; /* Offset within intersected selections (ss/sis and ds/ps) */ - size_t int_len; /* Length of segment in intersected selections */ - hsize_t proj_off; /* Segment offset in proj_space */ - size_t proj_len; /* Segment length in proj_space */ - size_t proj_len_rem; /* Remaining length in proj_space for segment */ - hsize_t proj_down_dims[H5S_MAX_RANK]; /* "Down" dimensions in proj_space */ - H5S_hyper_span_info_t *curr_span_tree[H5S_MAX_RANK]; /* Current span tree being built (in each dimension) */ - hsize_t curr_span_up_dim[H5S_MAX_RANK]; /* "Up" dimensions for current span */ - unsigned proj_rank; /* Rank of proj_space */ - hsize_t low; /* Low value of span */ - size_t nelem; /* Number of elements returned for get_seq_list op */ - unsigned u; /* Local index variable */ + H5S_hyper_project_intersect_ud_t udata; /* User data for subroutines */ + const H5S_hyper_span_info_t *ss_span_info; + const H5S_hyper_span_info_t *ds_span_info; + H5S_hyper_span_info_t *ss_span_info_buf = NULL; + H5S_hyper_span_info_t *ds_span_info_buf = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -10521,280 +11398,88 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, /* Assert that src_space and src_intersect_space have same extent and there * are no point selections */ HDassert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space)); - HDassert(!HDmemcmp(src_space->extent.size, src_intersect_space->extent.size, - (size_t)H5S_GET_EXTENT_NDIMS(src_space) * sizeof(src_space->extent.size[0]))); + HDassert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space)); HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_POINTS); HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_POINTS); - HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) != H5S_SEL_POINTS); - - /* Initialize prev_space, curr_span_tree, and curr_span_up_dim */ - HDmemset(curr_span_tree, 0, sizeof(curr_span_tree)); - HDmemset(curr_span_up_dim, 0, sizeof(curr_span_up_dim)); - - /* Save rank of projected space */ - proj_rank = proj_space->extent.rank; - HDassert(proj_rank > 0); - - /* Get numbers of elements */ - ss_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_space); - ds_nelem = (size_t)H5S_GET_SELECT_NPOINTS(dst_space); - sis_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_intersect_space); - HDassert(ss_nelem == ds_nelem); - - /* Calculate proj_down_dims */ - if(H5VM_array_down(proj_rank, proj_space->extent.size, proj_down_dims) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value") - - /* Remove current selection from proj_space */ - if(H5S_SELECT_RELEASE(proj_space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - - /* If any selections are empty, skip to the end so "none" is selected */ - if((ss_nelem == 0) || (ds_nelem == 0) || (sis_nelem == 0)) - goto loop_end; - - /* Allocate space for the hyperslab selection information (note this sets - * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */ - if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info") - - /* Set selection type */ - proj_space->select.type = H5S_sel_hyper; - - /* Set unlim_dim */ - proj_space->select.sel_info.hslab->unlim_dim = -1; - - /* Allocate the source selection iterator */ - if(NULL == (ss_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source selection iterator") - - /* Initialize source space iterator */ - if(H5S_select_iter_init(ss_iter, src_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ss_iter_init = TRUE; - - /* Get sequence list for source space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - ss_nelem -= nelem; - HDassert(ss_nseq > 0); - - /* Allocate the destination selection iterator */ - if(NULL == (ds_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate destination selection iterator") - - /* Initialize destination space iterator */ - if(H5S_select_iter_init(ds_iter, dst_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ds_iter_init = TRUE; - - /* Get sequence list for destination space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ds_nelem -= nelem; - HDassert(ds_nseq > 0); - - /* Allocate the source intersect space iterator */ - if(NULL == (sis_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source intersect space iterator") - - /* Initialize source intersect space iterator */ - if(H5S_select_iter_init(sis_iter, src_intersect_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - sis_iter_init = TRUE; - - /* Get sequence list for source intersect space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - sis_nelem -= nelem; - HDassert(sis_nseq > 0); - - /* Loop until we run out of sequences in either the source or source - * intersect space */ - while(1) { - while(advance_ss || (ss_off[ss_i] + ss_len[ss_i] <= sis_off[sis_i])) { - /* Either we finished the current source sequence or the - * sequences do not intersect. Advance source space. */ - ss_sel_off += (hsize_t)ss_len[ss_i]; - if(++ss_i == ss_nseq) { - if(ss_nelem > 0) { - /* Try to grab more sequences from src_space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(ss_len[0] > 0); - - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= ss_nelem); - ss_nelem -= nelem; - - /* Reset source space index */ - ss_i = 0; - } /* end if */ - else - /* There are no more sequences in src_space, so we can exit - * the loop. Use goto instead of break so we exit the outer - * loop. */ - goto loop_end; - } /* end if */ + HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS); - /* Reset advance_ss */ - advance_ss = FALSE; - } /* end while */ - if(advance_sis || (sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i])) { - do { - /* Either we finished the current source intersect sequence or - * the sequences do not intersect. Advance source intersect - * space. */ - if(++sis_i == sis_nseq) { - if(sis_nelem > 0) { - /* Try to grab more sequences from src_intersect_space - */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(sis_len[0] > 0); + /* Set up ss_span_info */ + if(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_HYPERSLABS) { + /* Make certain the selection has a span tree */ + if(NULL == src_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)src_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source hyperslab selection") - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= sis_nelem); - sis_nelem -= nelem; + /* Simply point to existing span tree */ + ss_span_info = src_space->select.sel_info.hslab->span_lst; + } /* end if */ + else { + /* Create temporary span tree from all selection */ + HDassert(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_ALL); - /* Reset source space index */ - sis_i = 0; - } /* end if */ - else - /* There are no more sequences in src_intersect_space, - * so we can exit the loop. Use goto instead of break - * so we exit the outer loop. */ - goto loop_end; - } /* end if */ - } while(sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i]); + if(NULL == (ss_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(src_space), + H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, src_space->extent.size))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL source space") + ss_span_info = ss_span_info_buf; + } /* end else */ - /* Reset advance_sis */ - advance_sis = FALSE; - } /* end if */ - else { - /* Sequences intersect, add intersection to projected space */ - /* Calculate intersection sequence in terms of offset within source - * selection and advance any sequences we complete */ - if(ss_off[ss_i] >= sis_off[sis_i]) - int_sel_off = ss_sel_off; - else - int_sel_off = sis_off[sis_i] - ss_off[ss_i] + ss_sel_off; - if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) <= (sis_off[sis_i] - + (hsize_t)sis_len[sis_i])) { - int_len = (size_t)((hsize_t)ss_len[ss_i] + ss_sel_off - int_sel_off); - advance_ss = TRUE; - } /* end if */ - else - int_len = (size_t)(sis_off[sis_i] + (hsize_t)sis_len[sis_i] - ss_off[ss_i] + ss_sel_off - int_sel_off); - if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) >= (sis_off[sis_i] - + (hsize_t)sis_len[sis_i])) - advance_sis = TRUE; - - /* Project intersection sequence to destination selection */ - while(int_len > (size_t)0) { - while(ds_sel_off + (hsize_t)ds_len[ds_i] <= int_sel_off) { - /* Intersection is not projected to this destination - * sequence, advance destination space */ - ds_sel_off += (hsize_t)ds_len[ds_i]; - if(++ds_i == ds_nseq) { - HDassert(ds_nelem > 0); - - /* Try to grab more sequences from dst_space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(ds_len[0] > 0); - - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= ds_nelem); - ds_nelem -= nelem; - - /* Reset source space index */ - ds_i = 0; - } /* end if */ - } /* end while */ + /* Set up ds_span_info */ + if(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_HYPERSLABS) { + /* Make certain the selection has a span tree */ + if(NULL == dst_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)dst_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for dsetination hyperslab selection") - /* Add sequence to projected space */ - HDassert(ds_sel_off <= int_sel_off); - proj_off = ds_off[ds_i] + int_sel_off - ds_sel_off; - proj_len = proj_len_rem = (size_t)MIN(int_len, - (size_t)(ds_sel_off + (hsize_t)ds_len[ds_i] - int_sel_off)); - - /* Add to span tree */ - while(proj_len_rem > (size_t)0) { - hsize_t high; /* High value of span */ - size_t span_len; /* Length of span */ - - /* Append spans in higher dimensions if we're going ouside - * the plane of the span currently being built (i.e. it's - * finished being built) */ - /* Check for more than one full row (in every dim) and - * append multiple spans at once? -NAF */ - for(u = proj_rank - 1; ((u > 0) - && ((proj_off / proj_down_dims[u - 1]) - != curr_span_up_dim[u - 1])); u--) { - if(curr_span_tree[u]) { - /* Append complete lower dimension span tree to - * current dimension */ - low = curr_span_up_dim[u - 1] % proj_space->extent.size[u - 1]; - if(H5S__hyper_append_span(&curr_span_tree[u - 1], (proj_rank - u) + 1, low, low, curr_span_tree[u]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + /* Simply point to existing span tree */ + ds_span_info = dst_space->select.sel_info.hslab->span_lst; + } /* end if */ + else { + /* Create temporary span tree from all selection */ + HDassert(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_ALL); - /* Reset lower dimension's span tree and previous - * span since we just committed it and will start - * over with a new one */ - H5S__hyper_free_span_info(curr_span_tree[u]); - curr_span_tree[u] = NULL; - } /* end if */ + if(NULL == (ds_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(dst_space), + H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, dst_space->extent.size))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL destination space") + ds_span_info = ds_span_info_buf; + } /* end else */ - /* Update curr_span_up_dim */ - curr_span_up_dim[u - 1] = proj_off / proj_down_dims[u - 1]; - } /* end for */ + /* Make certain the source intersect selection has a span tree */ + if(NULL == src_intersect_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)src_intersect_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source intersect hyperslab selection") - /* Compute bounds for new span in lowest dimension */ - low = proj_off % proj_space->extent.size[proj_rank - 1]; - span_len = MIN(proj_len_rem, - (size_t)(proj_space->extent.size[proj_rank - 1] - - low)); - HDassert(proj_len_rem >= span_len); - high = (low + (hsize_t)span_len) - (hsize_t)1; + /* Initialize udata */ + HDmemset(&udata, 0, sizeof(udata)); + udata.ds_span[0] = ds_span_info->head; + udata.ds_low[0] = udata.ds_span[0]->low; + udata.ss_rank = H5S_GET_EXTENT_NDIMS(src_space); + udata.ds_rank = H5S_GET_EXTENT_NDIMS(dst_space); + udata.op_gen = H5S__hyper_get_op_gen(); - /* Append span in lowest dimension */ - if(H5S__hyper_append_span(&curr_span_tree[proj_rank - 1], 1, low, high, NULL) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + /* Iterate over selections and build projected span tree */ + if(H5S__hyper_proj_int_iterate(ss_span_info, src_intersect_space->select.sel_info.hslab->span_lst, 1, 0, &udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "selection iteration failed") - /* Update remaining offset and length */ - proj_off += (hsize_t)span_len; - proj_len_rem -= span_len; - } /* end while */ + /* Remove current selection from proj_space */ + if(H5S_SELECT_RELEASE(proj_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - /* Update intersection sequence */ - int_sel_off += (hsize_t)proj_len; - int_len -= proj_len; - } /* end while */ - } /* end else */ - } /* end while */ + /* Check for elements in projected space */ + if(udata.ps_span_info[0]) { + /* Allocate space for the hyperslab selection information (note this sets + * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */ + if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info") -loop_end: - /* Add remaining spans to span tree */ - for(u = proj_rank - 1; u > 0; u--) - if(curr_span_tree[u]) { - /* Append remaining span tree to higher dimension */ - low = curr_span_up_dim[u - 1] % proj_space->extent.size[u - 1]; - if(H5S__hyper_append_span(&curr_span_tree[u - 1], (proj_rank - u) + 1, low, low, curr_span_tree[u]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + /* Set selection type */ + proj_space->select.type = H5S_sel_hyper; - /* Reset span tree */ - H5S__hyper_free_span_info(curr_span_tree[u]); - curr_span_tree[u] = NULL; - } /* end if */ + /* Set unlim_dim */ + proj_space->select.sel_info.hslab->unlim_dim = -1; - /* Add span tree to proj_space */ - if(curr_span_tree[0]) { - proj_space->select.sel_info.hslab->span_lst = curr_span_tree[0]; - curr_span_tree[0] = NULL; + /* Set span tree */ + proj_space->select.sel_info.hslab->span_lst = udata.ps_span_info[0]; + udata.ps_span_info[0] = NULL; /* Set the number of elements in current selection */ proj_space->select.num_elem = H5S__hyper_spans_nelem(proj_space->select.sel_info.hslab->span_lst); @@ -10810,36 +11495,40 @@ loop_end: HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") done: - /* Release source selection iterator */ - if(ss_iter_init && H5S_SELECT_ITER_RELEASE(ss_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(ss_iter) - ss_iter = H5FL_FREE(H5S_sel_iter_t, ss_iter); - - /* Release destination selection iterator */ - if(ds_iter_init && H5S_SELECT_ITER_RELEASE(ds_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(ds_iter) - ds_iter = H5FL_FREE(H5S_sel_iter_t, ds_iter); - - /* Release source intersect selection iterator */ - if(sis_iter_init && H5S_SELECT_ITER_RELEASE(sis_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(sis_iter) - sis_iter = H5FL_FREE(H5S_sel_iter_t, sis_iter); + /* Free ss_span_info_buf */ + if(ss_span_info_buf) { + H5S__hyper_free_span_info(ss_span_info_buf); + ss_span_info_buf = NULL; + } /* end if */ + + /* Free ds_span_info_buf */ + if(ds_span_info_buf) { + H5S__hyper_free_span_info(ds_span_info_buf); + ds_span_info_buf = NULL; + } /* end if */ /* Cleanup on error */ if(ret_value < 0) { - /* Remove current selection from proj_space */ - if(H5S_SELECT_RELEASE(proj_space) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") + unsigned u; /* Free span trees */ - for(u = 0; u < proj_rank; u++) - if(curr_span_tree[u]) - H5S__hyper_free_span_info(curr_span_tree[u]); + for(u = 0; u < udata.ds_rank; u++) + if(udata.ps_span_info[u]) { + H5S__hyper_free_span_info(udata.ps_span_info[u]); + udata.ps_span_info[u] = NULL; + } /* end if */ } /* end if */ +#ifndef NDEBUG + /* Verify there are no more span trees */ + { + unsigned u; + + for(u = 0; u < H5S_MAX_RANK; u++) + HDassert(!udata.ps_span_info[u]); + } /* end block */ +#endif /* NDEBUG */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S__hyper_project_intersection() */ @@ -10923,11 +11612,11 @@ H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count, herr_t H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size) { - H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */ - hsize_t orig_count; /* Original count in unlimited dimension */ - int orig_unlim_dim; /* Original unliminted dimension */ - H5S_hyper_dim_t *diminfo; /* Convenience pointer to diminfo.opt in unlimited dimension */ - herr_t ret_value = SUCCEED; /* Return value */ + H5S_hyper_sel_t *hslab = NULL; /* Convenience pointer to hyperslab info */ + hsize_t orig_count; /* Original count in unlimited dimension */ + int orig_unlim_dim; /* Original unliminted dimension */ + H5S_hyper_dim_t *diminfo = NULL; /* Convenience pointer to diminfo.opt in unlimited dimension */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -10958,6 +11647,10 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size) /* Convert to "none" selection */ if(H5S_select_none(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") + + /* Reset the convenience pointers */ + hslab = NULL; + diminfo = NULL; } /* end if */ /* Check for single block in unlimited dimension */ else if(orig_count == (hsize_t)1) { @@ -11010,7 +11703,7 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size) } /* end else */ /* Update the upper bound, if the diminfo is valid */ - if(H5S_DIMINFO_VALID_YES == hslab->diminfo_valid) + if(hslab && (H5S_DIMINFO_VALID_YES == hslab->diminfo_valid)) hslab->diminfo.high_bounds[orig_unlim_dim] = hslab->diminfo.opt[orig_unlim_dim].start + hslab->diminfo.opt[orig_unlim_dim].stride * (hslab->diminfo.opt[orig_unlim_dim].count - 1) + diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 93114bd..4752c59 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -70,6 +70,9 @@ /* Length of stack-allocated sequences for "project intersect" routines */ #define H5S_PROJECT_INTERSECT_NSEQS 256 +/* Internal flags for initializing selection iterators */ +#define H5S_SEL_ITER_API_CALL 0x1000 /* Selection iterator created from API call */ + /* Initial version of the dataspace information */ #define H5O_SDSPACE_VERSION_1 1 diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 445566a..875c018 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -180,14 +180,32 @@ H5FL_DEFINE_STATIC(H5S_pnt_list_t); static herr_t H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) { - FUNC_ENTER_STATIC_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC /* Check args */ HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space)); HDassert(iter); - /* Share point list for internal iterations */ - iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst; + /* If this iterator is created from an API call, by default we clone the + * selection now, as the dataspace could be modified or go out of scope. + * + * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given, + * the selection is shared between the selection iterator and the + * dataspace. In this case, the application _must_not_ modify or + * close the dataspace that the iterator is operating on, or undefined + * behavior will occur. + */ + if((iter->flags & H5S_SEL_ITER_API_CALL) && + !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) { + /* Copy the point list */ + if(NULL == (iter->u.pnt.pnt_lst = H5S__copy_pnt_list(space->select.sel_info.pnt_lst, space->extent.rank))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list") + } /* end if */ + else + /* OK to share point list for internal iterations */ + iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst; /* Start at the head of the list of points */ iter->u.pnt.curr = iter->u.pnt.pnt_lst->head; @@ -195,7 +213,8 @@ H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) /* Initialize type of selection iterator */ iter->type = H5S_sel_iter_point; - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S__point_iter_init() */ @@ -537,13 +556,18 @@ H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S__point_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED * iter) +H5S__point_iter_release(H5S_sel_iter_t * iter) { FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); + /* If this iterator copied the point list, we must free it */ + if((iter->flags & H5S_SEL_ITER_API_CALL) && + !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) + H5S__free_pnt_list(iter->u.pnt.pnt_lst); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S__point_iter_release() */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 84e577b..23e6846 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -44,6 +44,18 @@ * earlier offset than the previous * one. */ +#define H5S_SEL_ITER_SHARE_WITH_DATASPACE 0x0002 /* Don't copy the dataspace + * selection when creating the + * selection iterator. + * + * This can improve performance + * of creating the iterator, but + * the dataspace _MUST_NOT_ be + * modified or closed until the + * selection iterator is closed + * or the iterator's behavior + * will be undefined. + */ /* Different types of dataspaces */ typedef enum H5S_class_t { @@ -144,6 +156,11 @@ H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], const hsize_t _stride[], const hsize_t count[], const hsize_t _block[]); +H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, + const hsize_t start[], const hsize_t _stride[], const hsize_t count[], + const hsize_t _block[]); +H5_DLL herr_t H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id); +H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id); H5_DLL htri_t H5Sis_regular_hyperslab(hid_t spaceid); H5_DLL htri_t H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[], hsize_t count[], hsize_t block[]); @@ -151,6 +168,12 @@ H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid); H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t buf[/*numblocks*/]); +/* Operations on dataspace selection iterators */ +H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags); +H5_DLL herr_t H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, + size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); +H5_DLL herr_t H5Ssel_iter_close(hid_t sel_iter_id); + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 80b5ea1..c383fed 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -40,6 +40,9 @@ /* Local Macros */ /****************/ +/* All the valid public flags to H5Ssel_iter_create() */ +#define H5S_SEL_ITER_ALL_PUBLIC_FLAGS (H5S_SEL_ITER_GET_SEQ_LIST_SORTED | \ + H5S_SEL_ITER_SHARE_WITH_DATASPACE) /******************/ @@ -1392,7 +1395,7 @@ done: PURPOSE Release a selection iterator's resources. USAGE - hssize_t H5S_select_iter_release(sel_iter) + herr_t H5S_select_iter_release(sel_iter) H5S_sel_iter_t *sel_iter; IN: Selection iterator to query RETURNS The number of elements in selection on success, 0 on failure @@ -2374,10 +2377,11 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, if(H5S_select_copy(new_space, dst_space, FALSE) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection") } /* end if */ - /* If any of the spaces are "none", the projection must also be "none" */ - else if((src_intersect_space->select.type->type == H5S_SEL_NONE) - || (src_space->select.type->type == H5S_SEL_NONE) - || (dst_space->select.type->type == H5S_SEL_NONE)) { + /* If any of the selections contain no elements, the projection must be + * "none" */ + else if((H5S_GET_SELECT_NPOINTS(src_intersect_space) == 0) + || (H5S_GET_SELECT_NPOINTS(src_space) == 0) + || (H5S_GET_SELECT_NPOINTS(dst_space) == 0)) { /* Change to "none" selection */ if(H5S_select_none(new_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") @@ -2389,6 +2393,8 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") else { HDassert(src_intersect_space->select.type->type == H5S_SEL_HYPERSLABS); + HDassert(src_space->select.type->type != H5S_SEL_NONE); + HDassert(dst_space->select.type->type != H5S_SEL_NONE); /* Intersecting space is hyperslab selection. Call the hyperslab * routine to project to another hyperslab selection. */ @@ -2497,3 +2503,217 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_select_subtract() */ + +/*-------------------------------------------------------------------------- + NAME + H5Ssel_iter_create + PURPOSE + Create a dataspace selection iterator for a dataspace's selection + USAGE + hid_t H5Ssel_iter_create(space) + hid_t space; IN: ID of the dataspace with selection to iterate over + RETURNS + Valid dataspace selection iterator ID on success, H5I_INVALID_HID on failure + DESCRIPTION + Creates a selection iterator and initializes it to start at the first + element selected in the dataspace. + PROGRAMMER + Quincey Koziol - February 11, 2019 + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t +H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags) +{ + H5S_t *space; /* Dataspace with selection to iterate over */ + H5S_sel_iter_t *sel_iter; /* Selection iterator created */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + H5TRACE3("i", "izIu", space_id, elmt_size, flags); + + /* Check args */ + if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace") + if(elmt_size == 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "element size must be greater than 0") + if(flags != (flags & H5S_SEL_ITER_ALL_PUBLIC_FLAGS)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "invalid selection iterator flag") + + /* Allocate the iterator */ + if(NULL == (sel_iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate selection iterator") + + /* Add flag to indicate that this iterator is from an API call */ + flags |= H5S_SEL_ITER_API_CALL; + + /* Initialize the selection iterator */ + if(H5S_select_iter_init(sel_iter, space, elmt_size, flags) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to initialize selection iterator") + + /* Atomize */ + if((ret_value = H5I_register(H5I_SPACE_SEL_ITER, sel_iter, TRUE)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace selection iterator atom") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ssel_iter_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Ssel_iter_get_seq_list + PURPOSE + Retrieve a list of offset / length sequences for the elements in an iterator + USAGE + herr_t H5Ssel_iter_get_seq_list(sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len) + hid_t sel_iter_id; IN: ID of the dataspace selection iterator to retrieve sequence from + size_t maxseq; IN: Max. # of sequences to retrieve + size_t maxbytes; IN: Max. # of bytes to retrieve in sequences + size_t *nseq; OUT: # of sequences retrieved + size_t *nbytes; OUT: # of bytes retrieved, in all sequences + hsize_t *off; OUT: Array of sequence offsets + size_t *len; OUT: Array of sequence lengths + RETURNS + Non-negative on success / Negative on failure + DESCRIPTION + Retrieve a list of offset / length pairs (a list of "sequences") matching + the selected elements for an iterator, according to the iteration order for + the iterator. The lengths returned are in _bytes_, not elements. + + Note that the iteration order for "all" and "hyperslab" selections is + row-major (i.e. "C-ordered"), but the iteration order for "point" + selections is "in order selected", unless the H5S_SEL_ITER_GET_SEQ_LIST_SORTED + flag is passed to H5Sset_iter_create for a point selection. + + MAXSEQ and MAXBYTES specify the most sequences or bytes possible to + place into the OFF and LEN arrays. *NSEQ and *NBYTES return the actual + number of sequences and bytes put into the arrays. + + Each call to H5Ssel_iter_get_seq_list() will retrieve the next set + of sequences for the selection being iterated over. + + The total number of bytes possible to retrieve from a selection iterator + is the 'elmt_size' passed to H5Ssel_iter_create multiplied by the number + of elements selected in the dataspace the iterator was created from + (which can be retrieved with H5Sget_select_npoints). When there are no + further sequences of elements to retrieve, calls to this routine will + set *NSEQ and *NBYTES to zero. + PROGRAMMER + Quincey Koziol - February 11, 2019 + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes, + size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len) +{ + H5S_sel_iter_t *sel_iter; /* Dataspace selection iterator to operate on */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "izz*z*z*h*z", sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, + len); + + /* Check args */ + if(NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator") + if(NULL == nseq) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nseq' pointer is NULL") + if(NULL == nbytes) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nbytes' pointer is NULL") + if(NULL == off) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "offset array pointer is NULL") + if(NULL == len) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "length array pointer is NULL") + + /* Get the sequences of bytes */ + if(maxseq > 0 && maxbytes > 0) { + if(H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxbytes, nseq, nbytes, off, len) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed") + } /* end if */ + else + *nseq = *nbytes = 0; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ssel_iter_get_seq_list() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_sel_iter_close + * + * Purpose: Releases a dataspace selection iterator and its memory. + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Monday, February 11, 2019 + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_sel_iter_close(H5S_sel_iter_t *sel_iter) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(sel_iter); + + /* Call selection type-specific release routine */ + if(H5S_SELECT_ITER_RELEASE(sel_iter) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "problem releasing a selection iterator's type-specific info") + + /* Release the structure */ + sel_iter = H5FL_FREE(H5S_sel_iter_t, sel_iter); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_sel_iter_close() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Ssel_iter_close + PURPOSE + Close a dataspace selection iterator + USAGE + herr_t H5Ssel_iter_close(sel_iter_id) + hid_t sel_iter_id; IN: ID of the dataspace selection iterator to close + RETURNS + Non-negative on success / Negative on failure + DESCRIPTION + Close a dataspace selection iterator, releasing its state. + PROGRAMMER + Quincey Koziol - February 11, 2019 + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Ssel_iter_close(hid_t sel_iter_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", sel_iter_id); + + /* Check args */ + if(NULL == H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator") + + /* When the reference count reaches zero the resources are freed */ + if(H5I_dec_app_ref(sel_iter_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing dataspace selection iterator ID") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ssel_iter_close() */ + @@ -31,8 +31,11 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ +#include "H5Pprivate.h" /* Property lists */ #include "H5VLpkg.h" /* Virtual Object Layer */ +/* VOL connectors */ +#include "H5VLnative.h" /* Native VOL connector */ /****************/ /* Local Macros */ @@ -71,6 +74,9 @@ * Purpose: Registers a new VOL connector as a member of the virtual object * layer class. * + * VIPL_ID is a VOL initialization property list which must be + * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT). + * * Return: Success: A VOL connector ID which is good until the * library is closed or the connector is * unregistered. @@ -99,6 +105,13 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id) if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector must provide free callback for object wrapping contexts when a get callback is provided") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector(cls, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") @@ -114,6 +127,9 @@ done: * Purpose: Registers a new VOL connector as a member of the virtual object * layer class. * + * VIPL_ID is a VOL initialization property list which must be + * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT). + * * Return: Success: A VOL connector ID which is good until the * library is closed or the connector is * unregistered. @@ -136,6 +152,13 @@ H5VLregister_connector_by_name(const char *name, hid_t vipl_id) if (0 == HDstrlen(name)) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "zero-length VOL connector name is disallowed") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector_by_name(name, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") @@ -151,6 +174,9 @@ done: * Purpose: Registers a new VOL connector as a member of the virtual object * layer class. * + * VIPL_ID is a VOL initialization property list which must be + * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT). + * * Return: Success: A VOL connector ID which is good until the * library is closed or the connector is * unregistered. @@ -171,6 +197,13 @@ H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id) if(value < 0) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "negative VOL connector value is disallowed") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector_by_value(value, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") @@ -185,9 +218,9 @@ done: * * Purpose: Tests whether a VOL class has been registered or not * - * Return: >0 if the VOL class has been registered - * 0 if it is unregistered - * <0 on error (if the class is not a valid class ID) + * Return: >0 if a VOL connector with that name has been registered + * 0 if a VOL connector with that name has NOT been registered + * <0 on errors * * Programmer: Dana Robinson * June 17, 2017 @@ -216,8 +249,12 @@ done: * * Purpose: Retrieves the ID for a registered VOL connector. * - * Return: Positive if the VOL class has been registered - * Negative on error (if the class is not a valid class or not registered) + * Return: A valid VOL connector ID if a connector by that name has + * been registered. This ID will need to be closed using + * H5VLclose(). + * + * H5I_INVALID_HID on error or if a VOL connector of that + * name has not been registered. * * Programmer: Dana Robinson * June 17, 2017 @@ -245,7 +282,12 @@ done: * Function: H5VLget_connector_name * * Purpose: Returns the connector name for the VOL associated with the - * object or file ID + * object or file ID. + * + * This works like other calls where the caller must provide a + * buffer of the appropriate size for the library to fill in. + * i.e., passing in a NULL pointer for NAME will return the + * required size of the buffer. * * Return: Success: The length of the connector name * @@ -312,6 +354,9 @@ done: * this VOL connector or files which are already opened under with * this connector. * + * The native VOL connector cannot be unregistered and attempts + * to do so are considered an error. + * * Return: Success: Non-negative * * Failure: Negative @@ -321,6 +366,7 @@ done: herr_t H5VLunregister_connector(hid_t vol_id) { + hid_t native_id = H5I_INVALID_HID; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -328,13 +374,23 @@ H5VLunregister_connector(hid_t vol_id) /* Check arguments */ if(NULL == H5I_object_verify(vol_id, H5I_VOL)) - HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector") + HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID") + + /* For the time being, we disallow unregistering the native VOL connector */ + if(H5I_INVALID_HID == (native_id = H5VL__get_connector_id(H5VL_NATIVE_NAME, FALSE))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to find the native VOL connector ID") + if(vol_id == native_id) + HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "unregistering the native VOL connector is not allowed") /* The H5VL_class_t struct will be freed by this function */ - if (H5I_dec_app_ref(vol_id) < 0) + if(H5I_dec_app_ref(vol_id) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector") done: + if(native_id != H5I_INVALID_HID) + if(H5I_dec_ref(native_id) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement count on native_id") + FUNC_LEAVE_API(ret_value) } /* end H5VLunregister_connector() */ @@ -344,8 +400,8 @@ done: * * Purpose: Compares two connector classes (based on their value field) * - * Note: This routine is _only_ for HDF5 VOL connector authors! It is - * _not_ part of the public API for HDF5 application developers. + * Note: This routine is _only_ for HDF5 VOL connector authors! It is + * _not_ part of the public API for HDF5 application developers. * * Return: Success: Non-negative, *cmp set to a value like strcmp * @@ -381,11 +437,11 @@ done: * Function: H5VLwrap_register * * Purpose: Wrap an internal object with a "wrap context" and register an - * hid_t for the resulting object. + * hid_t for the resulting object. * - * Note: This routine is mainly targeted toward wrapping objects for - * iteration routine callbacks (i.e. the callbacks from H5Aiterate*, - * H5Literate* / H5Lvisit*, and H5Ovisit* ). + * Note: This routine is mainly targeted toward wrapping objects for + * iteration routine callbacks (i.e. the callbacks from H5Aiterate*, + * H5Literate* / H5Lvisit*, and H5Ovisit* ). * * Return: Success: Non-negative hid_t for the object. * Failure: Negative (H5I_INVALID_HID) @@ -420,10 +476,10 @@ done: * Function: H5VLobject * * Purpose: Retrieve the object pointer associated with an hid_t for a. - * VOL object. + * VOL object. * - * Note: This routine is mainly targeted toward unwrapping objects for - * testing. + * Note: This routine is mainly targeted toward unwrapping objects for + * testing. * * Return: Success: Object pointer * Failure: NULL @@ -451,16 +507,16 @@ done: * Function: H5VLretrieve_lib_state * * Purpose: Retrieves a copy of the internal state of the HDF5 library, - * so that it can be restored later. + * so that it can be restored later. * - * Note: This routine is _only_ for HDF5 VOL connector authors! It is - * _not_ part of the public API for HDF5 application developers. + * Note: This routine is _only_ for HDF5 VOL connector authors! It is + * _not_ part of the public API for HDF5 application developers. * * Return: Success: Non-negative, *state set * Failure: Negative, *state unset * - * Programmer: Quincey Koziol - * Thursday, January 10, 2019 + * Programmer: Quincey Koziol + * Thursday, January 10, 2019 * *--------------------------------------------------------------------------- */ @@ -491,14 +547,14 @@ done: * * Purpose: Restores the internal state of the HDF5 library. * - * Note: This routine is _only_ for HDF5 VOL connector authors! It is - * _not_ part of the public API for HDF5 application developers. + * Note: This routine is _only_ for HDF5 VOL connector authors! It is + * _not_ part of the public API for HDF5 application developers. * * Return: Success: Non-negative * Failure: Negative * - * Programmer: Quincey Koziol - * Thursday, January 10, 2019 + * Programmer: Quincey Koziol + * Thursday, January 10, 2019 * *--------------------------------------------------------------------------- */ @@ -528,20 +584,20 @@ done: * Function: H5VLreset_lib_state * * Purpose: Resets the internal state of the HDF5 library, undoing the - * affects of H5VLrestore_lib_state. + * affects of H5VLrestore_lib_state. * - * Note: This routine is _only_ for HDF5 VOL connector authors! It is - * _not_ part of the public API for HDF5 application developers. + * Note: This routine is _only_ for HDF5 VOL connector authors! It is + * _not_ part of the public API for HDF5 application developers. * - * Note: This routine must be called as a "pair" with - * H5VLrestore_lib_state. It can be called before / after / - * independently of H5VLfree_lib_state. + * Note: This routine must be called as a "pair" with + * H5VLrestore_lib_state. It can be called before / after / + * independently of H5VLfree_lib_state. * * Return: Success: Non-negative * Failure: Negative * - * Programmer: Quincey Koziol - * Saturday, February 23, 2019 + * Programmer: Quincey Koziol + * Saturday, February 23, 2019 * *--------------------------------------------------------------------------- */ @@ -568,17 +624,17 @@ done: * * Purpose: Free a retrieved library state. * - * Note: This routine is _only_ for HDF5 VOL connector authors! It is - * _not_ part of the public API for HDF5 application developers. + * Note: This routine is _only_ for HDF5 VOL connector authors! It is + * _not_ part of the public API for HDF5 application developers. * - * Note: This routine must be called as a "pair" with - * H5VLretrieve_lib_state. + * Note: This routine must be called as a "pair" with + * H5VLretrieve_lib_state. * * Return: Success: Non-negative * Failure: Negative * - * Programmer: Quincey Koziol - * Thursday, January 10, 2019 + * Programmer: Quincey Koziol + * Thursday, January 10, 2019 * *--------------------------------------------------------------------------- */ diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index 2d1274c..696ccab 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -3041,7 +3041,7 @@ H5VL_file_specific(const H5VL_object_t *vol_obj, H5VL_file_specific_t specific_t arg_started = TRUE; /* Special treatment of file access check */ - if(specific_type == H5VL_FILE_IS_ACCESSIBLE) { + if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) { H5P_genplist_t *plist; /* Property list pointer */ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ va_list tmp_args; /* argument list passed from the API call */ diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h new file mode 100644 index 0000000..9de518f --- /dev/null +++ b/src/H5VLconnector.h @@ -0,0 +1,417 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains public declarations for authoring VOL connectors. + */ + +#ifndef _H5VLconnector_H +#define _H5VLconnector_H + +/* Public headers needed by this file */ +#include "H5public.h" /* Generic Functions */ +#include "H5Apublic.h" /* Attributes */ +#include "H5ESpublic.h" /* Event Stack */ +#include "H5Fpublic.h" /* Files */ +#include "H5Ipublic.h" /* IDs */ +#include "H5Lpublic.h" /* Links */ +#include "H5Opublic.h" /* Objects */ +#include "H5Rpublic.h" /* References */ +#include "H5VLpublic.h" /* Virtual Object Layer */ + + +/*****************/ +/* Public Macros */ +/*****************/ + +/* Capability flags for connector */ +#define H5VL_CAP_FLAG_NONE 0 /* No special connector capabilities */ +#define H5VL_CAP_FLAG_THREADSAFE 0x01 /* Connector is threadsafe */ + + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/* types for attribute GET callback */ +typedef enum H5VL_attr_get_t { + H5VL_ATTR_GET_ACPL, /* creation property list */ + H5VL_ATTR_GET_INFO, /* info */ + H5VL_ATTR_GET_NAME, /* access property list */ + H5VL_ATTR_GET_SPACE, /* dataspace */ + H5VL_ATTR_GET_STORAGE_SIZE, /* storage size */ + H5VL_ATTR_GET_TYPE /* datatype */ +} H5VL_attr_get_t; + +/* types for attribute SPECFIC callback */ +typedef enum H5VL_attr_specific_t { + H5VL_ATTR_DELETE, /* H5Adelete(_by_name/idx) */ + H5VL_ATTR_EXISTS, /* H5Aexists(_by_name) */ + H5VL_ATTR_ITER, /* H5Aiterate(_by_name) */ + H5VL_ATTR_RENAME /* H5Arename(_by_name) */ +} H5VL_attr_specific_t; + +/* types for dataset GET callback */ +typedef enum H5VL_dataset_get_t { + H5VL_DATASET_GET_DAPL, /* access property list */ + H5VL_DATASET_GET_DCPL, /* creation property list */ + H5VL_DATASET_GET_OFFSET, /* offset */ + H5VL_DATASET_GET_SPACE, /* dataspace */ + H5VL_DATASET_GET_SPACE_STATUS, /* space status */ + H5VL_DATASET_GET_STORAGE_SIZE, /* storage size */ + H5VL_DATASET_GET_TYPE /* datatype */ +} H5VL_dataset_get_t; + +/* types for dataset SPECFIC callback */ +typedef enum H5VL_dataset_specific_t { + H5VL_DATASET_SET_EXTENT, /* H5Dset_extent */ + H5VL_DATASET_FLUSH, /* H5Dflush */ + H5VL_DATASET_REFRESH /* H5Drefresh */ +} H5VL_dataset_specific_t; + +/* types for datatype GET callback */ +typedef enum H5VL_datatype_get_t { + H5VL_DATATYPE_GET_BINARY, /* get serialized form of transient type */ + H5VL_DATATYPE_GET_TCPL /* datatype creation property list */ +} H5VL_datatype_get_t; + +/* types for datatype SPECFIC callback */ +typedef enum H5VL_datatype_specific_t { + H5VL_DATATYPE_FLUSH, + H5VL_DATATYPE_REFRESH +} H5VL_datatype_specific_t; + +/* types for file GET callback */ +typedef enum H5VL_file_get_t { + H5VL_FILE_GET_FAPL, /* file access property list */ + H5VL_FILE_GET_FCPL, /* file creation property list */ + H5VL_FILE_GET_INTENT, /* file intent */ + H5VL_FILE_GET_FILENO, /* file number */ + H5VL_FILE_GET_NAME, /* file name */ + H5VL_FILE_GET_OBJ_COUNT, /* object count in file */ + H5VL_FILE_GET_OBJ_IDS /* object ids in file */ +} H5VL_file_get_t; + +/* types for file SPECIFIC callback */ +typedef enum H5VL_file_specific_t { + H5VL_FILE_FLUSH, /* Flush file */ + H5VL_FILE_REOPEN, /* Reopen the file */ + H5VL_FILE_MOUNT, /* Mount a file */ + H5VL_FILE_UNMOUNT, /* Unmount a file */ + H5VL_FILE_IS_ACCESSIBLE, /* Check if a file is accessible */ + H5VL_FILE_DELETE /* Delete a file */ +} H5VL_file_specific_t; + +/* types for group GET callback */ +typedef enum H5VL_group_get_t { + H5VL_GROUP_GET_GCPL, /* group creation property list */ + H5VL_GROUP_GET_INFO /* group info */ +} H5VL_group_get_t; + +/* types for group SPECFIC callback */ +typedef enum H5VL_group_specific_t { + H5VL_GROUP_FLUSH, + H5VL_GROUP_REFRESH +} H5VL_group_specific_t; + +/* link create types for VOL */ +typedef enum H5VL_link_create_type_t { + H5VL_LINK_CREATE_HARD, + H5VL_LINK_CREATE_SOFT, + H5VL_LINK_CREATE_UD +} H5VL_link_create_type_t; + +/* types for link GET callback */ +typedef enum H5VL_link_get_t { + H5VL_LINK_GET_INFO, /* link info */ + H5VL_LINK_GET_NAME, /* link name */ + H5VL_LINK_GET_VAL /* link value */ +} H5VL_link_get_t; + +/* types for link SPECIFIC callback */ +typedef enum H5VL_link_specific_t { + H5VL_LINK_DELETE, /* H5Ldelete(_by_idx) */ + H5VL_LINK_EXISTS, /* link existence */ + H5VL_LINK_ITER /* H5Literate/visit(_by_name) */ +} H5VL_link_specific_t; + +/* types for object GET callback */ +typedef enum H5VL_object_get_t { + H5VL_REF_GET_NAME, /* object name, for reference */ + H5VL_REF_GET_REGION, /* dataspace of region */ + H5VL_REF_GET_TYPE, /* type of object */ + H5VL_OBJECT_GET_NAME /* object name */ +} H5VL_object_get_t; + +/* types for object SPECIFIC callback */ +typedef enum H5VL_object_specific_t { + H5VL_OBJECT_CHANGE_REF_COUNT, /* H5Oincr/decr_refcount */ + H5VL_OBJECT_EXISTS, /* H5Oexists_by_name */ + H5VL_OBJECT_VISIT, /* H5Ovisit(_by_name) */ + H5VL_REF_CREATE, /* H5Rcreate */ + H5VL_OBJECT_FLUSH, /* H5{D|G|O|T}flush */ + H5VL_OBJECT_REFRESH /* H5{D|G|O|T}refresh */ +} H5VL_object_specific_t; + +/* types for async request SPECIFIC callback */ +typedef enum H5VL_request_specific_t { + H5VL_REQUEST_WAITANY, /* Wait until any request completes */ + H5VL_REQUEST_WAITSOME, /* Wait until at least one requesst completes */ + H5VL_REQUEST_WAITALL /* Wait until all requests complete */ +} H5VL_request_specific_t; + +/* types for different ways that objects are located in an HDF5 container */ +typedef enum H5VL_loc_type_t { + H5VL_OBJECT_BY_SELF, + H5VL_OBJECT_BY_NAME, + H5VL_OBJECT_BY_IDX, + H5VL_OBJECT_BY_ADDR, + H5VL_OBJECT_BY_REF +} H5VL_loc_type_t; + +struct H5VL_loc_by_name { + const char *name; + hid_t lapl_id; +}; + +struct H5VL_loc_by_idx { + const char *name; + H5_index_t idx_type; + H5_iter_order_t order; + hsize_t n; + hid_t lapl_id; +}; + +struct H5VL_loc_by_addr { + haddr_t addr; +}; + +struct H5VL_loc_by_ref { + H5R_type_t ref_type; + const void *_ref; + hid_t lapl_id; +}; + +/* Structure to hold parameters for object locations. + * either: BY_ADDR, BY_ID, BY_NAME, BY_IDX, BY_REF + * + * Note: Leave loc_by_addr as the first union member so we + * can perform the simplest initialization of the struct + * without raising warnings. + */ +typedef struct H5VL_loc_params_t { + H5I_type_t obj_type; + H5VL_loc_type_t type; + union{ + struct H5VL_loc_by_addr loc_by_addr; + struct H5VL_loc_by_name loc_by_name; + struct H5VL_loc_by_idx loc_by_idx; + struct H5VL_loc_by_ref loc_by_ref; + } loc_data; +} H5VL_loc_params_t; + +/* VOL connector info fields & callbacks */ +typedef struct H5VL_info_class_t { + size_t size; /* Size of the VOL info */ + void * (*copy)(const void *info); /* Callback to create a copy of the VOL info */ + herr_t (*cmp)(int *cmp_value, const void *info1, const void *info2); /* Callback to compare VOL info */ + herr_t (*free)(void *info); /* Callback to release a VOL info */ + herr_t (*to_str)(const void *info, char **str); /* Callback to serialize connector's info into a string */ + herr_t (*from_str)(const char *str, void **info); /* Callback to deserialize a string into connector's info */ +} H5VL_info_class_t; + +/* VOL object wrap / retrieval callbacks */ +/* (These only need to be implemented by "pass through" VOL connectors) */ +typedef struct H5VL_wrap_class_t { + void * (*get_object)(const void *obj); /* Callback to retrieve underlying object */ + herr_t (*get_wrap_ctx)(const void *obj, void **wrap_ctx); /* Callback to retrieve the object wrapping context for the connector */ + void * (*wrap_object)(void *obj, H5I_type_t obj_type, void *wrap_ctx); /* Callback to wrap a library object */ + void * (*unwrap_object)(void *obj); /* Callback to unwrap a library object */ + herr_t (*free_wrap_ctx)(void *wrap_ctx); /* Callback to release the object wrapping context for the connector */ +} H5VL_wrap_class_t; + +/* H5A routines */ +typedef struct H5VL_attr_class_t { + void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + hid_t dxpl_id, void **req); + void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, + hid_t aapl_id, hid_t dxpl_id, void **req); + herr_t (*read)(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req); + herr_t (*write)(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req); + herr_t (*get)(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*close) (void *attr, hid_t dxpl_id, void **req); +} H5VL_attr_class_t; + +/* H5D routines */ +typedef struct H5VL_dataset_class_t { + void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, + hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, + hid_t dapl_id, hid_t dxpl_id, void **req); + void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, + hid_t dapl_id, hid_t dxpl_id, void **req); + herr_t (*read)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, + hid_t xfer_plist_id, void * buf, void **req); + herr_t (*write)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, + hid_t xfer_plist_id, const void * buf, void **req); + herr_t (*get)(void *obj, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, H5VL_dataset_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*close) (void *dset, hid_t dxpl_id, void **req); +} H5VL_dataset_class_t; + +/* H5T routines*/ +typedef struct H5VL_datatype_class_t { + void *(*commit)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, + hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); + void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char * name, + hid_t tapl_id, hid_t dxpl_id, void **req); + herr_t (*get) (void *obj, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, H5VL_datatype_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*close) (void *dt, hid_t dxpl_id, void **req); +} H5VL_datatype_class_t; + +/* H5F routines */ +typedef struct H5VL_file_class_t { + void *(*create)(const char *name, unsigned flags, hid_t fcpl_id, + hid_t fapl_id, hid_t dxpl_id, void **req); + void *(*open)(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); + herr_t (*get)(void *obj, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, H5VL_file_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*close) (void *file, hid_t dxpl_id, void **req); +} H5VL_file_class_t; + +/* H5G routines */ +typedef struct H5VL_group_class_t { + void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, + hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); + void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, + hid_t gapl_id, hid_t dxpl_id, void **req); + herr_t (*get)(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, H5VL_group_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); + herr_t (*close) (void *grp, hid_t dxpl_id, void **req); +} H5VL_group_class_t; + +/* H5L routines */ +typedef struct H5VL_link_class_t { + herr_t (*create)(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, + hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list argumenmts); + herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, + hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req); + herr_t (*move)(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, + hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req); + herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); +} H5VL_link_class_t; + +/* H5O routines */ +typedef struct H5VL_object_class_t { + void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type, + hid_t dxpl_id, void **req); + herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name, + void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name, + hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); + herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, + hid_t dxpl_id, void **req, va_list arguments); + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); +} H5VL_object_class_t; + +/* Asynchronous request 'notify' callback */ +typedef herr_t (*H5VL_request_notify_t)(void *ctx, H5ES_status_t status); + +/* Async request operation routines */ +typedef struct H5VL_request_class_t { + herr_t (*wait)(void *req, uint64_t timeout, H5ES_status_t *status); + herr_t (*notify)(void *req, H5VL_request_notify_t cb, void *ctx); + herr_t (*cancel)(void *req); + herr_t (*specific)(void *req, H5VL_request_specific_t specific_type, va_list arguments); + herr_t (*optional)(void *req, va_list arguments); + herr_t (*free)(void *req); +} H5VL_request_class_t; + +/* + * VOL connector identifiers. Values 0 through 255 are for connectors defined + * by the HDF5 library. Values 256 through 511 are available for testing new + * filters. Subsequent values should be obtained from the HDF5 development + * team at help@hdfgroup.org. + */ +typedef int H5VL_class_value_t; + +/* Class information for each VOL connector */ +typedef struct H5VL_class_t { + /* Overall connector fields & callbacks */ + unsigned int version; /* VOL connector class struct version # */ + H5VL_class_value_t value; /* Value to identify connector */ + const char *name; /* Connector name (MUST be unique!) */ + unsigned cap_flags; /* Capability flags for connector */ + herr_t (*initialize)(hid_t vipl_id); /* Connector initialization callback */ + herr_t (*terminate)(void); /* Connector termination callback */ + + /* VOL framework */ + H5VL_info_class_t info_cls; /* VOL info fields & callbacks */ + H5VL_wrap_class_t wrap_cls; /* VOL object wrap / retrieval callbacks */ + + /* Data Model */ + H5VL_attr_class_t attr_cls; /* Attribute (H5A*) class callbacks */ + H5VL_dataset_class_t dataset_cls; /* Dataset (H5D*) class callbacks */ + H5VL_datatype_class_t datatype_cls; /* Datatype (H5T*) class callbacks */ + H5VL_file_class_t file_cls; /* File (H5F*) class callbacks */ + H5VL_group_class_t group_cls; /* Group (H5G*) class callbacks */ + H5VL_link_class_t link_cls; /* Link (H5L*) class callbacks */ + H5VL_object_class_t object_cls; /* Object (H5O*) class callbacks */ + + /* Services */ + H5VL_request_class_t request_cls; /* Asynchronous request class callbacks */ + + /* Catch-all */ + herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); /* Optional callback */ +} H5VL_class_t; + + +/********************/ +/* Public Variables */ +/********************/ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper routines for VOL connector authors */ +H5_DLL void *H5VLobject(hid_t obj_id); + +#ifdef __cplusplus +} +#endif + +#endif /* _H5VLconnector_H */ + diff --git a/src/H5VLconnector_passthru.h b/src/H5VLconnector_passthru.h new file mode 100644 index 0000000..9a2bd52 --- /dev/null +++ b/src/H5VLconnector_passthru.h @@ -0,0 +1,166 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains public declarations for authoring VOL connectors + * which act as "passthrough" connectors that forward their API calls to + * an underlying connector. + * + * An example of this might be a logging connector, which creates log messages + * and then passes the call on to an underlying VOL connector. + * + * The functionality required to implement such a connector is specialized + * and non-trivial so it has been split into this header in an effort to keep + * the H5VLconnector.h header easier to understand. + */ + +#ifndef _H5VLconnector_passthru_H +#define _H5VLconnector_passthru_H + +/* Public headers needed by this file */ +#include "H5public.h" /* Generic Functions */ +#include "H5Ipublic.h" /* IDs */ +#include "H5VLpublic.h" /* Virtual Object Layer */ + +/* Semi-public headers mainly for VOL connector authors */ +#include "H5VLconnector.h" + + +/*****************/ +/* Public Macros */ +/*****************/ + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/********************/ +/* Public Variables */ +/********************/ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper routines for VOL connector authors */ +H5_DLL herr_t H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2); +H5_DLL hid_t H5VLwrap_register(void *obj, H5I_type_t type); +H5_DLL herr_t H5VLretrieve_lib_state(void **state); +H5_DLL herr_t H5VLrestore_lib_state(const void *state); +H5_DLL herr_t H5VLreset_lib_state(void); +H5_DLL herr_t H5VLfree_lib_state(void *state); + +/* Pass-through callbacks */ +H5_DLL void *H5VLget_object(void *obj, hid_t connector_id); +H5_DLL herr_t H5VLget_wrap_ctx(void *obj, hid_t connector_id, void **wrap_ctx); +H5_DLL void *H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, + void *wrap_ctx); +H5_DLL void *H5VLunwrap_object(void *obj, hid_t connector_id); +H5_DLL herr_t H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id); + +/* Public wrappers for generic callbacks */ +H5_DLL herr_t H5VLinitialize(hid_t connector_id, hid_t vipl_id); +H5_DLL herr_t H5VLterminate(hid_t connector_id); +H5_DLL herr_t H5VLget_cap_flags(hid_t connector_id, unsigned *cap_flags); +H5_DLL herr_t H5VLget_value(hid_t connector_id, H5VL_class_value_t *conn_value); + +/* Public wrappers for info fields and callbacks */ +H5_DLL herr_t H5VLcopy_connector_info(hid_t connector_id, void **dst_vol_info, void *src_vol_info); +H5_DLL herr_t H5VLcmp_connector_info(int *cmp, hid_t connector_id, const void *info1, + const void *info2); +H5_DLL herr_t H5VLfree_connector_info(hid_t connector_id, void *vol_info); +H5_DLL herr_t H5VLconnector_info_to_str(const void *info, hid_t connector_id, char **str); +H5_DLL herr_t H5VLconnector_str_to_info(const char *str, hid_t connector_id, void **info); + +/* Public wrappers for attribute callbacks */ +H5_DLL void *H5VLattr_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); +H5_DLL void *H5VLattr_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLattr_read(void *attr, hid_t connector_id, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLattr_write(void *attr, hid_t connector_id, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLattr_get(void *obj, hid_t connector_id, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLattr_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLattr_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLattr_close(void *attr, hid_t connector_id, hid_t dxpl_id, void **req); + +/* Public wrappers for dataset callbacks */ +H5_DLL void *H5VLdataset_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req); +H5_DLL void *H5VLdataset_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t dapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLdataset_read(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, void *buf, void **req); +H5_DLL herr_t H5VLdataset_write(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf, void **req); +H5_DLL herr_t H5VLdataset_get(void *dset, hid_t connector_id, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdataset_specific(void *obj, hid_t connector_id, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdataset_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdataset_close(void *dset, hid_t connector_id, hid_t dxpl_id, void **req); + +/* Public wrappers for file callbacks */ +H5_DLL void *H5VLfile_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req); +H5_DLL void *H5VLfile_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLfile_get(void *file, hid_t connector_id, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLfile_specific(void *obj, hid_t connector_id, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLfile_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLfile_close(void *file, hid_t connector_id, hid_t dxpl_id, void **req); + +/* Public wrappers for group callbacks */ +H5_DLL void *H5VLgroup_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); +H5_DLL void *H5VLgroup_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLgroup_get(void *obj, hid_t connector_id, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLgroup_specific(void *obj, hid_t connector_id, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLgroup_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLgroup_close(void *grp, hid_t connector_id, hid_t dxpl_id, void **req); + +/* Public wrappers for link callbacks */ +H5_DLL herr_t H5VLlink_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLlink_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id, + hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLlink_move(void *src_obj, const H5VL_loc_params_t *loc_params1, + void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id, + hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLlink_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLlink_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLlink_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); + +/* Public wrappers for object callbacks */ +H5_DLL void *H5VLobject_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5I_type_t *opened_type, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLobject_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name, + void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name, + hid_t connector_id, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLobject_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLobject_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLobject_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); + +/* Public wrappers for named datatype callbacks */ +H5_DLL void *H5VLdatatype_commit(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); +H5_DLL void *H5VLdatatype_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req); +H5_DLL herr_t H5VLdatatype_get(void *dt, hid_t connector_id, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdatatype_specific(void *obj, hid_t connector_id, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdatatype_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); +H5_DLL herr_t H5VLdatatype_close(void *dt, hid_t connector_id, hid_t dxpl_id, void **req); + +/* Public wrappers for asynchronous request callbacks */ +H5_DLL herr_t H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status); +H5_DLL herr_t H5VLrequest_notify(void *req, hid_t connector_id, H5VL_request_notify_t cb, void *ctx); +H5_DLL herr_t H5VLrequest_cancel(void *req, hid_t connector_id); +H5_DLL herr_t H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_specific_t specific_type, va_list arguments); +H5_DLL herr_t H5VLrequest_optional(void *req, hid_t connector_id, va_list arguments); +H5_DLL herr_t H5VLrequest_free(void *req, hid_t connector_id); + +#ifdef __cplusplus +} +#endif + +#endif /* _H5VLconnector_passthru_H */ + diff --git a/src/H5VLnative_file.c b/src/H5VLnative_file.c index 8903911..eeaade6 100644 --- a/src/H5VLnative_file.c +++ b/src/H5VLnative_file.c @@ -386,10 +386,16 @@ H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type, /* Call private routine */ if((*ret = H5F__is_hdf5(name, fapl_id)) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "error in HDF5 file check") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "error in HDF5 file check") break; } + /* H5Fdelete */ + case H5VL_FILE_DELETE: + { + HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "H5Fdelete() is currently not supported in the native VOL connector") + break; + } default: diff --git a/src/H5VLnative_object.c b/src/H5VLnative_object.c index 0b1d73a..de2a8a5 100644 --- a/src/H5VLnative_object.c +++ b/src/H5VLnative_object.c @@ -213,17 +213,32 @@ H5VL__native_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_obj break; } - /* H5Iget_name */ - case H5VL_ID_GET_NAME: + /* Object name */ + case H5VL_OBJECT_GET_NAME: { ssize_t *ret = HDva_arg(arguments, ssize_t *); char *name = HDva_arg(arguments, char *); size_t size = HDva_arg(arguments, size_t); - /* Retrieve object's name */ - if((*ret = H5G_get_name(&loc, name, size, NULL)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object name") + if(loc_params->type == H5VL_OBJECT_BY_SELF) { + /* Retrieve object's name */ + if((*ret = H5G_get_name(&loc, name, size, NULL)) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve object name") + } /* end if */ + else if(loc_params->type == H5VL_OBJECT_BY_ADDR) { + H5O_loc_t obj_oloc; /* Object location */ + + /* Initialize the object location */ + H5O_loc_reset(&obj_oloc); + obj_oloc.file = loc.oloc->file; + obj_oloc.addr = loc_params->loc_data.loc_by_addr.addr; + /* Retrieve object's name */ + if((*ret = H5G_get_name_by_addr(loc.oloc->file, &obj_oloc, name, size)) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't determine object name") + } /* end else-if */ + else + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_name parameters") break; } diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index ef92ddb..eecdac2 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -29,13 +29,17 @@ /* Header files needed */ -/* (Public HDF5 and standard C / POSIX only) */ +/* Do NOT include private HDF5 files here! */ #include <assert.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> + +/* Public HDF5 file */ #include "hdf5.h" + +/* This connector's header */ #include "H5VLpassthru.h" @@ -1733,7 +1737,7 @@ H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, /* Re-issue 'file specific' call, using the unwrapped pieces */ ret_value = H5VL_pass_through_file_specific_reissue(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, (int)loc_type, name, child_file->under_object, plist_id); } /* end if */ - else if(specific_type == H5VL_FILE_IS_ACCESSIBLE) { + else if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) { H5VL_pass_through_info_t *info; hid_t fapl_id, under_fapl_id; const char *name; diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index 45fd022..12448b6 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -19,387 +19,29 @@ /* Public headers needed by this file */ #include "H5public.h" /* Generic Functions */ -#include "H5Apublic.h" /* Attributes */ -#include "H5ESpublic.h" /* Event Stack */ -#include "H5Fpublic.h" /* Files */ -#include "H5Ipublic.h" /* IDs */ -#include "H5Lpublic.h" /* Links */ -#include "H5Opublic.h" /* Objects */ -#include "H5Rpublic.h" /* References */ +#include "H5Ipublic.h" /* IDs */ + +/* Semi-public headers mainly for VOL connector authors */ +#include "H5VLconnector.h" +#include "H5VLconnector_passthru.h" /*****************/ /* Public Macros */ /*****************/ -/* Default VOL connector value */ -#define H5VL_VOL_DEFAULT 0 - - -/*******************/ -/* Public Typedefs */ -/*******************/ - -/* types for attribute GET callback */ -typedef enum H5VL_attr_get_t { - H5VL_ATTR_GET_ACPL, /* creation property list */ - H5VL_ATTR_GET_INFO, /* info */ - H5VL_ATTR_GET_NAME, /* access property list */ - H5VL_ATTR_GET_SPACE, /* dataspace */ - H5VL_ATTR_GET_STORAGE_SIZE, /* storage size */ - H5VL_ATTR_GET_TYPE /* datatype */ -} H5VL_attr_get_t; - -/* types for attribute SPECFIC callback */ -typedef enum H5VL_attr_specific_t { - H5VL_ATTR_DELETE, /* H5Adelete(_by_name/idx) */ - H5VL_ATTR_EXISTS, /* H5Aexists(_by_name) */ - H5VL_ATTR_ITER, /* H5Aiterate(_by_name) */ - H5VL_ATTR_RENAME /* H5Arename(_by_name) */ -} H5VL_attr_specific_t; - -/* types for dataset GET callback */ -typedef enum H5VL_dataset_get_t { - H5VL_DATASET_GET_DAPL, /* access property list */ - H5VL_DATASET_GET_DCPL, /* creation property list */ - H5VL_DATASET_GET_OFFSET, /* offset */ - H5VL_DATASET_GET_SPACE, /* dataspace */ - H5VL_DATASET_GET_SPACE_STATUS, /* space status */ - H5VL_DATASET_GET_STORAGE_SIZE, /* storage size */ - H5VL_DATASET_GET_TYPE /* datatype */ -} H5VL_dataset_get_t; - -/* types for dataset SPECFIC callback */ -typedef enum H5VL_dataset_specific_t { - H5VL_DATASET_SET_EXTENT, /* H5Dset_extent */ - H5VL_DATASET_FLUSH, /* H5Dflush */ - H5VL_DATASET_REFRESH /* H5Drefresh */ -} H5VL_dataset_specific_t; - -/* types for datatype GET callback */ -typedef enum H5VL_datatype_get_t { - H5VL_DATATYPE_GET_BINARY, /* get serialized form of transient type */ - H5VL_DATATYPE_GET_TCPL /* datatype creation property list */ -} H5VL_datatype_get_t; - -/* types for datatype SPECFIC callback */ -typedef enum H5VL_datatype_specific_t { - H5VL_DATATYPE_FLUSH, - H5VL_DATATYPE_REFRESH -} H5VL_datatype_specific_t; - -/* types for file GET callback */ -typedef enum H5VL_file_get_t { - H5VL_FILE_GET_FAPL, /* file access property list */ - H5VL_FILE_GET_FCPL, /* file creation property list */ - H5VL_FILE_GET_INTENT, /* file intent */ - H5VL_FILE_GET_FILENO, /* file number */ - H5VL_FILE_GET_NAME, /* file name */ - H5VL_FILE_GET_OBJ_COUNT, /* object count in file */ - H5VL_FILE_GET_OBJ_IDS /* object ids in file */ -} H5VL_file_get_t; - -/* types for file SPECIFIC callback */ -typedef enum H5VL_file_specific_t { - H5VL_FILE_FLUSH, /* Flush file */ - H5VL_FILE_REOPEN, /* Reopen the file */ - H5VL_FILE_MOUNT, /* Mount a file */ - H5VL_FILE_UNMOUNT, /* Unmount a file */ - H5VL_FILE_IS_ACCESSIBLE /* Check if a file is accessible */ -} H5VL_file_specific_t; - -/* types for group GET callback */ -typedef enum H5VL_group_get_t { - H5VL_GROUP_GET_GCPL, /* group creation property list */ - H5VL_GROUP_GET_INFO /* group info */ -} H5VL_group_get_t; - -/* types for group SPECFIC callback */ -typedef enum H5VL_group_specific_t { - H5VL_GROUP_FLUSH, - H5VL_GROUP_REFRESH -} H5VL_group_specific_t; - -/* link create types for VOL */ -typedef enum H5VL_link_create_type_t { - H5VL_LINK_CREATE_HARD, - H5VL_LINK_CREATE_SOFT, - H5VL_LINK_CREATE_UD -} H5VL_link_create_type_t; - -/* types for link GET callback */ -typedef enum H5VL_link_get_t { - H5VL_LINK_GET_INFO, /* link info */ - H5VL_LINK_GET_NAME, /* link name */ - H5VL_LINK_GET_VAL /* link value */ -} H5VL_link_get_t; - -/* types for link SPECIFIC callback */ -typedef enum H5VL_link_specific_t { - H5VL_LINK_DELETE, /* H5Ldelete(_by_idx) */ - H5VL_LINK_EXISTS, /* link existence */ - H5VL_LINK_ITER /* H5Literate/visit(_by_name) */ -} H5VL_link_specific_t; - -/* types for object GET callback */ -typedef enum H5VL_object_get_t { - H5VL_REF_GET_NAME, /* object name, for reference */ - H5VL_REF_GET_REGION, /* dataspace of region */ - H5VL_REF_GET_TYPE, /* type of object */ - H5VL_ID_GET_NAME /* object name, for hid_t */ -} H5VL_object_get_t; - -/* types for object SPECIFIC callback */ -typedef enum H5VL_object_specific_t { - H5VL_OBJECT_CHANGE_REF_COUNT, /* H5Oincr/decr_refcount */ - H5VL_OBJECT_EXISTS, /* H5Oexists_by_name */ - H5VL_OBJECT_VISIT, /* H5Ovisit(_by_name) */ - H5VL_REF_CREATE, /* H5Rcreate */ - H5VL_OBJECT_FLUSH, /* H5{D|G|O|T}flush */ - H5VL_OBJECT_REFRESH /* H5{D|G|O|T}refresh */ -} H5VL_object_specific_t; - -/* types for async request SPECIFIC callback */ -typedef enum H5VL_request_specific_t { - H5VL_REQUEST_WAITANY, /* Wait until any request completes */ - H5VL_REQUEST_WAITSOME, /* Wait until at least one requesst completes */ - H5VL_REQUEST_WAITALL /* Wait until all requests complete */ -} H5VL_request_specific_t; - -/* types for different ways that objects are located in an HDF5 container */ -typedef enum H5VL_loc_type_t { - H5VL_OBJECT_BY_SELF, - H5VL_OBJECT_BY_NAME, - H5VL_OBJECT_BY_IDX, - H5VL_OBJECT_BY_ADDR, - H5VL_OBJECT_BY_REF -} H5VL_loc_type_t; - -struct H5VL_loc_by_name { - const char *name; - hid_t lapl_id; -}; - -struct H5VL_loc_by_idx { - const char *name; - H5_index_t idx_type; - H5_iter_order_t order; - hsize_t n; - hid_t lapl_id; -}; - -struct H5VL_loc_by_addr { - haddr_t addr; -}; - -struct H5VL_loc_by_ref { - H5R_type_t ref_type; - const void *_ref; - hid_t lapl_id; -}; - -/* Structure to hold parameters for object locations. - * either: BY_ADDR, BY_ID, BY_NAME, BY_IDX, BY_REF - * - * Note: Leave loc_by_addr as the first union member so we - * can perform the simplest initialization of the struct - * without raising warnings. +/* VOL connector identifier values + * These are H5VL_class_value_t values, NOT hid_t values! */ -typedef struct H5VL_loc_params_t { - H5I_type_t obj_type; - H5VL_loc_type_t type; - union{ - struct H5VL_loc_by_addr loc_by_addr; - struct H5VL_loc_by_name loc_by_name; - struct H5VL_loc_by_idx loc_by_idx; - struct H5VL_loc_by_ref loc_by_ref; - } loc_data; -} H5VL_loc_params_t; - -/* VOL connector info fields & callbacks */ -typedef struct H5VL_info_class_t { - size_t size; /* Size of the VOL info */ - void * (*copy)(const void *info); /* Callback to create a copy of the VOL info */ - herr_t (*cmp)(int *cmp_value, const void *info1, const void *info2); /* Callback to compare VOL info */ - herr_t (*free)(void *info); /* Callback to release a VOL info */ - herr_t (*to_str)(const void *info, char **str); /* Callback to serialize connector's info into a string */ - herr_t (*from_str)(const char *str, void **info); /* Callback to deserialize a string into connector's info */ -} H5VL_info_class_t; - -/* VOL object wrap / retrieval callbacks */ -/* (These only need to be implemented by "pass through" VOL connectors) */ -typedef struct H5VL_wrap_class_t { - void * (*get_object)(const void *obj); /* Callback to retrieve underlying object */ - herr_t (*get_wrap_ctx)(const void *obj, void **wrap_ctx); /* Callback to retrieve the object wrapping context for the connector */ - void * (*wrap_object)(void *obj, H5I_type_t obj_type, void *wrap_ctx); /* Callback to wrap a library object */ - void * (*unwrap_object)(void *obj); /* Callback to unwrap a library object */ - herr_t (*free_wrap_ctx)(void *wrap_ctx); /* Callback to release the object wrapping context for the connector */ -} H5VL_wrap_class_t; - -/* H5A routines */ -typedef struct H5VL_attr_class_t { - void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, - hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, - hid_t dxpl_id, void **req); - void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, - hid_t aapl_id, hid_t dxpl_id, void **req); - herr_t (*read)(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req); - herr_t (*write)(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req); - herr_t (*get)(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*close) (void *attr, hid_t dxpl_id, void **req); -} H5VL_attr_class_t; - -/* H5D routines */ -typedef struct H5VL_dataset_class_t { - void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, - hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, - hid_t dapl_id, hid_t dxpl_id, void **req); - void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, - hid_t dapl_id, hid_t dxpl_id, void **req); - herr_t (*read)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, - hid_t xfer_plist_id, void * buf, void **req); - herr_t (*write)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, - hid_t xfer_plist_id, const void * buf, void **req); - herr_t (*get)(void *obj, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, H5VL_dataset_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*close) (void *dset, hid_t dxpl_id, void **req); -} H5VL_dataset_class_t; - -/* H5T routines*/ -typedef struct H5VL_datatype_class_t { - void *(*commit)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, - hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); - void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char * name, - hid_t tapl_id, hid_t dxpl_id, void **req); - herr_t (*get) (void *obj, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, H5VL_datatype_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*close) (void *dt, hid_t dxpl_id, void **req); -} H5VL_datatype_class_t; - -/* H5F routines */ -typedef struct H5VL_file_class_t { - void *(*create)(const char *name, unsigned flags, hid_t fcpl_id, - hid_t fapl_id, hid_t dxpl_id, void **req); - void *(*open)(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); - herr_t (*get)(void *obj, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, H5VL_file_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*close) (void *file, hid_t dxpl_id, void **req); -} H5VL_file_class_t; - -/* H5G routines */ -typedef struct H5VL_group_class_t { - void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, - hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); - void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, - hid_t gapl_id, hid_t dxpl_id, void **req); - herr_t (*get)(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, H5VL_group_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); - herr_t (*close) (void *grp, hid_t dxpl_id, void **req); -} H5VL_group_class_t; - -/* H5L routines */ -typedef struct H5VL_link_class_t { - herr_t (*create)(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, - hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list argumenmts); - herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1, - void *dst_obj, const H5VL_loc_params_t *loc_params2, - hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req); - herr_t (*move)(void *src_obj, const H5VL_loc_params_t *loc_params1, - void *dst_obj, const H5VL_loc_params_t *loc_params2, - hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req); - herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); -} H5VL_link_class_t; - -/* H5O routines */ -typedef struct H5VL_object_class_t { - void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type, - hid_t dxpl_id, void **req); - herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name, - void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name, - hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); - herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, - hid_t dxpl_id, void **req, va_list arguments); - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); -} H5VL_object_class_t; - -/* Asynchronous request 'notify' callback */ -typedef herr_t (*H5VL_request_notify_t)(void *ctx, H5ES_status_t status); - -/* Async request operation routines */ -typedef struct H5VL_request_class_t { - herr_t (*wait)(void *req, uint64_t timeout, H5ES_status_t *status); - herr_t (*notify)(void *req, H5VL_request_notify_t cb, void *ctx); - herr_t (*cancel)(void *req); - herr_t (*specific)(void *req, H5VL_request_specific_t specific_type, va_list arguments); - herr_t (*optional)(void *req, va_list arguments); - herr_t (*free)(void *req); -} H5VL_request_class_t; - -/* - * VOL connector identifiers. Values 0 through 255 are for connectors defined - * by the HDF5 library. Values 256 through 511 are available for testing new - * filters. Subsequent values should be obtained from the HDF5 development - * team at help@hdfgroup.org. - */ -typedef int H5VL_class_value_t; - -/* VOL connector identifier values */ #define H5_VOL_INVALID (-1) /* Invalid ID for VOL connector iD */ -#define H5_VOL_NATIVE 0 /* Native HDF5 file formnat VOL connector */ +#define H5_VOL_NATIVE 0 /* Native HDF5 file format VOL connector */ #define H5_VOL_RESERVED 256 /* VOL connector IDs below this value are reserved for library use */ -#define H5_VOL_MAX 65535 /* Maximum VOL connector ID */ - -/* Capability flags for connector */ -#define H5VL_CAP_FLAG_NONE 0 /* No special connector capabilities */ -#define H5VL_CAP_FLAG_THREADSAFE 0x01 /* Connector is threadsafe */ - -/* Class information for each VOL connector */ -typedef struct H5VL_class_t { - /* Overall connector fields & callbacks */ - unsigned int version; /* VOL connector class struct version # */ - H5VL_class_value_t value; /* Value to identify connector */ - const char *name; /* Connector name (MUST be unique!) */ - unsigned cap_flags; /* Capability flags for connector */ - herr_t (*initialize)(hid_t vipl_id); /* Connector initialization callback */ - herr_t (*terminate)(void); /* Connector termination callback */ +#define H5_VOL_MAX 65535 /* Maximum VOL connector ID */ - /* VOL framework */ - H5VL_info_class_t info_cls; /* VOL info fields & callbacks */ - H5VL_wrap_class_t wrap_cls; /* VOL object wrap / retrieval callbacks */ - - /* Data Model */ - H5VL_attr_class_t attr_cls; /* Attribute (H5A*) class callbacks */ - H5VL_dataset_class_t dataset_cls; /* Dataset (H5D*) class callbacks */ - H5VL_datatype_class_t datatype_cls; /* Datatype (H5T*) class callbacks */ - H5VL_file_class_t file_cls; /* File (H5F*) class callbacks */ - H5VL_group_class_t group_cls; /* Group (H5G*) class callbacks */ - H5VL_link_class_t link_cls; /* Link (H5L*) class callbacks */ - H5VL_object_class_t object_cls; /* Object (H5O*) class callbacks */ - - /* Services */ - H5VL_request_class_t request_cls; /* Asynchronous request class callbacks */ - - /* Catch-all */ - herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); /* Optional callback */ -} H5VL_class_t; +/*******************/ +/* Public Typedefs */ +/*******************/ /********************/ /* Public Variables */ @@ -413,7 +55,10 @@ typedef struct H5VL_class_t { extern "C" { #endif -/* VOL Connector Functionality */ +/* The H5VL types uses in the API calls are not opaque - they are defined in + * H5VLconnector.h, which is included at the top of this file. + */ + H5_DLL hid_t H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id); H5_DLL hid_t H5VLregister_connector_by_name(const char *connector_name, hid_t vipl_id); H5_DLL hid_t H5VLregister_connector_by_value(H5VL_class_value_t connector_value, hid_t vipl_id); @@ -424,112 +69,6 @@ H5_DLL herr_t H5VLclose(hid_t connector_id); H5_DLL herr_t H5VLunregister_connector(hid_t connector_id); -/***************************************************************************** - * VOL callback wrappers and helper routines, for _VOL_connector_ authors only! * - * (Not part of the public API for _application_ developers) * - *****************************************************************************/ - -/* Helper routines for VOL connector authors */ -H5_DLL herr_t H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2); -H5_DLL hid_t H5VLwrap_register(void *obj, H5I_type_t type); -H5_DLL void *H5VLobject(hid_t obj_id); -H5_DLL herr_t H5VLretrieve_lib_state(void **state); -H5_DLL herr_t H5VLrestore_lib_state(const void *state); -H5_DLL herr_t H5VLreset_lib_state(void); -H5_DLL herr_t H5VLfree_lib_state(void *state); - - -/* Public wrappers for generic callbacks */ -H5_DLL herr_t H5VLinitialize(hid_t connector_id, hid_t vipl_id); -H5_DLL herr_t H5VLterminate(hid_t connector_id); -H5_DLL herr_t H5VLget_cap_flags(hid_t connector_id, unsigned *cap_flags); -H5_DLL herr_t H5VLget_value(hid_t connector_id, H5VL_class_value_t *conn_value); -H5_DLL herr_t H5VLcopy_connector_info(hid_t connector_id, void **dst_vol_info, void *src_vol_info); -H5_DLL herr_t H5VLcmp_connector_info(int *cmp, hid_t connector_id, const void *info1, - const void *info2); -H5_DLL herr_t H5VLfree_connector_info(hid_t connector_id, void *vol_info); -H5_DLL herr_t H5VLconnector_info_to_str(const void *info, hid_t connector_id, char **str); -H5_DLL herr_t H5VLconnector_str_to_info(const char *str, hid_t connector_id, void **info); -H5_DLL void *H5VLget_object(void *obj, hid_t connector_id); -H5_DLL herr_t H5VLget_wrap_ctx(void *obj, hid_t connector_id, void **wrap_ctx); -H5_DLL void *H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, - void *wrap_ctx); -H5_DLL void *H5VLunwrap_object(void *obj, hid_t connector_id); -H5_DLL herr_t H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id); - -/* Public wrappers for attribute callbacks */ -H5_DLL void *H5VLattr_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); -H5_DLL void *H5VLattr_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLattr_read(void *attr, hid_t connector_id, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLattr_write(void *attr, hid_t connector_id, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLattr_get(void *obj, hid_t connector_id, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLattr_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLattr_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLattr_close(void *attr, hid_t connector_id, hid_t dxpl_id, void **req); - -/* Public wrappers for dataset callbacks */ -H5_DLL void *H5VLdataset_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req); -H5_DLL void *H5VLdataset_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t dapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLdataset_read(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, void *buf, void **req); -H5_DLL herr_t H5VLdataset_write(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf, void **req); -H5_DLL herr_t H5VLdataset_get(void *dset, hid_t connector_id, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdataset_specific(void *obj, hid_t connector_id, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdataset_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdataset_close(void *dset, hid_t connector_id, hid_t dxpl_id, void **req); - -/* Public wrappers for file callbacks */ -H5_DLL void *H5VLfile_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req); -H5_DLL void *H5VLfile_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLfile_get(void *file, hid_t connector_id, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLfile_specific(void *obj, hid_t connector_id, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLfile_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLfile_close(void *file, hid_t connector_id, hid_t dxpl_id, void **req); - -/* Public wrappers for group callbacks */ -H5_DLL void *H5VLgroup_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); -H5_DLL void *H5VLgroup_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLgroup_get(void *obj, hid_t connector_id, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLgroup_specific(void *obj, hid_t connector_id, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLgroup_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLgroup_close(void *grp, hid_t connector_id, hid_t dxpl_id, void **req); - -/* Public wrappers for link callbacks */ -H5_DLL herr_t H5VLlink_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLlink_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, - void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id, - hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLlink_move(void *src_obj, const H5VL_loc_params_t *loc_params1, - void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id, - hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLlink_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLlink_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLlink_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); - -/* Public wrappers for object callbacks */ -H5_DLL void *H5VLobject_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5I_type_t *opened_type, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLobject_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name, - void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name, - hid_t connector_id, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLobject_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLobject_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLobject_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); - -/* Public wrappers for named datatype callbacks */ -H5_DLL void *H5VLdatatype_commit(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); -H5_DLL void *H5VLdatatype_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req); -H5_DLL herr_t H5VLdatatype_get(void *dt, hid_t connector_id, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdatatype_specific(void *obj, hid_t connector_id, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdatatype_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments); -H5_DLL herr_t H5VLdatatype_close(void *dt, hid_t connector_id, hid_t dxpl_id, void **req); - -/* Public wrappers for asynchronous request callbacks */ -H5_DLL herr_t H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status); -H5_DLL herr_t H5VLrequest_notify(void *req, hid_t connector_id, H5VL_request_notify_t cb, void *ctx); -H5_DLL herr_t H5VLrequest_cancel(void *req, hid_t connector_id); -H5_DLL herr_t H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_specific_t specific_type, va_list arguments); -H5_DLL herr_t H5VLrequest_optional(void *req, hid_t connector_id, va_list arguments); -H5_DLL herr_t H5VLrequest_free(void *req, hid_t connector_id); - #ifdef __cplusplus } #endif diff --git a/src/H5err.txt b/src/H5err.txt index 4eedc0f..d4edfba 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -134,6 +134,7 @@ MINOR, FILEACC, H5E_NOTHDF5, Not an HDF5 file MINOR, FILEACC, H5E_BADFILE, Bad file ID accessed MINOR, FILEACC, H5E_TRUNCATED, File has been truncated MINOR, FILEACC, H5E_MOUNT, File mount error +MINOR, FILEACC, H5E_CANTDELETEFILE, Unable to delete file # Generic low-level file I/O errors MINOR, FILE, H5E_SEEKERROR, Seek failed diff --git a/src/H5trace.c b/src/H5trace.c index 23f2f1d..9c858fc 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -1387,6 +1387,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...) HDfprintf(out, "%ld (err stack)", (long)obj); break; + case H5I_SPACE_SEL_ITER: + HDfprintf(out, "%ld (dataspace selection iterator)", (long)obj); + break; + case H5I_NTYPES: HDfprintf (out, "%ld (ntypes - error)", (long)obj); break; @@ -1568,6 +1572,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...) HDfprintf(out, "H5I_ERROR_STACK"); break; + case H5I_SPACE_SEL_ITER: + HDfprintf(out, "H5I_SPACE_SEL_ITER"); + break; + case H5I_NTYPES: HDfprintf(out, "H5I_NTYPES"); break; @@ -2714,6 +2722,9 @@ H5_trace(const double *returning, const char *func, const char *type, ...) case H5VL_FILE_GET_INTENT: HDfprintf(out, "H5VL_FILE_GET_INTENT"); break; + case H5VL_FILE_GET_FILENO: + HDfprintf(out, "H5VL_FILE_GET_FILENO"); + break; case H5VL_FILE_GET_NAME: HDfprintf(out, "H5VL_FILE_GET_NAME"); break; @@ -2755,6 +2766,9 @@ H5_trace(const double *returning, const char *func, const char *type, ...) case H5VL_FILE_IS_ACCESSIBLE: HDfprintf(out, "H5VL_FILE_IS_ACCESSIBLE"); break; + case H5VL_FILE_DELETE: + HDfprintf(out, "H5VL_FILE_DELETE"); + break; default: HDfprintf(out, "%ld", (long)specific); break; @@ -2905,8 +2919,8 @@ H5_trace(const double *returning, const char *func, const char *type, ...) case H5VL_REF_GET_NAME: HDfprintf(out, "H5VL_REF_GET_NAME"); break; - case H5VL_ID_GET_NAME: - HDfprintf(out, "H5VL_ID_GET_NAME"); + case H5VL_OBJECT_GET_NAME: + HDfprintf(out, "H5VL_OBJECT_GET_NAME"); break; default: HDfprintf(out, "%ld", (long)get); diff --git a/src/Makefile.am b/src/Makefile.am index 378e390..0eaae1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -115,9 +115,9 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Torder.c \ H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c \ H5VL.c H5VLcallback.c H5VLint.c H5VLnative.c \ - H5VLnative_attr.c H5VLnative_dataset.c H5VLnative_datatype.c \ - H5VLnative_file.c H5VLnative_group.c H5VLnative_link.c H5VLnative_object.c \ - H5VLpassthru.c \ + H5VLnative_attr.c H5VLnative_dataset.c H5VLnative_datatype.c \ + H5VLnative_file.c H5VLnative_group.c H5VLnative_link.c H5VLnative_object.c \ + H5VLpassthru.c \ H5VM.c H5WB.c H5Z.c \ H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \ H5Zscaleoffset.c H5Zszip.c H5Ztrans.c @@ -144,7 +144,9 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5MMpublic.h H5Opublic.h H5Ppublic.h \ H5PLextern.h H5PLpublic.h \ H5Rpublic.h H5Spublic.h H5Tpublic.h \ - H5VLnative.h H5VLpassthru.h H5VLpublic.h H5Zpublic.h + H5VLconnector.h H5VLconnector_passthru.h \ + H5VLnative.h H5VLpassthru.h H5VLpublic.h \ + H5Zpublic.h # install libhdf5.settings in lib directory settingsdir=$(libdir) @@ -209,3 +211,4 @@ trace: $(libhdf5_la_SOURCES) done include $(top_srcdir)/config/conclude.am + diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in index 9d0e29f..37957a2 100644 --- a/src/libhdf5.settings.in +++ b/src/libhdf5.settings.in @@ -71,6 +71,8 @@ Features: Parallel Filtered Dataset Writes: @PARALLEL_FILTERED_WRITES@ Large Parallel I/O: @LARGE_PARALLEL_IO@ High-level library: @HDF5_HL@ + Build HDF5 Tests: @HDF5_TESTS@ + Build HDF5 TOOLS: @HDF5_TOOLS@ Threadsafety: @THREADSAFE@ Default API mapping: @DEFAULT_API_VERSION@ With deprecated public symbols: @DEPRECATED_SYMBOLS@ |