summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Gcompact.c73
-rw-r--r--src/H5Gdense.c121
-rw-r--r--src/H5Gobj.c242
-rw-r--r--src/H5Gpkg.h8
-rw-r--r--src/H5L.c17
-rw-r--r--test/links.c213
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, &ltable) < 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(&ltable) < 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(&ltable) < 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, &ltable) < 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(&ltable) < 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, &ltable) < 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(&ltable) < 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, &ltable) < 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(&ltable) < 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;