From c35a2ad6b2fe19c8016469041f15009dd6e6118e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 14 Nov 2006 10:42:31 -0500 Subject: [svn-r12910] Description: More progress toward getting H5Ldelete_by_idx to work fully - can now delete by index in compact group (but not dense groups or "old-style" groups yet). Need to go write a v2 B-tree routine to delete from the B-tree by index before the dense storage will work properly... Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2) --- src/H5Gcompact.c | 73 ++++++++++++++--- src/H5Gdense.c | 121 +++++++++++++++++++++++++++- src/H5Gobj.c | 242 +++++++++++++++++++++++++++++++++++++++++-------------- src/H5Gpkg.h | 8 ++ src/H5L.c | 17 +--- test/links.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 590 insertions(+), 84 deletions(-) diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 4f0f895..19f0827 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -336,10 +336,10 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_compact_remove_cb + * Function: H5G_compact_remove_common_cb * - * Purpose: Callback routine for deleting 'link' message for a particular - * name. + * Purpose: Common callback routine for deleting 'link' message for a + * particular name. * * Return: Non-negative on success/Negative on failure * @@ -350,13 +350,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_compact_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) +H5G_compact_remove_common_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) { const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ H5G_iter_rm_t *udata = (H5G_iter_rm_t *)_udata; /* 'User data' passed in */ herr_t ret_value = H5O_ITER_CONT; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_compact_remove_cb) + FUNC_ENTER_NOAPI_NOINIT(H5G_compact_remove_common_cb) /* check arguments */ HDassert(lnk); @@ -374,7 +374,7 @@ H5G_compact_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_compact_remove_cb() */ +} /* end H5G_compact_remove_common_cb() */ /*------------------------------------------------------------------------- @@ -408,7 +408,7 @@ H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id, H5RS_str_t *grp_full_pa udata.name = name; /* Iterate over the link messages to delete the right one */ - if(H5O_remove_op(oloc, H5O_LINK_ID, H5O_FIRST, H5G_compact_remove_cb, &udata, TRUE, dxpl_id) < 0) + if(H5O_remove_op(oloc, H5O_LINK_ID, H5O_FIRST, H5G_compact_remove_common_cb, &udata, TRUE, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link message") done: @@ -417,6 +417,60 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_compact_remove_by_idx + * + * Purpose: Remove link from group, according to an index order. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, November 14, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n) +{ + H5G_link_table_t ltable = {0, NULL};/* Link table */ + H5G_iter_rm_t udata; /* Data to pass through OH iteration */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_compact_remove_by_idx, FAIL) + + HDassert(oloc && oloc->file); + HDassert(linfo); + + /* Build table of all link messages, sorted according to desired order */ + if(H5G_compact_build_table(oloc, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index out of bound") + + /* Initialize data to pass through object header iteration */ + udata.file = oloc->file; + udata.dxpl_id = dxpl_id; + udata.grp_full_path_r = grp_full_path_r; + udata.name = ltable.lnks[n].name; + + /* Iterate over the link messages to delete the right one */ + if(H5O_remove_op(oloc, H5O_LINK_ID, H5O_FIRST, H5G_compact_remove_common_cb, &udata, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link message") + +done: + /* Release link table */ + if(ltable.lnks) + if(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_compact_remove_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5G_compact_iterate * * Purpose: Iterate over the links in a group @@ -589,8 +643,8 @@ herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk) { - H5G_link_table_t ltable = {0, NULL}; /* Link table */ - herr_t ret_value = SUCCEED; /* Return value */ + H5G_link_table_t ltable = {0, NULL};/* Link table */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_compact_lookup_by_idx, FAIL) @@ -614,7 +668,6 @@ H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *lin done: /* Release link table */ if(ltable.lnks) - /* Free link table information */ if(H5G_link_release_table(<able) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") diff --git a/src/H5Gdense.c b/src/H5Gdense.c index c4cb814..b2269f4 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -1433,7 +1433,7 @@ H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, const char *name) { H5HF_t *fheap = NULL; /* Fractal heap handle */ - H5G_bt2_ud_rem_t udata; /* User data for v2 B-tree record removal */ + H5G_bt2_ud_rem_t udata; /* User data for v2 B-tree record removal */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_dense_remove, FAIL) @@ -1480,6 +1480,125 @@ done: /*------------------------------------------------------------------------- + * Function: H5G_dense_remove_by_idx + * + * Purpose: Remove a link from the dense storage of a group, according to + * to the offset in an indexed order + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5RS_str_t *grp_full_path_r, H5L_index_t idx_type, H5_iter_order_t order, + hsize_t n) +{ + const H5B2_class_t *bt2_class = NULL; /* Class of v2 B-tree */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_dense_remove_by_idx, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Determine the address of the index to use */ + if(idx_type == H5L_INDEX_NAME) { + /* Check if "native" order is OK - since names are hashed, getting them + * in strictly increasing or decreasing order requires building a + * table and sorting it. + */ + if(order == H5_ITER_NATIVE) { + bt2_addr = linfo->name_bt2_addr; + bt2_class = H5G_BT2_NAME; + HDassert(H5F_addr_defined(bt2_addr)); + } /* end if */ + else + bt2_addr = HADDR_UNDEF; + } /* end if */ + else { + HDassert(idx_type == H5L_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links, a table will be built. + */ + bt2_addr = linfo->corder_bt2_addr; + bt2_class = H5G_BT2_CORDER; + } /* end else */ + + /* If there is an index defined for the field, use it */ + if(H5F_addr_defined(bt2_addr)) { + H5HF_t *fheap; /* Fractal heap handle */ + H5G_bt2_ud_rem_t udata; /* User data for v2 B-tree record removal */ + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->link_fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + +#ifdef NOT_YET + /* Set up the user data for the v2 B-tree 'record remove' callback */ + udata.common.f = f; + udata.common.dxpl_id = dxpl_id; + udata.common.fheap = fheap; + udata.common.name = name; + udata.common.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); + udata.common.found_op = NULL; + udata.common.found_op_data = NULL; + udata.adj_link = TRUE; + udata.rem_from_fheap = TRUE; + udata.rem_from_corder_index = H5F_addr_defined(linfo->corder_bt2_addr); + udata.corder_bt2_addr = linfo->corder_bt2_addr; + udata.grp_full_path_r = grp_full_path_r; + udata.replace_names = TRUE; + + /* Remove the record from the name index v2 B-tree */ + if(H5B2_remove(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, + &udata, H5G_dense_remove_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from name index v2 B-tree") +#else /* NOT_YET */ +HDfprintf(stderr, "%s: Removing by index in dense storage w/index not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "removing by index in dense storage w/index not supported yet") +#endif /* NOT_YET */ + + /* Close heap */ + if(H5HF_close(fheap, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + } /* end if */ + else { /* Otherwise, we need to build a table of the links and sort it */ + H5G_link_table_t ltable; /* Table of links */ + + /* Build the table of links for this group */ + if(H5G_dense_build_table(f, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") + + /* Remove the appropriate link from the dense storage */ + if(H5G_dense_remove(f, dxpl_id, linfo, grp_full_path_r, ltable.lnks[n].name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from dense storage") + + /* Free link table information */ + if(H5G_link_release_table(<able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_remove_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: H5G_dense_delete * * Purpose: Delete the dense storage for a group diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 5e68d6b..6db0060 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -90,6 +90,8 @@ typedef struct { /********************/ static herr_t H5G_obj_compact_to_dense_cb(const void *_mesg, unsigned idx, void *_udata); +static herr_t H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, + hid_t dxpl_id); /*********************/ @@ -808,11 +810,104 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_obj_remove + * Function: H5G_obj_remove_update_linfo + * + * Purpose: Update the link info after removing a link from a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Nov 14, 2006 * - * Purpose: Remove an object from a group. + *------------------------------------------------------------------------- + */ +static herr_t +H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_obj_remove_update_linfo) + + /* Sanity check */ + HDassert(oloc); + HDassert(linfo); + + /* Decrement # of links in group */ + linfo->nlinks--; + + /* Reset the creation order min/max if there's no more links in group */ + if(linfo->nlinks == 0) + linfo->min_corder = linfo->max_corder = 0; + + /* Check for transitioning out of dense storage, if we are using it */ + if(H5F_addr_defined(linfo->link_fheap_addr)) { + /* Check if there's no more links */ + if(linfo->nlinks == 0) { + /* Delete the dense storage */ + if(H5G_dense_delete(oloc->file, dxpl_id, linfo, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage") + } /* end if */ + /* Check for switching back to compact storage */ + else { + H5O_ginfo_t ginfo; /* Group info message */ + + /* Get the group info */ + if(NULL == H5O_read(oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* Check if we should switch from dense storage back to link messages */ + if(linfo->nlinks < ginfo.min_dense) { + H5G_link_table_t ltable; /* Table of links */ + hbool_t can_convert = TRUE; /* Whether converting to link messages is possible */ + size_t u; /* Local index */ + + /* Build the table of links for this group */ + if(H5G_dense_build_table(oloc->file, dxpl_id, linfo, H5L_INDEX_NAME, H5_ITER_NATIVE, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") + + /* Inspect links in table for ones that can't be converted back + * into link message form (currently only links which can't fit + * into an object header message) + */ + for(u = 0; u < linfo->nlinks; u++) + if(H5O_mesg_size(H5O_LINK_ID, oloc->file, &(ltable.lnks[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) { + can_convert = FALSE; + break; + } /* end if */ + + /* If ok, insert links as link messages */ + if(can_convert) { + /* Insert link messages into group */ + for(u = 0; u < linfo->nlinks; u++) + if(H5O_modify(oloc, H5O_LINK_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, &(ltable.lnks[u]), dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") + + /* Remove the dense storage */ + if(H5G_dense_delete(oloc->file, dxpl_id, linfo, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage") + } /* end if */ + + /* Free link table information */ + if(H5G_link_release_table(<able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + } /* end if */ + } /* end else */ + } /* end if */ + + /* Update link info in the object header */ + if(H5O_modify(oloc, H5O_LINFO_ID, 0, 0, H5O_UPDATE_TIME, linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_remove_update_linfo() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_remove * - * Note: Needs to hand up the type of the object removed + * Purpose: Remove a link from a group. * * Return: Success: Non-negative * Failure: Negative @@ -866,66 +961,95 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h /* Update link info for a new-style group */ if(!use_old_format) { - /* Decrement # of links in group */ - linfo.nlinks--; + if(H5G_obj_remove_update_linfo(oloc, &linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTUPDATE, FAIL, "unable to update link info") + } /* end if */ - /* Check for transitioning out of dense storage, if we are using it */ - if(H5F_addr_defined(linfo.link_fheap_addr)) { - /* If there's no more links, delete the dense storage */ - if(linfo.nlinks == 0) { - if(H5G_dense_delete(oloc->file, dxpl_id, &linfo, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage") - } /* end if */ - /* Check for switching back to compact storage */ - else { - H5O_ginfo_t ginfo; /* Group info message */ - - /* Get the group info */ - if(NULL == H5O_read(oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") - - /* Check if we should switch from dense storage back to link messages */ - if(linfo.nlinks < ginfo.min_dense) { - H5G_link_table_t ltable; /* Table of links */ - hbool_t can_convert = TRUE; /* Whether converting to link messages is possible */ - size_t u; /* Local index */ - - /* Build the table of links for this group */ - if(H5G_dense_build_table(oloc->file, dxpl_id, &linfo, H5L_INDEX_NAME, H5_ITER_NATIVE, <able) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") - - /* Inspect links in table for ones that can't be converted back - * into link message form (currently only links which can't fit - * into an object header message) - */ - for(u = 0; u < linfo.nlinks; u++) - if(H5O_mesg_size(H5O_LINK_ID, oloc->file, &(ltable.lnks[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) { - can_convert = FALSE; - break; - } /* end if */ - - /* If ok, insert links as link messages */ - if(can_convert) { - /* Insert link messages into group */ - for(u = 0; u < linfo.nlinks; u++) - if(H5O_modify(oloc, H5O_LINK_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, &(ltable.lnks[u]), dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") - - /* Remove the dense storage */ - if(H5G_dense_delete(oloc->file, dxpl_id, &linfo, FALSE) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage") - } /* end if */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_remove() */ - /* Free link table information */ - if(H5G_link_release_table(<able) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") - } /* end if */ - } /* end else */ + +/*------------------------------------------------------------------------- + * Function: H5G_obj_remove_by_idx + * + * Purpose: Remove a link from a group, according to the order within an index. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Nov 14, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id) +{ + H5O_linfo_t linfo; /* Link info message */ + hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_remove_by_idx, FAIL) + + /* Sanity check */ + HDassert(grp_oloc && grp_oloc->file); + + /* Attempt to get the link info for this group */ + if(H5O_read(grp_oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) { + /* Check for creation order tracking, if creation order index lookup requested */ + if(idx_type == H5L_INDEX_CRT_ORDER) { + H5O_ginfo_t ginfo; /* Group info message */ + + /* Get group info message, to see if creation order is tracked for links in this group */ + if(NULL == H5O_read(grp_oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info message for group") + + /* Check if creation order is tracked */ + if(!ginfo.track_corder) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group") } /* end if */ - /* Update link info in the object header */ - if(H5O_modify(oloc, H5O_LINFO_ID, 0, 0, H5O_UPDATE_TIME, &linfo, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message") + /* Using the new format for groups */ + use_old_format = FALSE; + + /* Check for dense or compact storage */ + if(H5F_addr_defined(linfo.link_fheap_addr)) { + /* Remove object from the dense link storage */ + if(H5G_dense_remove_by_idx(grp_oloc->file, dxpl_id, &linfo, grp_full_path_r, idx_type, order, n) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object") + } /* end if */ + else { + /* Remove object from compact link storage */ + if(H5G_compact_remove_by_idx(grp_oloc, dxpl_id, &linfo, grp_full_path_r, idx_type, order, n) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object") + } /* end else */ + } /* end if */ + else { + /* Clear error stack from not finding the link info message */ + H5E_clear_stack(NULL); +HDfprintf(stderr, "%s: Removing by index in symbol table not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "removing by index in symbol table not supported yet") + + /* Can only perform name lookups on groups with symbol tables */ + if(idx_type != H5L_INDEX_NAME) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") + + /* Using the old format for groups */ + use_old_format = TRUE; + +#ifdef QAK + /* Remove object from the symbol table */ + if(H5G_stab_remove_by_idx(grp_oloc, dxpl_id, grp_full_path_r, idx_type, order, n) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object") +#endif /* QAK */ + } /* end else */ + + /* Update link info for a new-style group */ + if(!use_old_format) { + if(H5G_obj_remove_update_linfo(grp_oloc, &linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTUPDATE, FAIL, "unable to update link info") } /* end if */ done: diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 6aabb33..84d03a8 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -435,6 +435,9 @@ H5_DLL H5G_obj_t H5G_compact_get_type_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, hsize_t idx); H5_DLL herr_t H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r, const char *name); +H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n); H5_DLL herr_t H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_iter_order_t order, hid_t gid, hbool_t lib_internal, int skip, int *last_obj, H5G_link_iterate_t op, void *op_data); @@ -465,6 +468,9 @@ H5_DLL H5G_obj_t H5G_dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hsize_t idx); H5_DLL herr_t H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, const char *name); +H5_DLL herr_t H5G_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, + const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5L_index_t idx_type, + H5_iter_order_t order, hsize_t n); H5_DLL herr_t H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link); @@ -484,6 +490,8 @@ H5_DLL H5G_obj_t H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id); H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, + H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id); H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5L_index_t idx_type, diff --git a/src/H5L.c b/src/H5L.c index 7f27c4a..f5281ee 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -2049,8 +2049,6 @@ H5L_delete_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, H5G_own_loc_t *own_loc/*out*/) { H5L_trav_gvbi_t *udata = (H5L_trav_gvbi_t *)_udata; /* User data passed in */ - H5O_link_t grp_lnk; /* Link within group */ - hbool_t lnk_copied = FALSE; /* Whether the link was copied */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5L_delete_by_idx_cb) @@ -2059,21 +2057,12 @@ H5L_delete_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, if(obj_loc == NULL) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist") - /* Query link */ - if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order, - udata->n, &grp_lnk, udata->dxpl_id) < 0) + /* Delete link */ + if(H5G_obj_remove_by_idx(obj_loc->oloc, obj_loc->path->full_path_r, + udata->idx_type, udata->order, udata->n, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found") - lnk_copied = TRUE; - - /* Retrieve the value for the link */ - if(H5L_get_val_real(&grp_lnk, udata->buf, udata->size) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't retrieve link value") done: - /* Reset the link information, if we have a copy */ - if(lnk_copied) - H5O_reset(H5O_LINK_ID, &grp_lnk); - /* Indicate that this callback didn't take ownership of the group * * location for the object */ *own_loc = H5G_OWN_NONE; diff --git a/test/links.c b/test/links.c index 0c1cae2..d4083ec 100644 --- a/test/links.c +++ b/test/links.c @@ -6210,6 +6210,20 @@ link_info_by_idx(hid_t fapl) if(link_info_by_idx_check(group_id, objname, (hsize_t)u, hard_link, use_index) < 0) TEST_ERROR } /* end for */ + /* Check for out of bound offset queries */ + H5E_BEGIN_TRY { + ret = H5Lget_info_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, &linfo, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + H5E_BEGIN_TRY { + ret = H5Lget_info_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)u, &linfo, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + H5E_BEGIN_TRY { + ret = H5Lget_name_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + /* Close the group */ if(H5Gclose(group_id) < 0) TEST_ERROR @@ -6407,6 +6421,203 @@ error: /*------------------------------------------------------------------------- + * Function: delete_by_idx + * + * Purpose: Create a group with creation order indices and test deleting + * links by index. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, November 14, 2006 + * + *------------------------------------------------------------------------- + */ +static int +delete_by_idx(hid_t fapl) +{ + hid_t file_id = (-1); /* File ID */ + hid_t group_id = (-1); /* Group ID */ + hid_t gcpl_id = (-1); /* Group creation property list ID */ + hbool_t use_index; /* Use index on creation order values */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + H5L_info_t linfo; /* Link info struct */ + char objname[NAME_BUF_SIZE]; /* Object name */ + char filename[NAME_BUF_SIZE];/* File name */ + char tmpname[NAME_BUF_SIZE]; /* Temporary link name */ + unsigned u; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Loop over using index for creation order value */ + for(use_index = FALSE; use_index <= TRUE; use_index++) { + if(use_index) + TESTING("deleting links by index w/creation order index") + else + TESTING("deleting links by index w/o creation order index") + + /* Create file */ + /* (with creation order tracking for the root group) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create group creation property list */ + if((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0) TEST_ERROR + + /* Set creation order tracking & indexing on group */ + if(use_index) + if(H5Pset_creation_order_index(gcpl_id, TRUE) < 0) TEST_ERROR + if(H5Pset_creation_order_tracking(gcpl_id, TRUE) < 0) TEST_ERROR + + /* Create group with creation order tracking on */ + if((group_id = H5Gcreate_expand(file_id, gcpl_id, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Llink(file_id, CORDER_GROUP_NAME, group_id, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Query the group creation properties */ + if(H5Pget_link_phase_change(gcpl_id, &max_compact, &min_dense) < 0) TEST_ERROR + + /* Check for deletion on empty group */ + H5E_BEGIN_TRY { + ret = H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + + /* Create several links, up to limit of compact form */ + for(u = 0; u < max_compact; u++) { + hid_t group_id2; /* Group ID */ + + /* Make name for link */ + sprintf(objname, "filler %02u", u); + + /* Create hard link, with group object */ + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + + /* Verify link information for new link */ + if(link_info_by_idx_check(group_id, objname, (hsize_t)u, TRUE, use_index) < 0) TEST_ERROR + } /* end for */ + + /* Verify state of group (compact) */ + if(H5G_has_links_test(group_id, NULL) != TRUE) TEST_ERROR + + /* Check for out of bound deletion */ + H5E_BEGIN_TRY { + ret = H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + + /* Delete links from compact group, from front, with creation order */ + for(u = 0; u < (max_compact - 1); u++) { + /* Delete first link in creation order */ + if(H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT) < 0) TEST_ERROR + + /* Make link nam for queries */ + sprintf(objname, "filler %02u", (u + 1)); + + /* Verify the link information for first link, in increasing creation order */ + HDmemset(&linfo, 0, sizeof(linfo)); + if(H5Lget_info_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &linfo, H5P_DEFAULT) < 0) TEST_ERROR + if(linfo.corder != (u + 1)) TEST_ERROR + + /* Verify the name for first link, in increasing creation order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + if(H5Lget_name_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR + if(HDstrcmp(objname, tmpname)) TEST_ERROR + } /* end for */ + + /* Delete last link in creation order */ + if(H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify state of group (empty) */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + +#ifdef NOT_YET + /* Create more links, to push group into dense form */ + for(u = 0; u < (max_compact * 2); u++) { + hid_t group_id2; /* Group ID */ + + /* Make name for link */ + sprintf(objname, "filler %02u", u); + + /* Create hard link, with group object */ + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + + /* Verify state of group (dense) */ + if(u >= max_compact) + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Verify link information for new link */ + if(link_info_by_idx_check(group_id, objname, (hsize_t)u, TRUE, use_index) < 0) TEST_ERROR + } /* end for */ + + /* Check for out of bound deletion */ + H5E_BEGIN_TRY { + ret = H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + + /* Delete links from dense group, from front, with creation order */ + for(u = 0; u < ((max_compact * 2) - 1); u++) { + /* Delete first link in creation order */ + if(H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT) < 0) TEST_ERROR + + /* Make link name for queries */ + sprintf(objname, "filler %02u", (u + 1)); + + /* Verify the link information for first link, in increasing creation order */ + HDmemset(&linfo, 0, sizeof(linfo)); + if(H5Lget_info_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &linfo, H5P_DEFAULT) < 0) TEST_ERROR + if(linfo.corder != (u + 1)) TEST_ERROR + + /* Verify the name for first link, in increasing creation order */ + HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE); + if(H5Lget_name_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR + if(HDstrcmp(objname, tmpname)) TEST_ERROR + } /* end for */ + + /* Delete last link in creation order */ + if(H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT) < 0) TEST_ERROR +#else /* NOT_YET */ +HDfprintf(stderr, "Finish deletion tests!\n"); +#endif /* NOT_YET */ + + /* Verify state of group (empty) */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) == TRUE) TEST_ERROR + + /* Check for deletion on empty group again */ + H5E_BEGIN_TRY { + ret = H5Ldelete_by_idx(group_id, ".", H5L_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, H5P_DEFAULT); + } H5E_END_TRY; + if(ret >= 0) TEST_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) TEST_ERROR + + /* Close the group creation property list */ + if(H5Pclose(gcpl_id) < 0) TEST_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + PASSED(); + } /* end for */ + + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(gcpl_id); + H5Gclose(group_id); + H5Fclose(file_id); + } H5E_END_TRY; + return -1; +} /* end delete_by_idx() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test links @@ -6510,6 +6721,7 @@ main(void) nerrors += corder_transition(fapl2) < 0 ? 1 : 0; nerrors += corder_delete(fapl2) < 0 ? 1 : 0; nerrors += link_info_by_idx(fapl2) < 0 ? 1 : 0; + nerrors += delete_by_idx(fapl2) < 0 ? 1 : 0; } /* end if */ else { /* Test new API calls on old-style groups */ @@ -6527,6 +6739,7 @@ main(void) nerrors += corder_transition(fapl2) < 0 ? 1 : 0; nerrors += corder_delete(fapl2) < 0 ? 1 : 0; nerrors += link_info_by_idx(fapl2) < 0 ? 1 : 0; + nerrors += delete_by_idx(fapl2) < 0 ? 1 : 0; /* Test new API calls on old-style groups */ nerrors += link_info_by_idx_old(fapl) < 0 ? 1 : 0; -- cgit v0.12