diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-11-11 04:15:27 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-11-11 04:15:27 (GMT) |
commit | a9af13d9871afc2afdb308e999d2c0b823ab0033 (patch) | |
tree | fd093b58d06be1078db76a03faff4abed669ddef /src/H5Gstab.c | |
parent | b7826900273e403c29810bafc32218e210a43a79 (diff) | |
download | hdf5-a9af13d9871afc2afdb308e999d2c0b823ab0033.zip hdf5-a9af13d9871afc2afdb308e999d2c0b823ab0033.tar.gz hdf5-a9af13d9871afc2afdb308e999d2c0b823ab0033.tar.bz2 |
[svn-r12890] Description:
Finished implementation of H5Lget_info_by_idx for all cases: old vs. new
group formats, compact vs. dense new link storage, increasing vs. decreasing
vs. native iteration order.
Also, refactor symbol table "foo by index" routines to be more generic
and share more code by using a single B-tree iteration callback which makes
callbacks to a specific "get <foo>" callback.
Tested on:
Mac OS X/32 10.4.8 (amazon)
FreeBSD/32 4.11 (sleipnir)
Linux/32 2.4 (heping)
Linux/64 2.4 (mir)
AIX/32 5.? (copper)
Diffstat (limited to 'src/H5Gstab.c')
-rw-r--r-- | src/H5Gstab.c | 272 |
1 files changed, 257 insertions, 15 deletions
diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 81b9916..9dc945b 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -443,7 +443,7 @@ 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; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5G_stab_count, FAIL) @@ -459,8 +459,8 @@ H5G_stab_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Iterate over the group members */ - if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, num_objs)) < 0) - HERROR(H5E_SYM, H5E_CANTINIT, "iteration operator failed"); + if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, num_objs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed") done: FUNC_LEAVE_NOAPI(ret_value) @@ -468,6 +468,55 @@ done: /*------------------------------------------------------------------------- + * 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_idx1_t *udata = (H5G_bt_it_idx1_t *)_udata; + const H5HL_t *heap = NULL; /* Pointer to local heap for group */ + size_t name_off; /* Offset of name in heap */ + const char *name; /* Pointer to name string in heap */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_stab_get_name_by_idx) + + /* Sanity check */ + HDassert(ent); + HDassert(udata); + + /* Get name offset in heap */ + name_off = ent->name_off; + + /* Pin the heap down in memory */ + if(NULL == (heap = H5HL_protect(udata->common.f, udata->common.dxpl_id, udata->heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to protect symbol name") + + name = H5HL_offset_into(udata->common.f, heap, name_off); + HDassert(name); + udata->name = H5MM_strdup(name); + HDassert(udata->name); + +done: + if(heap && H5HL_unprotect(udata->common.f, udata->common.dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol name") + + FUNC_LEAVE_NOAPI(ret_value) +} /* 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. @@ -485,7 +534,7 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, size_t size, hid_t dxpl_id) { H5O_stab_t stab; /* Info about local heap & B-tree */ - H5G_bt_it_ud2_t udata; /* Iteration information */ + H5G_bt_it_idx1_t udata; /* Iteration information */ ssize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_stab_get_name_by_idx, FAIL) @@ -498,17 +547,20 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") /* Set iteration information */ - udata.idx = idx; - udata.num_objs = 0; + udata.common.f = oloc->file; + udata.common.dxpl_id = dxpl_id; + udata.common.idx = idx; + udata.common.num_objs = 0; + udata.common.op = H5G_stab_get_name_by_idx_cb; udata.heap_addr = stab.heap_addr; udata.name = NULL; /* Iterate over the group members */ - if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_name, stab.btree_addr, &udata)) < 0) + if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &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) + if(udata.name == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound") /* Get the length of the name */ @@ -516,20 +568,67 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, /* Copy the name into the user's buffer, if given */ if(name) { - HDstrncpy(name, udata.name, MIN((size_t)(ret_value+1),size)); + HDstrncpy(name, udata.name, MIN((size_t)(ret_value + 1),size)); if((size_t)ret_value >= size) - name[size-1]='\0'; + name[size - 1]='\0'; } /* end if */ done: /* Free the duplicated name */ - if(udata.name!=NULL) + if(udata.name != NULL) H5MM_xfree(udata.name); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_get_name_by_idx() */ /*------------------------------------------------------------------------- + * 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_idx2_t *udata = (H5G_bt_it_idx2_t *)_udata; + H5O_loc_t tmp_oloc; /* Temporary object location */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_stab_get_type_by_idx) + + /* Sanity check */ + HDassert(ent); + HDassert(udata); + + /* Check for a soft link */ + switch(ent->type) { + case H5G_CACHED_SLINK: + udata->type = H5G_LINK; + break; + + default: + /* Build temporary object location */ + tmp_oloc.file = udata->common.f; + HDassert(H5F_addr_defined(ent->header)); + tmp_oloc.addr = ent->header; + + udata->type = H5O_obj_type(&tmp_oloc, udata->common.dxpl_id); + break; + } /* end switch */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_stab_get_type_by_idx_cb */ + + +/*------------------------------------------------------------------------- * Function: H5G_get_objtype_by_idx * * Purpose: Private function for H5Gget_objtype_by_idx. @@ -548,7 +647,7 @@ 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_ud3_t udata; /* User data for B-tree callback */ + H5G_bt_it_idx2_t udata; /* User data for B-tree callback */ H5G_obj_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_stab_get_type_by_idx, H5G_UNKNOWN) @@ -561,12 +660,15 @@ H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address") /* Set iteration information */ - udata.idx = idx; - udata.num_objs = 0; + udata.common.f = oloc->file; + udata.common.dxpl_id = dxpl_id; + udata.common.idx = idx; + udata.common.num_objs = 0; + udata.common.op = H5G_stab_get_type_by_idx_cb; udata.type = H5G_UNKNOWN; /* Iterate over the group members */ - if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_type, stab.btree_addr, &udata) < 0) + if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &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 */ @@ -670,3 +772,143 @@ done: 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_idx3_t *udata = (H5G_bt_it_idx3_t *)_udata; + const H5HL_t *heap; /* Pointer to local heap for group */ + size_t name_off; /* Offset of name in heap */ + const char *name; /* Pointer to name string in heap */ + size_t name_len; /* Length of link name */ + char buf[1024]; /* Buffer for name */ + char *s = NULL; /* Pointer to copy of name string */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_stab_lookup_by_idx_cb) + + /* Sanity check */ + HDassert(ent); + HDassert(udata); + + /* Get name offset in heap */ + name_off = ent->name_off; + + /* Pin the heap down in memory */ + if(NULL == (heap = H5HL_protect(udata->common.f, udata->common.dxpl_id, udata->heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to protect symbol name") + + /* Duplicate the link name */ + name = H5HL_offset_into(udata->common.f, heap, name_off); + HDassert(name); + name_len = HDstrlen(name); + + /* Allocate space or point to existing buffer */ + if((name_len + 1) > sizeof(buf)) { + if(NULL == (s = H5MM_malloc(name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + else + s = buf; + + /* Make a copy of the name */ + HDstrcpy(s, name); + + /* Unlock the heap */ + if(H5HL_unprotect(udata->common.f, udata->common.dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol name") + heap = NULL; name = NULL; + + /* Convert the entry to a link */ + if(H5G_link_convert(udata->common.f, udata->common.dxpl_id, udata->lnk, udata->heap_addr, ent, s) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link") + udata->found = TRUE; + +done: + /* Free the memory for the name, if we used a dynamically allocated buffer */ + if(s && s != buf) + H5MM_xfree(s); + + 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(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n, + H5O_link_t *lnk, hid_t dxpl_id) +{ + H5G_bt_it_idx3_t udata; /* Iteration information */ + H5O_stab_t stab; /* Symbol table message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_lookup_by_idx, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + HDassert(lnk); + + /* Get the B-tree & local heap info */ + if(NULL == H5O_read(grp_oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + + /* 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, H5G_node_sumup, stab.btree_addr, &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.f = grp_oloc->file; + udata.common.dxpl_id = dxpl_id; + udata.common.idx = n; + udata.common.num_objs = 0; + udata.common.op = H5G_stab_lookup_by_idx_cb; + udata.heap_addr = stab.heap_addr; + udata.lnk = lnk; + udata.found = FALSE; + + /* Iterate over the group members */ + if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &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: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_lookup_by_idx() */ + |