Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 45094 Content-Disposition: inline; filename="H5Plapl.c" Last-Modified: Sun, 21 Jul 2024 23:23:19 GMT Expires: Wed, 19 Jul 2034 23:23:19 GMT ETag: "7a7cc23e00933c7762567419a14247014c54455e" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*------------------------------------------------------------------------- * * Created: H5Plapl.c * July 14 2006 * James Laird * * Purpose: Link access property list class routines * *------------------------------------------------------------------------- */ /****************/ /* Module Setup */ /****************/ #include "H5Pmodule.h" /* This source code file is part of the H5P module */ /***********/ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ #include "H5Lprivate.h" /* Links */ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ /****************/ /* Local Macros */ /****************/ /* ======== Link access properties ======== */ /* Definitions for number of soft links to traverse */ #define H5L_ACS_NLINKS_SIZE sizeof(size_t) #define H5L_ACS_NLINKS_DEF H5L_NUM_LINKS /*max symlinks to follow per lookup */ #define H5L_ACS_NLINKS_ENC H5P__encode_size_t #define H5L_ACS_NLINKS_DEC H5P__decode_size_t /* Definitions for external link prefix */ #define H5L_ACS_ELINK_PREFIX_SIZE sizeof(char *) #define H5L_ACS_ELINK_PREFIX_DEF NULL /*default is no prefix */ #define H5L_ACS_ELINK_PREFIX_SET H5P__lacc_elink_pref_set #define H5L_ACS_ELINK_PREFIX_GET H5P__lacc_elink_pref_get #define H5L_ACS_ELINK_PREFIX_ENC H5P__lacc_elink_pref_enc #define H5L_ACS_ELINK_PREFIX_DEC H5P__lacc_elink_pref_dec #define H5L_ACS_ELINK_PREFIX_DEL H5P__lacc_elink_pref_del #define H5L_ACS_ELINK_PREFIX_COPY H5P__lacc_elink_pref_copy #define H5L_ACS_ELINK_PREFIX_CMP H5P__lacc_elink_pref_cmp #define H5L_ACS_ELINK_PREFIX_CLOSE H5P__lacc_elink_pref_close /* Definitions for setting fapl of external link access */ #define H5L_ACS_ELINK_FAPL_SIZE sizeof(hid_t) #define H5L_ACS_ELINK_FAPL_DEF H5P_DEFAULT #define H5L_ACS_ELINK_FAPL_SET H5P__lacc_elink_fapl_set #define H5L_ACS_ELINK_FAPL_GET H5P__lacc_elink_fapl_get #define H5L_ACS_ELINK_FAPL_ENC H5P__lacc_elink_fapl_enc #define H5L_ACS_ELINK_FAPL_DEC H5P__lacc_elink_fapl_dec #define H5L_ACS_ELINK_FAPL_DEL H5P__lacc_elink_fapl_del #define H5L_ACS_ELINK_FAPL_COPY H5P__lacc_elink_fapl_copy #define H5L_ACS_ELINK_FAPL_CMP H5P__lacc_elink_fapl_cmp #define H5L_ACS_ELINK_FAPL_CLOSE H5P__lacc_elink_fapl_close /* Definitions for file access flags for external link traversal */ #define H5L_ACS_ELINK_FLAGS_SIZE sizeof(unsigned) #define H5L_ACS_ELINK_FLAGS_DEF H5F_ACC_DEFAULT #define H5L_ACS_ELINK_FLAGS_ENC H5P__encode_unsigned #define H5L_ACS_ELINK_FLAGS_DEC H5P__decode_unsigned /* Definitions for callback function for external link traversal */ #define H5L_ACS_ELINK_CB_SIZE sizeof(H5L_elink_cb_t) #define H5L_ACS_ELINK_CB_DEF {NULL,NULL} #ifdef H5_HAVE_PARALLEL /* Definition for reading metadata collectively */ #define H5L_ACS_COLL_MD_READ_SIZE sizeof(H5P_coll_md_read_flag_t) #define H5L_ACS_COLL_MD_READ_DEF H5P_USER_FALSE #define H5L_ACS_COLL_MD_READ_ENC H5P__encode_coll_md_read_flag_t #define H5L_ACS_COLL_MD_READ_DEC H5P__decode_coll_md_read_flag_t #endif /* H5_HAVE_PARALLEL */ /******************/ /* Local Typedefs */ /******************/ /********************/ /* Package Typedefs */ /********************/ /********************/ /* Local Prototypes */ /********************/ /* Property class callbacks */ static herr_t H5P__lacc_reg_prop(H5P_genclass_t *pclass); /* Property list callbacks */ static herr_t H5P__lacc_elink_pref_set(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_pref_get(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_pref_enc(const void *value, void **_pp, size_t *size); static herr_t H5P__lacc_elink_pref_dec(const void **_pp, void *value); static herr_t H5P__lacc_elink_pref_del(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_pref_copy(const char* name, size_t size, void* value); static int H5P__lacc_elink_pref_cmp(const void *value1, const void *value2, size_t size); static herr_t H5P__lacc_elink_pref_close(const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_fapl_set(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_fapl_get(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_fapl_enc(const void *value, void **_pp, size_t *size); static herr_t H5P__lacc_elink_fapl_dec(const void **_pp, void *value); static herr_t H5P__lacc_elink_fapl_del(hid_t prop_id, const char* name, size_t size, void* value); static herr_t H5P__lacc_elink_fapl_copy(const char* name, size_t size, void* value); static int H5P__lacc_elink_fapl_cmp(const void *value1, const void *value2, size_t size); static herr_t H5P__lacc_elink_fapl_close(const char* name, size_t size, void* value); /*********************/ /* Package Variables */ /*********************/ /* Dataset creation property list class library initialization object */ const H5P_libclass_t H5P_CLS_LACC[1] = {{ "link access", /* Class name for debugging */ H5P_TYPE_LINK_ACCESS, /* Class type */ &H5P_CLS_ROOT_g, /* Parent class */ &H5P_CLS_LINK_ACCESS_g, /* Pointer to class */ &H5P_CLS_LINK_ACCESS_ID_g, /* Pointer to class ID */ &H5P_LST_LINK_ACCESS_ID_g, /* Pointer to default property list ID */ H5P__lacc_reg_prop, /* 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 Private Variables */ /*****************************/ /*******************/ /* Local Variables */ /*******************/ /* Property value defaults */ static const size_t H5L_def_nlinks_g = H5L_ACS_NLINKS_DEF; /* Default number of soft links to traverse */ static const char *H5L_def_elink_prefix_g = H5L_ACS_ELINK_PREFIX_DEF; /* Default external link prefix string */ static const hid_t H5L_def_fapl_id_g = H5L_ACS_ELINK_FAPL_DEF; /* Default fapl for external link access */ static const unsigned H5L_def_elink_flags_g = H5L_ACS_ELINK_FLAGS_DEF; /* Default file access flags for external link traversal */ static const H5L_elink_cb_t H5L_def_elink_cb_g = H5L_ACS_ELINK_CB_DEF; /* Default external link traversal callback */ #ifdef H5_HAVE_PARALLEL static const H5P_coll_md_read_flag_t H5L_def_coll_md_read_g = H5L_ACS_COLL_MD_READ_DEF; /* Default setting for the collective metedata read flag */ #endif /* H5_HAVE_PARALLEL */ /*------------------------------------------------------------------------- * Function: H5P__lacc_reg_prop * * Purpose: Register the dataset creation property list class's properties * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * October 31, 2006 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_reg_prop(H5P_genclass_t *pclass) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Register property for number of links traversed */ if(H5P__register_real(pclass, H5L_ACS_NLINKS_NAME, H5L_ACS_NLINKS_SIZE, &H5L_def_nlinks_g, NULL, NULL, NULL, H5L_ACS_NLINKS_ENC, H5L_ACS_NLINKS_DEC, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") /* Register property for external link prefix */ if(H5P__register_real(pclass, H5L_ACS_ELINK_PREFIX_NAME, H5L_ACS_ELINK_PREFIX_SIZE, &H5L_def_elink_prefix_g, NULL, H5L_ACS_ELINK_PREFIX_SET, H5L_ACS_ELINK_PREFIX_GET, H5L_ACS_ELINK_PREFIX_ENC, H5L_ACS_ELINK_PREFIX_DEC, H5L_ACS_ELINK_PREFIX_DEL, H5L_ACS_ELINK_PREFIX_COPY, H5L_ACS_ELINK_PREFIX_CMP, H5L_ACS_ELINK_PREFIX_CLOSE) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") /* Register fapl for link access */ if(H5P__register_real(pclass, H5L_ACS_ELINK_FAPL_NAME, H5L_ACS_ELINK_FAPL_SIZE, &H5L_def_fapl_id_g, NULL, H5L_ACS_ELINK_FAPL_SET, H5L_ACS_ELINK_FAPL_GET, H5L_ACS_ELINK_FAPL_ENC, H5L_ACS_ELINK_FAPL_DEC, H5L_ACS_ELINK_FAPL_DEL, H5L_ACS_ELINK_FAPL_COPY, H5L_ACS_ELINK_FAPL_CMP, H5L_ACS_ELINK_FAPL_CLOSE) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") /* Register property for external link file access flags */ if(H5P__register_real(pclass, H5L_ACS_ELINK_FLAGS_NAME, H5L_ACS_ELINK_FLAGS_SIZE, &H5L_def_elink_flags_g, NULL, NULL, NULL, H5L_ACS_ELINK_FLAGS_ENC, H5L_ACS_ELINK_FLAGS_DEC, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") /* Register property for external link file traversal callback */ /* (Note: this property should not have an encode/decode callback -QAK) */ if(H5P__register_real(pclass, H5L_ACS_ELINK_CB_NAME, H5L_ACS_ELINK_CB_SIZE, &H5L_def_elink_cb_g, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") #ifdef H5_HAVE_PARALLEL /* Register the metadata collective read flag */ if(H5P__register_real(pclass, H5_COLL_MD_READ_FLAG_NAME, H5L_ACS_COLL_MD_READ_SIZE, &H5L_def_coll_md_read_g, NULL, NULL, NULL, H5L_ACS_COLL_MD_READ_ENC, H5L_ACS_COLL_MD_READ_DEC, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") #endif /* H5_HAVE_PARALLEL */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_reg_prop() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_set * * Purpose: Copies an external link FAPL property when it's set for a property list * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, Sept 2, 2015 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { hid_t l_fapl_id; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC /* Sanity check */ HDassert(value); /* Get the FAPL ID */ l_fapl_id = *(const hid_t *)value; /* Duplicate the FAPL, if it's non-default */ if(l_fapl_id != H5P_DEFAULT) { H5P_genplist_t *l_fapl_plist; if(NULL == (l_fapl_plist = (H5P_genplist_t *)H5P_object_verify(l_fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") if(((*(hid_t *)value) = H5P_copy_plist(l_fapl_plist, FALSE)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy file access property list") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_set() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_get * * Purpose: Copies an external link FAPL property when it's retrieved from a property list * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, Sept 2, 2015 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { hid_t l_fapl_id; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC /* Sanity check */ HDassert(value); /* Get the FAPL ID */ l_fapl_id = *(const hid_t *)value; /* Duplicate the FAPL, if it's non-default */ if(l_fapl_id != H5P_DEFAULT) { H5P_genplist_t *l_fapl_plist; if(NULL == (l_fapl_plist = (H5P_genplist_t *)H5P_object_verify(l_fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") if(((*(hid_t *)value) = H5P_copy_plist(l_fapl_plist, FALSE)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy file access property list") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_get() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_enc * * Purpose: Callback routine which is called whenever the elink FAPL * property in the dataset access property list is * encoded. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, August 15, 2012 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_enc(const void *value, void **_pp, size_t *size) { const hid_t *elink_fapl = (const hid_t *)value; /* Property to encode */ uint8_t **pp = (uint8_t **)_pp; H5P_genplist_t *fapl_plist; /* Pointer to property list */ hbool_t non_default_fapl = FALSE; /* Whether the FAPL is non-default */ size_t fapl_size = 0; /* FAPL's encoded size */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check for non-default FAPL */ if(*elink_fapl != H5P_DEFAULT) { if(NULL == (fapl_plist = (H5P_genplist_t *)H5P_object_verify(*elink_fapl, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property list") non_default_fapl = TRUE; } /* end if */ if(NULL != *pp) { /* Store whether the FAPL is non-default */ *(*pp)++ = (uint8_t)non_default_fapl; } /* end if */ /* Encode the property list, if non-default */ /* (if *pp == NULL, will only compute the size) */ if(non_default_fapl) { if(H5P__encode(fapl_plist, TRUE, NULL, &fapl_size) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "can't encode property list") if(*pp) { uint64_t enc_value; unsigned enc_size; /* encode the length of the plist */ enc_value = (uint64_t)fapl_size; enc_size = H5VM_limit_enc_size(enc_value); HDassert(enc_size < 256); *(*pp)++ = (uint8_t)enc_size; UINT64ENCODE_VAR(*pp, enc_value, enc_size); /* encode the plist */ if(H5P__encode(fapl_plist, TRUE, *pp, &fapl_size) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "can't encode property list") *pp += fapl_size; } fapl_size += (1 + H5VM_limit_enc_size((uint64_t)fapl_size)); } /* end if */ *size += (1 + fapl_size); /* Non-default flag, plus encoded property list size */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_enc() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_dec * * Purpose: Callback routine which is called whenever the elink FAPL * property in the dataset access property list is * decoded. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, August 15, 2012 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_dec(const void **_pp, void *_value) { hid_t *elink_fapl = (hid_t *)_value; /* The elink FAPL value */ const uint8_t **pp = (const uint8_t **)_pp; hbool_t non_default_fapl; /* Whether the FAPL is non-default */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Sanity check */ HDassert(pp); HDassert(*pp); HDassert(elink_fapl); HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); /* Determine if the FAPL is non-default */ non_default_fapl = (hbool_t)*(*pp)++; if(non_default_fapl) { size_t fapl_size = 0; /* Encoded size of property list */ unsigned enc_size; uint64_t enc_value; /* Decode the plist length */ enc_size = *(*pp)++; HDassert(enc_size < 256); UINT64DECODE_VAR(*pp, enc_value, enc_size); fapl_size = (size_t)enc_value; /* Decode the property list */ if((*elink_fapl = H5P__decode(*pp)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDECODE, FAIL, "can't decode property") *pp += fapl_size; } /* end if */ else *elink_fapl = H5P_DEFAULT; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_dec() */ /*-------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_del * * Purpose: Close the FAPL for link access * * Return: Success: Non-negative * Failure: Negative * * Programmer: Vailin Choi * Tuesday, Sept 23, 2008 * *-------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { hid_t l_fapl_id; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC /* Sanity check */ HDassert(value); /* Get the FAPL ID */ l_fapl_id = (*(const hid_t *)value); /* Close the FAPL */ if(l_fapl_id != H5P_DEFAULT && H5I_dec_ref(l_fapl_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_del() */ /*-------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_copy * * Purpose: Copy the FAPL for link access * * Return: Success: Non-negative * Failure: Negative * * Programmer: Vailin Choi * Tuesday, Sept 23, 2008 * *-------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { hid_t l_fapl_id; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC /* Sanity check */ HDassert(value); /* Get the FAPL ID */ l_fapl_id = (*(const hid_t *)value); /* Duplicate the FAPL, if it's non-default */ if(l_fapl_id != H5P_DEFAULT) { H5P_genplist_t *l_fapl_plist; if(NULL == (l_fapl_plist = (H5P_genplist_t *)H5P_object_verify(l_fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") if(((*(hid_t *)value) = H5P_copy_plist(l_fapl_plist, FALSE)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy file access property list") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_copy() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_cmp * * Purpose: Callback routine which is called whenever the elink FAPL * property in the link access property list is * compared. * * Return: zero if VALUE1 and VALUE2 are equal, non zero otherwise. * * Programmer: Quincey Koziol * Wednesday, August 15, 2012 * *------------------------------------------------------------------------- */ static int H5P__lacc_elink_fapl_cmp(const void *value1, const void *value2, size_t H5_ATTR_UNUSED size) { const hid_t *fapl1 = (const hid_t *)value1; const hid_t *fapl2 = (const hid_t *)value2; H5P_genplist_t *obj1, *obj2; /* Property lists to compare */ int ret_value = 0; FUNC_ENTER_STATIC_NOERR /* Check for comparison with default value */ if(*fapl1 == 0 && *fapl2 > 0) HGOTO_DONE(1); if(*fapl1 > 0 && *fapl2 == 0) HGOTO_DONE(-1); /* Get the property list objects */ obj1 = (H5P_genplist_t *)H5I_object(*fapl1); obj2 = (H5P_genplist_t *)H5I_object(*fapl2); /* Check for NULL property lists */ if(obj1 == NULL && obj2 != NULL) HGOTO_DONE(1); if(obj1 != NULL && obj2 == NULL) HGOTO_DONE(-1); if(obj1 && obj2) { herr_t status; status = H5P__cmp_plist(obj1, obj2, &ret_value); HDassert(status >= 0); } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_cmp() */ /*-------------------------------------------------------------------------- * Function: H5P__lacc_elink_fapl_close * * Purpose: Close the FAPL for link access * * Return: Success: Non-negative * Failure: Negative * * Programmer: Vailin Choi * Tuesday, Sept 23, 2008 * *--------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_fapl_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { hid_t l_fapl_id; herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC /* Sanity check */ HDassert(value); /* Get the FAPL ID */ l_fapl_id = (*(const hid_t *)value); /* Close the FAPL */ if((l_fapl_id > H5P_DEFAULT) && (H5I_dec_ref(l_fapl_id) < 0)) HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_fapl_close() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_set * * Purpose: Copies an external link prefix property when it's set for a property list * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, Sept 2, 2015 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { FUNC_ENTER_STATIC_NOERR /* Sanity check */ HDassert(value); /* Copy the prefix */ *(char **)value = H5MM_xstrdup(*(const char **)value); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_set() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_get * * Purpose: Copies an external link prefix property when it's retrieved from a property list * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Wednesday, Sept 2, 2015 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { FUNC_ENTER_STATIC_NOERR /* Sanity check */ HDassert(value); /* Copy the prefix */ *(char **)value = H5MM_xstrdup(*(const char **)value); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_get() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_enc * * Purpose: Callback routine which is called whenever the elink flags * property in the dataset access property list is * encoded. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Mohamad Chaarawi * Monday, October 10, 2011 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_enc(const void *value, void **_pp, size_t *size) { const char *elink_pref = *(const char * const *)value; uint8_t **pp = (uint8_t **)_pp; size_t len = 0; uint64_t enc_value; unsigned enc_size; FUNC_ENTER_STATIC_NOERR HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); /* calculate prefix length */ if(NULL != elink_pref) len = HDstrlen(elink_pref); enc_value = (uint64_t)len; enc_size = H5VM_limit_enc_size(enc_value); HDassert(enc_size < 256); if(NULL != *pp) { /* encode the length of the prefix */ *(*pp)++ = (uint8_t)enc_size; UINT64ENCODE_VAR(*pp, enc_value, enc_size); /* encode the prefix */ if(NULL != elink_pref) { H5MM_memcpy(*(char **)pp, elink_pref, len); *pp += len; } /* end if */ } /* end if */ *size += (1 + enc_size); if(NULL != elink_pref) *size += len; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_enc() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_dec * * Purpose: Callback routine which is called whenever the elink prefix * property in the dataset access property list is * decoded. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Mohamad Chaarawi * Monday, October 10, 2011 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_dec(const void **_pp, void *_value) { char **elink_pref = (char **)_value; const uint8_t **pp = (const uint8_t **)_pp; size_t len; uint64_t enc_value; /* Decoded property value */ unsigned enc_size; /* Size of encoded property */ herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC HDassert(pp); HDassert(*pp); HDassert(elink_pref); HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); /* Decode the size */ enc_size = *(*pp)++; HDassert(enc_size < 256); /* Decode the value */ UINT64DECODE_VAR(*pp, enc_value, enc_size); len = (size_t)enc_value; if(0 != len) { /* Make a copy of the user's prefix string */ if(NULL == (*elink_pref = (char *)H5MM_malloc(len + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "memory allocation failed for prefix") HDstrncpy(*elink_pref, *(const char **)pp, len); (*elink_pref)[len] = '\0'; *pp += len; } /* end if */ else *elink_pref = NULL; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_pref_dec() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_del * * Purpose: Frees memory used to store the external link prefix string * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * November 2, 2006 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { FUNC_ENTER_STATIC_NOERR HDassert(value); H5MM_xfree(*(void **)value); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_del() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_copy * * Purpose: Creates a copy of the external link prefix string * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * November 2, 2006 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { FUNC_ENTER_STATIC_NOERR HDassert(value); *(char **)value = H5MM_xstrdup(*(const char **)value); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_copy() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_cmp * * Purpose: Callback routine which is called whenever the elink prefix * property in the dataset creation property list is * compared. * * Return: zero if VALUE1 and VALUE2 are equal, non zero otherwise. * * Programmer: Mohamad Chaarawi * Thursday, November 3, 2011 * *------------------------------------------------------------------------- */ static int H5P__lacc_elink_pref_cmp(const void *value1, const void *value2, size_t H5_ATTR_UNUSED size) { const char *pref1 = *(const char * const *)value1; const char *pref2 = *(const char * const *)value2; int ret_value = 0; FUNC_ENTER_STATIC_NOERR if(NULL == pref1 && NULL != pref2) HGOTO_DONE(1); if(NULL != pref1 && NULL == pref2) HGOTO_DONE(-1); if(NULL != pref1 && NULL != pref2) ret_value = HDstrcmp(pref1, pref2); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__lacc_elink_pref_cmp() */ /*------------------------------------------------------------------------- * Function: H5P__lacc_elink_pref_close * * Purpose: Frees memory used to store the external link prefix string * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * November 2, 2006 * *------------------------------------------------------------------------- */ static herr_t H5P__lacc_elink_pref_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value) { FUNC_ENTER_STATIC_NOERR HDassert(value); H5MM_xfree(*(void **)value); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5P__lacc_elink_pref_close() */ /*------------------------------------------------------------------------- * Function: H5Pset_nlinks * * Purpose: Set the number of soft or UD link traversals allowed before * the library assumes it has found a cycle and aborts the * traversal. * * The limit on soft or UD link traversals is designed to * terminate link traversal if one or more links form a cycle. * However, users may have a file with a legitimate path * formed of a large number of soft or user-defined links. * This property can be used to allow traversal of as many * links as desired. * * Return: Non-negative on success/Negative on failure * * Programmer: James Laird * Friday, July 14, 2006 * *------------------------------------------------------------------------- */ herr_t H5Pset_nlinks(hid_t plist_id, size_t nlinks) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "iz", plist_id, nlinks); if(nlinks <= 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "number of links must be positive"); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Set number of links */ if(H5P_set(plist, H5L_ACS_NLINKS_NAME, &nlinks) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set nlink info") done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_nlinks() */ /*------------------------------------------------------------------------- * Function: H5Pget_nlinks * * Purpose: Gets the number of soft or user-defined links that can be * traversed before a failure occurs. * * Retrieves the current setting for the nlinks property on * the given property list. * * Return: Non-negative on success/Negative on failure * * Programmer: James Laird * Friday, July 14, 2006 * *------------------------------------------------------------------------- */ herr_t H5Pget_nlinks(hid_t plist_id, size_t *nlinks) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*z", plist_id, nlinks); if(!nlinks) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer passed in"); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get the current number of links */ if(H5P_get(plist, H5L_ACS_NLINKS_NAME, nlinks) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get number of links") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Pset_elink_prefix * * Purpose: Set a prefix to be applied to the path of any external links * traversed. The prefix is appended to the filename stored * in the external link. * * Return: Non-negative on success/Negative on failure * * Programmer: James Laird * Thursday, August 3, 2006 * *------------------------------------------------------------------------- */ herr_t H5Pset_elink_prefix(hid_t plist_id, const char *prefix) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*s", plist_id, prefix); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Set prefix */ if(H5P_set(plist, H5L_ACS_ELINK_PREFIX_NAME, &prefix) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set prefix info") done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_elink_prefix() */ /*------------------------------------------------------------------------- * Function: H5Pget_elink_prefix * * Purpose: Gets the prefix to be applied to any external link * traversals made using this property list. * * If the pointer is not NULL, it points to a user-allocated * buffer. * * Return: Non-negative on success/Negative on failure * * Programmer: James Laird * Thursday, August 3, 2006 * *------------------------------------------------------------------------- */ ssize_t H5Pget_elink_prefix(hid_t plist_id, char *prefix, size_t size) { H5P_genplist_t *plist; /* Property list pointer */ char *my_prefix; /* Library's copy of the prefix */ size_t len; /* Length of prefix string */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("Zs", "i*sz", plist_id, prefix, size); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(plist_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get the current prefix */ if(H5P_peek(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix") /* Check for prefix being set */ if(my_prefix) { /* Copy to user's buffer, if given */ len = HDstrlen(my_prefix); if(prefix) { HDstrncpy(prefix, my_prefix, MIN(len + 1, size)); if(len >= size) prefix[size - 1] = '\0'; } /* end if */ } /* end if */ else len = 0; /* Set return value */ ret_value = (ssize_t)len; done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_elink_prefix() */ /*------------------------------------------------------------------------- * Function: H5Pset_elink_fapl * * Purpose: Sets the file access property list for link access * * Return: Non-negative on success/Negative on failure * * Programmer: * Vailin Choi; Tuesday, September 12th, 2008 * *------------------------------------------------------------------------- */ herr_t H5Pset_elink_fapl(hid_t lapl_id, hid_t fapl_id) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "ii", lapl_id, fapl_id); /* Check arguments */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link access property list"); /* Set the file access property list for the link access */ if(H5P_set(plist, H5L_ACS_ELINK_FAPL_NAME, &fapl_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fapl for link") done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_elink_fapl() */ /*------------------------------------------------------------------------- * Function: H5Pget_elink_fapl * * Purpose: Gets the file access property list identifier that is * set for link access property. * * Return: Non-negative on success/Negative on failure * * Programmer: * Vailin Choi; Tuesday, September 12th, 2008 * *------------------------------------------------------------------------- */ hid_t H5Pget_elink_fapl(hid_t lapl_id) { H5P_genplist_t *plist; /* Property list pointer */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("i", "i", lapl_id); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") if(H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &ret_value) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links") done: FUNC_LEAVE_API(ret_value); } /* end H5Pget_elink_fapl() */ /*------------------------------------------------------------------------- * Function: H5Pset_elink_acc_flags * * Purpose: Sets the file access flags to be used when traversing an * external link. This should be either H5F_ACC_RDONLY or * H5F_ACC_RDWR, or H5F_ACC_DEFAULT to unset the value. * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * Tuesday, December 9, 2008 * *------------------------------------------------------------------------- */ herr_t H5Pset_elink_acc_flags(hid_t lapl_id, unsigned flags) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "iIu", lapl_id, flags); /* Check that flags are valid */ if(( flags != H5F_ACC_RDWR) && (flags != (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE)) && (flags != H5F_ACC_RDONLY) && (flags != (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ)) && (flags != H5F_ACC_DEFAULT)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Set flags */ if(H5P_set(plist, H5L_ACS_ELINK_FLAGS_NAME, &flags) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set access flags") done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_elink_acc_flags() */ /*------------------------------------------------------------------------- * Function: H5Pget_elink_acc_flags * * Purpose: Gets the file access flags to be used when traversing an * external link. * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * Tuesday, December 9, 2008 * *------------------------------------------------------------------------- */ herr_t H5Pget_elink_acc_flags(hid_t lapl_id, unsigned *flags) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*Iu", lapl_id, flags); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get flags */ if(flags) if(H5P_get(plist, H5L_ACS_ELINK_FLAGS_NAME, flags) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "can't get access flags") done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_elink_acc_flags() */ /*------------------------------------------------------------------------- * Function: H5Pset_elink_cb * * Purpose: Sets the file access flags to be used when traversing an * external link. This should be either H5F_ACC_RDONLY or * H5F_ACC_RDWR. * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * Tuesday, December 15, 2008 * *------------------------------------------------------------------------- */ herr_t H5Pset_elink_cb(hid_t lapl_id, H5L_elink_traverse_t func, void *op_data) { H5P_genplist_t *plist; /* Property list pointer */ H5L_elink_cb_t cb_info; /* Callback info struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "ix*x", lapl_id, func, op_data); /* Check if the callback function is NULL and the user data is non-NULL. * This is almost certainly an error as the user data will not be used. */ if(!func && op_data) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not") /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Populate the callback info struct */ cb_info.func = func; cb_info.user_data = op_data; /* Set callback info */ if(H5P_set(plist, H5L_ACS_ELINK_CB_NAME, &cb_info) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info") done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_elink_acc_flags() */ /*------------------------------------------------------------------------- * Function: H5Pget_elink_cb * * Purpose: Gets the file access flags to be used when traversing an * external link. * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * Tuesday, December 15, 2008 * *------------------------------------------------------------------------- */ herr_t H5Pget_elink_cb(hid_t lapl_id, H5L_elink_traverse_t *func, void **op_data) { H5P_genplist_t *plist; /* Property list pointer */ H5L_elink_cb_t cb_info; /* Callback info struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "i*x**x", lapl_id, func, op_data); /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get callback_info */ if(H5P_get(plist, H5L_ACS_ELINK_CB_NAME, &cb_info) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't ge * 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://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*------------------------------------------------------------------------- * * Created: H5ESint.c * Apr 8 2020 * Quincey Koziol * * Purpose: Internal "event set" routines for managing asynchronous * operations. * * Please see the asynchronous I/O RFC document * for a full description of how they work, etc. * *------------------------------------------------------------------------- */ /****************/ /* Module Setup */ /****************/ #include "H5ESmodule.h" /* This source code file is part of the H5ES module */ /***********/ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5ESpkg.h" /* Event Sets */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5RSprivate.h" /* Reference-counted strings */ /****************/ /* Local Macros */ /****************/ /******************/ /* Local Typedefs */ /******************/ /* Callback context for get events operations */ typedef struct H5ES_get_requests_ctx_t { hid_t *connector_ids; /* Output buffer for list of connector IDs that match the above requests */ void **requests; /* Output buffer for list of requests in event set */ size_t array_len; /* Length of the above output buffers */ size_t i; /* Number of elements filled in output buffers */ } H5ES_get_requests_ctx_t; /* Callback context for wait operations */ typedef struct H5ES_wait_ctx_t { H5ES_t *es; /* Event set being operated on */ uint64_t timeout; /* Timeout for wait operation (in ns) */ size_t *num_in_progress; /* Count of # of operations that have not completed */ hbool_t *op_failed; /* Flag to indicate an operation failed */ } H5ES_wait_ctx_t; /* Callback context for cancel operations */ typedef struct H5ES_cancel_ctx_t { H5ES_t *es; /* Event set being operated on */ size_t *num_not_canceled; /* Count of # of operations were not canceled */ hbool_t *op_failed; /* Flag to indicate an operation failed */ } H5ES_cancel_ctx_t; /* Callback context for get error info (gei) operations */ typedef struct H5ES_gei_ctx_t { H5ES_t *es; /* Event set being operated on */ size_t num_err_info; /* # of elements in err_info[] array */ size_t curr_err; /* Index of current error in array */ H5ES_err_info_t *curr_err_info; /* Pointer to current element in err_info[] array */ } H5ES_gei_ctx_t; /********************/ /* Package Typedefs */ /********************/ /********************/ /* Local Prototypes */ /********************/ static herr_t H5ES__close(H5ES_t *es); static herr_t H5ES__close_cb(void *es, void **request_token); static herr_t H5ES__insert(H5ES_t *es, H5VL_t *connector, void *request_token, const char *app_file, const char *app_func, unsigned app_line, const char *caller, const char *api_args); static int H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx); static herr_t H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev); static herr_t H5ES__op_complete(H5ES_t *es, H5ES_event_t *ev, H5VL_request_status_t ev_status); static int H5ES__wait_cb(H5ES_event_t *ev, void *_ctx); static int H5ES__cancel_cb(H5ES_event_t *ev, void *_ctx); static int H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx); static int H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx); /*********************/ /* Package Variables */ /*********************/ /*****************************/ /* Library Private Variables */ /*****************************/ /*******************/ /* Local Variables */ /*******************/ /* Event Set ID class */ static const H5I_class_t H5I_EVENTSET_CLS[1] = {{ H5I_EVENTSET, /* ID class value */ 0, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5ES__close_cb /* Callback routine for closing objects of this class */ }}; /* Declare a static free list to manage H5ES_t structs */ H5FL_DEFINE_STATIC(H5ES_t); /*------------------------------------------------------------------------- * Function: H5ES_init * * Purpose: Initialize the interface from some other layer. * * Return: Success: non-negative * Failure: negative *------------------------------------------------------------------------- */ herr_t H5ES_init(void) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Initialize the ID group for the event set IDs */ if (H5I_register_type(H5I_EVENTSET_CLS) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINIT, FAIL, "unable to initialize interface") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5ES_term_package * * Purpose: Terminate this interface. * * Return: Success: Positive if anything is done that might * affect other interfaces; zero otherwise. * Failure: Negative * * Programmer: Quincey Koziol * Monday, April 6, 2020 * *------------------------------------------------------------------------- */ int H5ES_term_package(void) { int n = 0; FUNC_ENTER_NOAPI_NOINIT_NOERR /* Destroy the event set ID group */ n += (H5I_dec_type_ref(H5I_EVENTSET) > 0); FUNC_LEAVE_NOAPI(n) } /* end H5ES_term_package() */ /*------------------------------------------------------------------------- * Function: H5ES__close_cb * * Purpose: Called when the ref count reaches zero on an event set's ID * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Monday, April 6, 2020 * *------------------------------------------------------------------------- */ static herr_t H5ES__close_cb(void *_es, void H5_ATTR_UNUSED **rt) { H5ES_t *es = (H5ES_t *)_es; /* The event set to close */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); /* Close the event set object */ if (H5ES__close(es) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CLOSEERROR, FAIL, "unable to close event set"); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__close_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__create * * Purpose: Private function to create an event set object * * Return: Success: Pointer to an event set struct * Failure: NULL * * Programmer: Quincey Koziol * Wednesday, April 8, 2020 * *------------------------------------------------------------------------- */ H5ES_t * H5ES__create(void) { H5ES_t *es = NULL; /* Pointer to event set */ H5ES_t *ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE /* Allocate space for new event set */ if (NULL == (es = H5FL_CALLOC(H5ES_t))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, NULL, "can't allocate event set object") /* Set the return value */ ret_value = es; done: if (!ret_value) if (es && H5ES__close(es) < 0) HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, NULL, "unable to free event set") FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__create() */ /*------------------------------------------------------------------------- * Function: H5ES__insert * * Purpose: Insert a request token into an event set * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Friday, December 11, 2020 * *------------------------------------------------------------------------- */ static herr_t H5ES__insert(H5ES_t *es, H5VL_t *connector, void *request_token, const char *app_file, const char *app_func, unsigned app_line, const char *caller, const char *api_args) { H5ES_event_t *ev = NULL; /* Event for request */ hbool_t ev_inserted = FALSE; /* Flag to indicate that event is in active list */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); /* Create new event */ if (NULL == (ev = H5ES__event_new(connector, request_token))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, FAIL, "can't create event object") /* Copy the app source information */ /* The 'app_func' & 'app_file' strings are statically allocated (by the compiler) * there's no need to duplicate them. */ ev->op_info.app_file_name = app_file; ev->op_info.app_func_name = app_func; ev->op_info.app_line_num = app_line; /* Set the event's operation counter */ ev->op_info.op_ins_count = es->op_counter++; /* Set the event's timestamp & execution time */ ev->op_info.op_ins_ts = H5_now_usec(); ev->op_info.op_exec_ts = UINT64_MAX; ev->op_info.op_exec_time = UINT64_MAX; /* Copy the API routine's name & arguments */ /* The 'caller' string is also statically allocated (by the compiler) * there's no need to duplicate it. */ ev->op_info.api_name = caller; assert(ev->op_info.api_args == NULL); if (api_args && NULL == (ev->op_info.api_args = H5MM_xstrdup(api_args))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy API routine arguments") /* Append fully initialized event onto the event set's 'active' list */ H5ES__list_append(&es->active, ev); ev_inserted = TRUE; /* Invoke the event set's 'insert' callback, if present */ if (es->ins_func) if ((es->ins_func)(&ev->op_info, es->ins_ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'insert' callback for event set failed") done: /* Release resources on error */ if (ret_value < 0) if (ev) { if (ev_inserted) H5ES__list_remove(&es->active, ev); if (H5ES__event_free(ev) < 0) HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "unable to release event") } FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__insert() */ /*------------------------------------------------------------------------- * Function: H5ES_insert * * Purpose: Insert a request token into an event set * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Wednesday, April 8, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES_insert(hid_t es_id, H5VL_t *connector, void *token, const char *caller, const char *caller_args, ...) { H5ES_t *es = NULL; /* Event set for the operation */ const char *app_file; /* Application source file name */ const char *app_func; /* Application source function name */ unsigned app_line; /* Application source line number */ H5RS_str_t *rs = NULL; /* Ref-counted string to compose formatted argument string in */ const char *api_args; /* Pointer to api_args string from ref-counted string */ va_list ap; /* Varargs for caller */ hbool_t arg_started = FALSE; /* Whether the va_list has been started */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ assert(connector); assert(token); assert(caller); assert(caller_args); /* Get event set */ if (NULL == (es = (H5ES_t *)H5I_object_verify(es_id, H5I_EVENTSET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event set") /* Check for errors in event set */ if (es->err_occurred) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations") /* Start working on the API routines arguments */ va_start(ap, caller_args); arg_started = TRUE; /* Copy the app source information */ (void)va_arg(ap, char *); /* Toss the 'app_file' parameter name */ app_file = va_arg(ap, char *); (void)va_arg(ap, char *); /* Toss the 'app_func' parameter name */ app_func = va_arg(ap, char *); (void)va_arg(ap, char *); /* Toss the 'app_line' parameter name */ app_line = va_arg(ap, unsigned); /* Create the string for the API routine's arguments */ if (NULL == (rs = H5RS_create(NULL))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't allocate ref-counted string") /* Copy the string for the API routine's arguments */ /* (skip the six characters from the app's file, function and line # arguments) */ assert(0 == HDstrncmp(caller_args, "*s*sIu", 6)); if (H5_trace_args(rs, caller_args + 6, ap) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, FAIL, "can't create formatted API arguments") if (NULL == (api_args = H5RS_get_str(rs))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't get pointer to formatted API arguments") /* Insert the operation into the event set */ if (H5ES__insert(es, connector, token, app_file, app_func, app_line, caller, api_args) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations") done: /* Clean up */ if (arg_started) va_end(ap); if (rs) H5RS_decr(rs); FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES_insert() */ /*------------------------------------------------------------------------- * Function: H5ES__insert_request * * Purpose: Directly insert a request token into an event set * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Friday, December 11, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES__insert_request(H5ES_t *es, H5VL_t *connector, void *token) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(connector); assert(token); /* Insert an 'anonymous' operation into the event set */ if (H5ES__insert(es, connector, token, NULL, NULL, 0, NULL, NULL) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__insert_request() */ /*------------------------------------------------------------------------- * Function: H5ES__get_requests_cb * * Purpose: Iterator callback for H5ES__get_events - adds the event to * the list. * * Return: SUCCEED / FAIL * * Programmer: Neil Fortner * Tuesday, November 23, 2021 * *------------------------------------------------------------------------- */ static int H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx) { H5ES_get_requests_ctx_t *ctx = (H5ES_get_requests_ctx_t *)_ctx; /* Callback context */ int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_PACKAGE_NOERR /* Sanity check */ assert(ev); assert(ctx); assert(ctx->i < ctx->array_len); /* Get the connector ID for the event */ if (ctx->connector_ids) ctx->connector_ids[ctx->i] = ev->request->connector->id; /* Get the request for the event */ if (ctx->requests) ctx->requests[ctx->i] = ev->request->data; /* Check if we've run out of room in the arrays */ if (++ctx->i == ctx->array_len) ret_value = H5_ITER_STOP; FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__get_requests_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__get_requests * * Purpose: Get all requests in an event set. * * Return: SUCCEED / FAIL * * Programmer: Neil Fortner * Tuesday, November 23, 2021 * *------------------------------------------------------------------------- */ herr_t H5ES__get_requests(H5ES_t *es, H5_iter_order_t order, hid_t *connector_ids, void **requests, size_t array_len) { H5ES_get_requests_ctx_t ctx; /* Callback context */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(array_len > 0); assert(requests || connector_ids); /* Set up context for iterator callbacks */ ctx.connector_ids = connector_ids; ctx.requests = requests; ctx.array_len = array_len; ctx.i = 0; /* Iterate over the events in the set */ if (H5ES__list_iterate(&es->active, order, H5ES__get_requests_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__get_requests() */ /*------------------------------------------------------------------------- * Function: H5ES__handle_fail * * Purpose: Handle a failed event * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Thursday, October 15, 2020 * *------------------------------------------------------------------------- */ static herr_t H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev) { FUNC_ENTER_PACKAGE_NOERR /* Sanity check */ assert(es); assert(es->active.head); assert(ev); /* Set error flag for event set */ es->err_occurred = TRUE; /* Remove event from normal list */ H5ES__list_remove(&es->active, ev); /* Append event onto the event set's error list */ H5ES__list_append(&es->failed, ev); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5ES__handle_fail() */ /*------------------------------------------------------------------------- * Function: H5ES__op_complete * * Purpose: Handle an operation completing * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Friday, December 11, 2020 * *------------------------------------------------------------------------- */ static herr_t H5ES__op_complete(H5ES_t *es, H5ES_event_t *ev, H5VL_request_status_t ev_status) { H5VL_request_specific_args_t vol_cb_args; /* Arguments to VOL callback */ hid_t err_stack_id = H5I_INVALID_HID; /* Error stack for failed operation */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(ev); assert(H5VL_REQUEST_STATUS_SUCCEED == ev_status || H5VL_REQUEST_STATUS_FAIL == ev_status || H5VL_REQUEST_STATUS_CANCELED == ev_status); /* Handle each form of event completion */ if (H5VL_REQUEST_STATUS_SUCCEED == ev_status || H5VL_REQUEST_STATUS_CANCELED == ev_status) { /* Invoke the event set's 'complete' callback, if present */ if (es->comp_func) { H5ES_status_t op_status; /* Status for complete callback */ /* Set appropriate info for callback */ if (H5VL_REQUEST_STATUS_SUCCEED == ev_status) { /* Translate status */ op_status = H5ES_STATUS_SUCCEED; /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_REQUEST_GET_EXEC_TIME; vol_cb_args.args.get_exec_time.exec_ts = &ev->op_info.op_exec_ts; vol_cb_args.args.get_exec_time.exec_time = &ev->op_info.op_exec_time; /* Retrieve the execution time info */ if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "unable to retrieve execution time info for operation") } else /* Translate status */ op_status = H5ES_STATUS_CANCELED; if ((es->comp_func)(&ev->op_info, op_status, H5I_INVALID_HID, es->comp_ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'complete' callback for event set failed") } /* end if */ /* Event success or cancellation */ if (H5ES__event_completed(ev, &es->active) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "unable to release completed event") } /* end if */ else if (H5VL_REQUEST_STATUS_FAIL == ev_status) { /* Invoke the event set's 'complete' callback, if present */ if (es->comp_func) { /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_REQUEST_GET_ERR_STACK; vol_cb_args.args.get_err_stack.err_stack_id = H5I_INVALID_HID; /* Retrieve the error stack for the operation */ if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "unable to retrieve error stack for operation") /* Set values */ err_stack_id = vol_cb_args.args.get_err_stack.err_stack_id; if ((es->comp_func)(&ev->op_info, H5ES_STATUS_FAIL, err_stack_id, es->comp_ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'complete' callback for event set failed") } /* end if */ /* Handle failure */ if (H5ES__handle_fail(es, ev) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, FAIL, "unable to handle failed event") } /* end else-if */ else HGOTO_ERROR(H5E_EVENTSET, H5E_BADVALUE, FAIL, "unknown event status?!?") done: /* Clean up */ if (H5I_INVALID_HID != err_stack_id) if (H5I_dec_ref(err_stack_id) < 0) HDONE_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack for failed operation") FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__op_complete() */ /*------------------------------------------------------------------------- * Function: H5ES__wait_cb * * Purpose: Common routine for testing / waiting on an operation * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Sunday, November 7, 2020 * *------------------------------------------------------------------------- */ static int H5ES__wait_cb(H5ES_event_t *ev, void *_ctx) { H5ES_wait_ctx_t *ctx = (H5ES_wait_ctx_t *)_ctx; /* Callback context */ H5VL_request_status_t ev_status = H5VL_REQUEST_STATUS_SUCCEED; /* Status from event's operation */ uint64_t start_time = 0, elapsed_time = 0; /* Start and elapsed times for waiting on an operation */ int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(ev); assert(ctx); /* Wait on the request */ if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) start_time = H5_now_usec(); if (H5VL_request_wait(ev->request, ctx->timeout, &ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTWAIT, H5_ITER_ERROR, "unable to test operation") if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) elapsed_time = H5_now_usec() - start_time; /* Check for status values that indicate we should break out of the loop */ if (ev_status == H5VL_REQUEST_STATUS_FAIL) { /* Handle event completion */ if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event") /* Record the error */ *ctx->op_failed = TRUE; /* Exit from the iteration */ ret_value = H5_ITER_STOP; } /* end if */ else if (ev_status == H5VL_REQUEST_STATUS_SUCCEED || ev_status == H5VL_REQUEST_STATUS_CANCELED) { /* Handle event completion */ if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event") } /* end else-if */ else if (ev_status == H5VL_REQUEST_STATUS_CANT_CANCEL) /* Should never get a status of 'can't cancel' back from test / wait operation */ HGOTO_ERROR(H5E_EVENTSET, H5E_BADVALUE, H5_ITER_ERROR, "received \"can't cancel\" status for operation") else { /* Sanity check */ assert(ev_status == H5VL_REQUEST_STATUS_IN_PROGRESS); /* Increment "in progress operation" counter */ (*ctx->num_in_progress)++; } /* end if */ /* Check for updateable timeout */ if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) { /* Update timeout for next operation */ if ((elapsed_time * 1000) > ctx->timeout) ctx->timeout = H5ES_WAIT_NONE; else ctx->timeout -= (elapsed_time * 1000); /* Convert us to ns */ } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__wait_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__wait * * Purpose: Wait for operations in event set to complete * * Note: Timeout value is in ns, and is for H5ES__wait itself. * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Monday, July 13, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, hbool_t *op_failed) { H5ES_wait_ctx_t ctx; /* Iterator callback context info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(num_in_progress); assert(op_failed); /* Set user's parameters to known values */ *num_in_progress = 0; *op_failed = FALSE; /* Set up context for iterator callbacks */ ctx.es = es; ctx.timeout = timeout; ctx.num_in_progress = num_in_progress; ctx.op_failed = op_failed; /* Iterate over the events in the set, waiting for them to complete */ if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__wait_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__wait() */ /*------------------------------------------------------------------------- * Function: H5ES__cancel_cb * * Purpose: Callback for canceling operations * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Thursday, December 10, 2020 * *------------------------------------------------------------------------- */ static int H5ES__cancel_cb(H5ES_event_t *ev, void *_ctx) { H5ES_cancel_ctx_t *ctx = (H5ES_cancel_ctx_t *)_ctx; /* Callback context */ H5VL_request_status_t ev_status = H5VL_REQUEST_STATUS_SUCCEED; /* Status from event's operation */ int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(ev); assert(ctx); /* Attempt to cancel the request */ if (H5VL_request_cancel(ev->request, &ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCANCEL, H5_ITER_ERROR, "unable to cancel operation") /* Check for status values that indicate we should break out of the loop */ if (ev_status == H5VL_REQUEST_STATUS_FAIL) { /* Handle event completion */ if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, H5_ITER_ERROR, "unable to handle failed event") /* Record the error */ *ctx->op_failed = TRUE; /* Exit from the iteration */ ret_value = H5_ITER_STOP; } /* end if */ else if (ev_status == H5VL_REQUEST_STATUS_SUCCEED) { /* Increment "not canceled" counter */ (*ctx->num_not_canceled)++; /* Handle event completion */ if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event") } /* end else-if */ else if (ev_status == H5VL_REQUEST_STATUS_CANT_CANCEL || ev_status == H5VL_REQUEST_STATUS_IN_PROGRESS) { /* Increment "not canceled" counter */ (*ctx->num_not_canceled)++; } /* end else-if */ else { /* Sanity check */ assert(ev_status == H5VL_REQUEST_STATUS_CANCELED); /* Handle event completion */ if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event") } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__cancel_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__cancel * * Purpose: Cancel operations in event set * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Thursday, December 10, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES__cancel(H5ES_t *es, size_t *num_not_canceled, hbool_t *op_failed) { H5ES_cancel_ctx_t ctx; /* Iterator callback context info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(num_not_canceled); assert(op_failed); /* Set user's parameters to known values */ *num_not_canceled = 0; *op_failed = FALSE; /* Set up context for iterator callbacks */ ctx.es = es; ctx.num_not_canceled = num_not_canceled; ctx.op_failed = op_failed; /* Iterate over the events in the set, attempting to cancel them */ if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__cancel_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__cancel() */ /*------------------------------------------------------------------------- * Function: H5ES__get_err_info_cb * * Purpose: Retrieve information about a failed operation * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Monday, November 11, 2020 * *------------------------------------------------------------------------- */ static int H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx) { H5VL_request_specific_args_t vol_cb_args; /* Arguments to VOL callback */ H5ES_gei_ctx_t *ctx = (H5ES_gei_ctx_t *)_ctx; /* Callback context */ int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(ev); assert(ctx); /* Copy operation info for event */ /* The 'app_func_name', 'app_file_name', and 'api_name' strings are statically allocated (by the compiler) * so there's no need to duplicate them internally, but they are duplicated * here, when they are given back to the user. */ if (NULL == (ctx->curr_err_info->api_name = H5MM_xstrdup(ev->op_info.api_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine name") if (NULL == (ctx->curr_err_info->api_args = H5MM_xstrdup(ev->op_info.api_args))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine arguments") if (NULL == (ctx->curr_err_info->app_file_name = H5MM_xstrdup(ev->op_info.app_file_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application file name") if (NULL == (ctx->curr_err_info->app_func_name = H5MM_xstrdup(ev->op_info.app_func_name))) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application function name") ctx->curr_err_info->app_line_num = ev->op_info.app_line_num; ctx->curr_err_info->op_ins_count = ev->op_info.op_ins_count; ctx->curr_err_info->op_ins_ts = ev->op_info.op_ins_ts; ctx->curr_err_info->op_exec_ts = ev->op_info.op_exec_ts; ctx->curr_err_info->op_exec_time = ev->op_info.op_exec_time; /* Set up VOL callback arguments */ vol_cb_args.op_type = H5VL_REQUEST_GET_ERR_STACK; vol_cb_args.args.get_err_stack.err_stack_id = H5I_INVALID_HID; /* Get error stack for event */ if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, H5_ITER_ERROR, "unable to retrieve error stack for operation") /* Set value */ ctx->curr_err_info->err_stack_id = vol_cb_args.args.get_err_stack.err_stack_id; /* Remove event from event set's failed list */ H5ES__list_remove(&ctx->es->failed, ev); /* Free event node */ if (H5ES__event_free(ev) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event") /* Advance to next element of err_info[] array */ ctx->curr_err++; ctx->curr_err_info++; /* Stop iteration if err_info[] array is full */ if (ctx->curr_err == ctx->num_err_info) ret_value = H5_ITER_STOP; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__get_err_info_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__get_err_info * * Purpose: Retrieve information about failed operations * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Friday, November 6, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], size_t *num_cleared) { H5ES_gei_ctx_t ctx; /* Iterator callback context info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); assert(num_err_info); assert(err_info); assert(num_cleared); /* Set up context for iterator callbacks */ ctx.es = es; ctx.num_err_info = num_err_info; ctx.curr_err = 0; ctx.curr_err_info = &err_info[0]; /* Iterate over the failed events in the set, copying their error info */ if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__get_err_info_cb, &ctx) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") /* Set # of failed events cleared from event set's failed list */ *num_cleared = ctx.curr_err; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__get_err_info() */ /*------------------------------------------------------------------------- * Function: H5ES__close_failed_cb * * Purpose: Release a failed event * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Monday, November 11, 2020 * *------------------------------------------------------------------------- */ static int H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx) { H5ES_t *es = (H5ES_t *)_ctx; /* Callback context */ int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(ev); assert(es); /* Remove event from event set's failed list */ H5ES__list_remove(&es->failed, ev); /* Free event node */ if (H5ES__event_free(ev) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__close_failed_cb() */ /*------------------------------------------------------------------------- * Function: H5ES__close * * Purpose: Destroy an event set object * * Return: SUCCEED / FAIL * * Programmer: Quincey Koziol * Monday, April 6, 2020 * *------------------------------------------------------------------------- */ herr_t H5ES__close(H5ES_t *es) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ assert(es); /* Fail if active operations still present */ if (H5ES__list_count(&es->active) > 0) HGOTO_ERROR( H5E_EVENTSET, H5E_CANTCLOSEOBJ, FAIL, "can't close event set while unfinished operations are present (i.e. wait on event set first)") /* Iterate over the failed events in the set, releasing them */ if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__close_failed_cb, (void *)es) < 0) HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed") /* Release the event set */ es = H5FL_FREE(H5ES_t, es); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5ES__close() */