/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Programmer: Robb Matzke * Friday, September 19, 1997 * */ /****************/ /* Module Setup */ /****************/ #define H5G_PACKAGE /*suppress error about including H5Gpkg */ /***********/ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ #include "H5Gpkg.h" /* Groups */ #include "H5HLprivate.h" /* Local Heaps */ #include "H5MMprivate.h" /* Memory management */ /****************/ /* Local Macros */ /****************/ /******************/ /* Local Typedefs */ /******************/ /* User data for finding link information from B-tree */ typedef struct { /* downward */ const char *name; /* Name to search for */ H5HL_t *heap; /* Local heap for group */ /* upward */ H5O_link_t *lnk; /* Caller's link location */ } H5G_stab_fnd_ud_t; /* Data passed through B-tree iteration for looking up a name by index */ typedef struct H5G_bt_it_gnbi_t { /* downward */ H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup */ H5HL_t *heap; /*symbol table heap */ /* upward */ char *name; /*member name to be returned */ } H5G_bt_it_gnbi_t; #ifndef H5_NO_DEPRECATED_SYMBOLS /* Data passed through B-tree iteration for looking up a type by index */ typedef struct H5G_bt_it_gtbi_t { /* downward */ H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup */ H5F_t *f; /* Pointer to file that symbol table is in */ hid_t dxpl_id; /* DXPL for operation */ /* upward */ H5G_obj_t type; /*member type to be returned */ } H5G_bt_it_gtbi_t; #endif /* H5_NO_DEPRECATED_SYMBOLS */ /* Data passed through B-tree iteration for looking up a link by index */ typedef struct H5G_bt_it_lbi_t { /* downward */ H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup */ H5HL_t *heap; /*symbol table heap */ /* upward */ H5O_link_t *lnk; /*link to be returned */ hbool_t found; /*whether we found the link */ } H5G_bt_it_lbi_t; /********************/ /* Package Typedefs */ /********************/ /********************/ /* Local Prototypes */ /********************/ /*********************/ /* Package Variables */ /*********************/ /*****************************/ /* Library Private Variables */ /*****************************/ /*******************/ /* Local Variables */ /*******************/ /*------------------------------------------------------------------------- * Function: H5G__stab_create_components * * Purpose: Creates the components for a new, empty, symbol table (name heap * and B-tree). The caller can specify an initial size for the * name heap. * * In order for the B-tree to operate correctly, the first * item in the heap is the empty string, and must appear at * heap offset zero. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Nov 7 2005 * *------------------------------------------------------------------------- */ herr_t H5G__stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t dxpl_id) { H5HL_t *heap = NULL; /* Pointer to local heap */ size_t name_offset; /* Offset of "" name */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* * Check arguments. */ HDassert(f); HDassert(stab); HDassert(size_hint > 0); /* Create the B-tree */ if(H5B_create(f, dxpl_id, H5B_SNODE, NULL, &(stab->btree_addr)/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree") /* Create symbol table private heap */ if(H5HL_create(f, dxpl_id, size_hint, &(stab->heap_addr)/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Insert name into the heap */ if((size_t)(-1) == (name_offset = H5HL_insert(f, dxpl_id, heap, (size_t)1, ""))) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert name into heap") /* * B-tree's won't work if the first name isn't at the beginning * of the heap. */ HDassert(0 == name_offset); done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_create_components() */ /*------------------------------------------------------------------------- * Function: H5G__stab_create * * Purpose: Creates a new empty symbol table (object header, name heap, * and B-tree). The caller can specify an initial size for the * name heap. The object header of the group is opened for * write access. * * In order for the B-tree to operate correctly, the first * item in the heap is the empty string, and must appear at * heap offset zero. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * matzke@llnl.gov * Aug 1 1997 * *------------------------------------------------------------------------- */ herr_t H5G__stab_create(H5O_loc_t *grp_oloc, hid_t dxpl_id, const H5O_ginfo_t *ginfo, H5O_stab_t *stab) { size_t heap_hint; /* Local heap size hint */ size_t size_hint; /* Local heap size hint */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* * Check arguments. */ HDassert(grp_oloc); HDassert(stab); /* Adjust the size hint, if necessary */ if(ginfo->lheap_size_hint == 0) heap_hint = 8 + /* "null" name inserted for B-tree */ (ginfo->est_num_entries * H5HL_ALIGN(ginfo->est_name_len + 1)) + /* estimated size of names for links, aligned for inserting into local heap */ H5HL_SIZEOF_FREE(grp_oloc->file); /* Free list entry in local heap */ else heap_hint = ginfo->lheap_size_hint; size_hint = MAX(heap_hint, H5HL_SIZEOF_FREE(grp_oloc->file) + 2); /* Go create the B-tree & local heap */ if(H5G__stab_create_components(grp_oloc->file, stab, size_hint, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create symbol table components") /* * Insert the symbol table message into the object header and the symbol * table entry. */ if(H5O_msg_create(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME, stab, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_create() */ /*------------------------------------------------------------------------- * Function: H5G__stab_insert_real * * Purpose: Insert a new symbol into a table. * The name of the new symbol is NAME and its symbol * table entry is OBJ_LNK. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@uiuc.edu * Nov 7 2005 * *------------------------------------------------------------------------- */ herr_t H5G__stab_insert_real(H5F_t *f, const H5O_stab_t *stab, const char *name, H5O_link_t *obj_lnk, H5O_type_t obj_type, const void *crt_info, hid_t dxpl_id) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5G_bt_ins_t udata; /* Data to pass through B-tree */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ HDassert(f); HDassert(stab); HDassert(name && *name); HDassert(obj_lnk); /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Initialize data to pass through B-tree */ udata.common.name = name; udata.common.heap = heap; udata.lnk = obj_lnk; udata.obj_type = obj_type; udata.crt_info = crt_info; /* Insert into symbol table */ if(H5B_insert(f, dxpl_id, H5B_SNODE, stab->btree_addr, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_insert_real() */ /*------------------------------------------------------------------------- * Function: H5G__stab_insert * * Purpose: Insert a new symbol into the table described by GRP_ENT in * file F. The name of the new symbol is NAME and its symbol * table entry is OBJ_ENT. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * matzke@llnl.gov * Aug 1 1997 * *------------------------------------------------------------------------- */ herr_t H5G__stab_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, H5O_type_t obj_type, const void *crt_info, hid_t dxpl_id) { H5O_stab_t stab; /* Symbol table message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ HDassert(grp_oloc && grp_oloc->file); HDassert(name && *name); HDassert(obj_lnk); /* Retrieve symbol table message */ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") if(H5G__stab_insert_real(grp_oloc->file, &stab, name, obj_lnk, obj_type, crt_info, dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "unable to insert the name") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_insert() */ /*------------------------------------------------------------------------- * Function: H5G__stab_remove * * Purpose: Remove NAME from a symbol table. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Thursday, September 17, 1998 * *------------------------------------------------------------------------- */ herr_t H5G__stab_remove(const H5O_loc_t *loc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r, const char *name) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5O_stab_t stab; /*symbol table message */ H5G_bt_rm_t udata; /*data to pass through B-tree */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE HDassert(loc && loc->file); HDassert(name && *name); /* Read in symbol table message */ if(NULL == H5O_msg_read(loc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(loc->file, dxpl_id, stab.heap_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Initialize data to pass through B-tree */ udata.common.name = name; udata.common.heap = heap; udata.grp_full_path_r = grp_full_path_r; /* Remove from symbol table */ if(H5B_remove(loc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_remove() */ /*------------------------------------------------------------------------- * Function: H5G__stab_remove_by_idx * * Purpose: Remove NAME from a symbol table, according to the name index. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, November 15, 2006 * *------------------------------------------------------------------------- */ herr_t H5G__stab_remove_by_idx(const H5O_loc_t *grp_oloc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r, H5_iter_order_t order, hsize_t n) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5O_stab_t stab; /* Symbol table message */ H5G_bt_rm_t udata; /* Data to pass through B-tree */ H5O_link_t obj_lnk; /* Object's link within group */ hbool_t lnk_copied = FALSE; /* Whether the link was copied */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE HDassert(grp_oloc && grp_oloc->file); /* Look up name of link to remove, by index */ if(H5G__stab_lookup_by_idx(grp_oloc, order, n, &obj_lnk, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get link information") lnk_copied = TRUE; /* Read in symbol table message */ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Initialize data to pass through B-tree */ udata.common.name = obj_lnk.name; udata.common.heap = heap; udata.grp_full_path_r = grp_full_path_r; /* Remove link from symbol table */ if(H5B_remove(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") /* Reset the link information, if we have a copy */ if(lnk_copied) H5O_msg_reset(H5O_LINK_ID, &obj_lnk); FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_remove_by_idx() */ /*------------------------------------------------------------------------- * Function: H5G__stab_delete * * Purpose: Delete entire symbol table information from file * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Thursday, March 20, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5G__stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5G_bt_rm_t udata; /*data to pass through B-tree */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE HDassert(f); HDassert(stab); HDassert(H5F_addr_defined(stab->btree_addr)); HDassert(H5F_addr_defined(stab->heap_addr)); /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC_WRITE))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Set up user data for B-tree deletion */ udata.common.name = NULL; udata.common.heap = heap; /* Delete entire B-tree */ if(H5B_delete(f, dxpl_id, H5B_SNODE, stab->btree_addr, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table B-tree") /* Release resources */ if(H5HL_unprotect(heap) < 0) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") heap = NULL; /* Delete local heap for names */ if(H5HL_delete(f, dxpl_id, stab->heap_addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table heap") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_delete() */ /*------------------------------------------------------------------------- * Function: H5G__stab_iterate * * Purpose: Iterate over the objects in a group * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Monday, October 3, 2005 * *------------------------------------------------------------------------- */ herr_t H5G__stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data) { H5HL_t *heap = NULL; /* Local heap for group */ H5O_stab_t stab; /* Info about symbol table */ H5G_link_table_t ltable = {0, NULL}; /* Link table */ herr_t ret_value; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(oloc); HDassert(op); /* Get the B-tree info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Check on iteration order */ /* ("native" iteration order is increasing for this link storage mechanism) */ if(order != H5_ITER_DEC) { H5G_bt_it_it_t udata; /* User data to pass to B-tree callback */ /* Build udata to pass through H5B_iterate() to H5G__node_iterate() */ udata.heap = heap; udata.skip = skip; udata.final_ent = last_lnk; udata.op = op; udata.op_data = op_data; /* Iterate over the group members */ if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_iterate, &udata)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); /* Check for too high of a starting index (ex post facto :-) */ /* (Skipping exactly as many entries as are in the group is currently an error) */ if(skip > 0 && skip >= *last_lnk) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") } /* end if */ else { H5G_bt_it_bt_t udata; /* User data to pass to B-tree callback */ /* Build udata to pass through H5B_iterate() to H5G__node_build_table() */ udata.alloc_nlinks = 0; udata.heap = heap; udata.ltable = <able; /* Iterate over the group members */ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_build_table, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to build link table") /* Check for skipping out of bounds */ if(skip > 0 && (size_t)skip >= ltable.nlinks) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") /* Sort link table in correct iteration order */ if(H5G__link_sort_table(<able, H5_INDEX_NAME, order) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages") /* Iterate over links in table */ if((ret_value = H5G__link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") if(ltable.lnks && H5G__link_release_table(<able) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_iterate() */ /*------------------------------------------------------------------------- * Function: H5G__stab_count * * Purpose: Count the # of links in a group * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Tuesday, September 6, 2005 * *------------------------------------------------------------------------- */ herr_t H5G__stab_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id) { H5O_stab_t stab; /* Info about symbol table */ herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(oloc); HDassert(num_objs); /* Reset the number of objects in the group */ *num_objs = 0; /* Get the B-tree info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Iterate over the group members */ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, num_objs) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_count() */ /*------------------------------------------------------------------------- * Function: H5G__stab_bh_size * * Purpose: Retrieve storage for btree and heap (1.6) * * Return: Non-negative on success/Negative on failure * * Programmer: Vailin Choi * June 25 2007 * *------------------------------------------------------------------------- */ herr_t H5G__stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, H5_ih_info_t *bh_info) { hsize_t snode_size; /* Symbol table node size */ H5B_info_t bt_info; /* B-tree node info */ herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(f); HDassert(stab); HDassert(bh_info); /* Set up user data for B-tree iteration */ snode_size = 0; /* Get the B-tree & symbol table node size info */ if(H5B_get_info(f, dxpl_id, H5B_SNODE, stab->btree_addr, &bt_info, H5G__node_iterate_size, &snode_size) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "iteration operator failed") /* Add symbol table & B-tree node sizes to index info */ bh_info->index_size += snode_size + bt_info.size; /* Get the size of the local heap for the group */ if(H5HL_heapsize(f, dxpl_id, stab->heap_addr, &(bh_info->heap_size)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "iteration operator failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_bh_size() */ /*------------------------------------------------------------------------- * Function: H5G_stab_get_name_by_idx_cb * * Purpose: Callback for B-tree iteration 'by index' info query to * retrieve the name of a link * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Nov 7, 2006 * *------------------------------------------------------------------------- */ static herr_t H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata) { H5G_bt_it_gnbi_t *udata = (H5G_bt_it_gnbi_t *)_udata; size_t name_off; /* Offset of name in heap */ const char *name; /* Pointer to name string in heap */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Sanity check */ HDassert(ent); HDassert(udata && udata->heap); /* Get name offset in heap */ name_off = ent->name_off; name = (const char *)H5HL_offset_into(udata->heap, name_off); HDassert(name); udata->name = H5MM_strdup(name); HDassert(udata->name); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_stab_get_name_by_idx_cb */ /*------------------------------------------------------------------------- * Function: H5G__stab_get_name_by_idx * * Purpose: Returns the name of objects in the group by giving index. * * Return: Success: Non-negative, length of name * Failure: Negative * * Programmer: Raymond Lu * Nov 20, 2002 * *------------------------------------------------------------------------- */ ssize_t H5G__stab_get_name_by_idx(const H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5O_stab_t stab; /* Info about local heap & B-tree */ H5G_bt_it_gnbi_t udata; /* Iteration information */ hbool_t udata_valid = FALSE; /* Whether iteration information is valid */ ssize_t ret_value; /* Return value */ /* Portably clear udata struct (before FUNC_ENTER) */ HDmemset(&udata, 0, sizeof(udata)); FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(oloc); /* Get the B-tree & local heap info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Remap index for decreasing iteration order */ if(order == H5_ITER_DEC) { hsize_t nlinks = 0; /* Number of links in group */ /* Iterate over the symbol table nodes, to count the links */ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, &nlinks) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed") /* Map decreasing iteration order index to increasing iteration order index */ n = nlinks - (n + 1); } /* end if */ /* Set iteration information */ udata.common.idx = n; udata.common.num_objs = 0; udata.common.op = H5G_stab_get_name_by_idx_cb; udata.heap = heap; udata.name = NULL; udata_valid = TRUE; /* Iterate over the group members */ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed") /* If we don't know the name now, we almost certainly went out of bounds */ if(udata.name == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound") /* Get the length of the name */ ret_value = (ssize_t)HDstrlen(udata.name); /* Copy the name into the user's buffer, if given */ if(name) { HDstrncpy(name, udata.name, MIN((size_t)(ret_value + 1), size)); if((size_t)ret_value >= size) name[size - 1]='\0'; } /* end if */ done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") /* Free the duplicated name */ if(udata_valid && udata.name != NULL) H5MM_xfree(udata.name); FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_get_name_by_idx() */ /*------------------------------------------------------------------------- * Function: H5G_stab_lookup_cb * * Purpose: B-tree 'find' callback to retrieve location for an object * * Return: Success: Non-negative * * Failure: Negative * * Programmer: Quincey Koziol * Sep 20, 2005 * *------------------------------------------------------------------------- */ static herr_t H5G_stab_lookup_cb(const H5G_entry_t *ent, void *_udata) { H5G_stab_fnd_ud_t *udata = (H5G_stab_fnd_ud_t *)_udata; /* 'User data' passed in */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check for setting link info */ if(udata->lnk) /* Convert the entry to a link */ if(H5G__ent_to_link(udata->lnk, udata->heap, ent, udata->name) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_lookup_cb() */ /*------------------------------------------------------------------------- * Function: H5G__stab_lookup * * Purpose: Look up an object relative to a group, using symbol table * * Return: Non-negative (TRUE/FALSE) on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Sep 20 2005 * *------------------------------------------------------------------------- */ htri_t H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */ H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */ H5O_stab_t stab; /* Symbol table message */ htri_t ret_value; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ HDassert(grp_oloc && grp_oloc->file); HDassert(name && *name); HDassert(lnk); /* Retrieve the symbol table message for the group */ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Set up user data to pass to 'find' operation callback */ udata.name = name; udata.lnk = lnk; udata.heap = heap; /* Set up the user data for actual B-tree find operation */ bt_udata.common.name = name; bt_udata.common.heap = heap; bt_udata.op = H5G_stab_lookup_cb; bt_udata.op_data = &udata; /* Search the B-tree */ if((ret_value = H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_lookup() */ /*------------------------------------------------------------------------- * Function: H5G_stab_lookup_by_idx_cb * * Purpose: Callback for B-tree iteration 'by index' info query to * retrieve the link * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Nov 9, 2006 * *------------------------------------------------------------------------- */ static herr_t H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata) { H5G_bt_it_lbi_t *udata = (H5G_bt_it_lbi_t *)_udata; const char *name; /* Pointer to name string in heap */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(ent); HDassert(udata && udata->heap); /* Get a pointer to the link name */ name = (const char *)H5HL_offset_into(udata->heap, ent->name_off); HDassert(name); /* Convert the entry to a link */ if(H5G__ent_to_link(udata->lnk, udata->heap, ent, name) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link") udata->found = TRUE; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_lookup_by_idx_cb */ /*------------------------------------------------------------------------- * Function: H5G__stab_lookup_by_idx * * Purpose: Look up an object in a group, according to the name index * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@hdfgroup.org * Nov 7 2006 * *------------------------------------------------------------------------- */ herr_t H5G__stab_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id) { H5HL_t *heap = NULL; /* Pointer to local heap */ H5G_bt_it_lbi_t udata; /* Iteration information */ H5O_stab_t stab; /* Symbol table message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* check arguments */ HDassert(grp_oloc && grp_oloc->file); HDassert(lnk); /* Get the B-tree & local heap info */ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap") /* Remap index for decreasing iteration order */ if(order == H5_ITER_DEC) { hsize_t nlinks = 0; /* Number of links in group */ /* Iterate over the symbol table nodes, to count the links */ if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, &nlinks) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed") /* Map decreasing iteration order index to increasing iteration order index */ n = nlinks - (n + 1); } /* end if */ /* Set iteration information */ udata.common.idx = n; udata.common.num_objs = 0; udata.common.op = H5G_stab_lookup_by_idx_cb; udata.heap = heap; udata.lnk = lnk; udata.found = FALSE; /* Iterate over the group members */ if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed") /* If we didn't find the link, we almost certainly went out of bounds */ if(!udata.found) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound") done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_lookup_by_idx() */ #ifndef H5_STRICT_FORMAT_CHECKS /*------------------------------------------------------------------------- * Function: H5G__stab_valid * * Purpose: Verify that a group's symbol table message is valid. If * provided, the addresses in alt_stab will be tried if the * addresses in the group's stab message are invalid, and * the stab message will be updated if necessary. * * NOTE: This function is only called when strict format * checks are disabled. This is so that, when strict * format checks are enabled, errors in the symbol table * messages are not fixed by this function and are instead * reported by the library. * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * nfortne2@hdfgroup.org * Mar 17, 2009 * *------------------------------------------------------------------------- */ herr_t H5G__stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab) { H5O_stab_t stab; /* Current symbol table */ H5HL_t *heap = NULL; /* Pointer to local heap */ hbool_t changed = FALSE; /* Whether stab has been modified */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Read the symbol table message */ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message"); /* Check if the symbol table message's b-tree address is valid */ if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) { /* Address is invalid, try the b-tree address in the alternate symbol * table message */ if(!alt_stab || H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, alt_stab->btree_addr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to locate b-tree") else { /* The alternate symbol table's b-tree address is valid. Adjust the * symbol table message in the group. */ stab.btree_addr = alt_stab->btree_addr; changed = TRUE; } /* end else */ } /* end if */ /* Check if the symbol table message's heap address is valid */ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) { /* Address is invalid, try the heap address in the alternate symbol * table message */ if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap") else { /* The alternate symbol table's heap address is valid. Adjust the * symbol table message in the group. */ stab.heap_addr = alt_stab->heap_addr; changed = TRUE; } /* end else */ } /* end if */ /* Update the symbol table message and clear errors if necessary */ if(changed) { H5E_clear_stack(NULL); if(H5O_msg_write(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME | H5O_UPDATE_FORCE, &stab, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to correct symbol table message") } /* end if */ done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_valid */ #endif /* H5_STRICT_FORMAT_CHECKS */ #ifndef H5_NO_DEPRECATED_SYMBOLS /*------------------------------------------------------------------------- * Function: H5G_stab_get_type_by_idx_cb * * Purpose: Callback for B-tree iteration 'by index' info query to * retrieve the type of an object * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Nov 7, 2006 * *------------------------------------------------------------------------- */ static herr_t H5G_stab_get_type_by_idx_cb(const H5G_entry_t *ent, void *_udata) { H5G_bt_it_gtbi_t *udata = (H5G_bt_it_gtbi_t *)_udata; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(ent); HDassert(udata); /* Check for a soft link */ switch(ent->type) { case H5G_CACHED_SLINK: udata->type = H5G_LINK; break; case H5G_CACHED_ERROR: case H5G_NOTHING_CACHED: case H5G_CACHED_STAB: case H5G_NCACHED: default: { H5O_loc_t tmp_oloc; /* Temporary object location */ H5O_type_t obj_type; /* Type of object at location */ /* Build temporary object location */ tmp_oloc.file = udata->f; HDassert(H5F_addr_defined(ent->header)); tmp_oloc.addr = ent->header; /* Get the type of the object */ if(H5O_obj_type(&tmp_oloc, &obj_type, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object type") udata->type = H5G_map_obj_type(obj_type); } break; } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_get_type_by_idx_cb */ /*------------------------------------------------------------------------- * Function: H5G__stab_get_type_by_idx * * Purpose: Private function for H5Gget_objtype_by_idx. * Returns the type of objects in the group by giving index. * * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) * * Failure: UNKNOWN * * Programmer: Raymond Lu * Nov 20, 2002 * *------------------------------------------------------------------------- */ H5G_obj_t H5G__stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) { H5O_stab_t stab; /* Info about local heap & B-tree */ H5G_bt_it_gtbi_t udata; /* User data for B-tree callback */ H5G_obj_t ret_value; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity check */ HDassert(oloc); /* Get the B-tree & local heap info */ if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address") /* Set iteration information */ udata.common.idx = idx; udata.common.num_objs = 0; udata.common.op = H5G_stab_get_type_by_idx_cb; udata.f = oloc->file; udata.dxpl_id = dxpl_id; udata.type = H5G_UNKNOWN; /* Iterate over the group members */ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed") /* If we don't know the type now, we almost certainly went out of bounds */ if(udata.type == H5G_UNKNOWN) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound") /* Set the return value */ ret_value = udata.type; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__stab_get_type_by_idx() */ #endif /* H5_NO_DEPRECATED_SYMBOLS */