summaryrefslogtreecommitdiffstats
path: root/src/H5Olink.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-11-13 21:45:35 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-11-13 21:45:35 (GMT)
commitf494ab7674dc39225deb4a06ba211f82f3e9df5e (patch)
tree55d6b6ace03aa2063c0569466d9ef474fcf66487 /src/H5Olink.c
parent3f7dc01ccc7f9702c3a4080afe0c2ddebf34c032 (diff)
downloadhdf5-f494ab7674dc39225deb4a06ba211f82f3e9df5e.zip
hdf5-f494ab7674dc39225deb4a06ba211f82f3e9df5e.tar.gz
hdf5-f494ab7674dc39225deb4a06ba211f82f3e9df5e.tar.bz2
[svn-r12906] Description:
Straighten out some convoluted code when links were being deleted, which could cause the "delete" callback for user-defined links to not get called when the group they were in was deleted. Had to compromise on the "delete" callback though - only calls the callback with the ID for the file the link is in, instead of the group, since the group is being held open upstream in the calling sequence during a group deletion and this prevents a group and its ID from being created. (This could possibly be worked around, but would cause a fair bit of havoc in the code and I'm not entirely certain it's worth it...) Tested on: Linux/32 2.6 (chicago)
Diffstat (limited to 'src/H5Olink.c')
-rw-r--r--src/H5Olink.c62
1 files changed, 47 insertions, 15 deletions
diff --git a/src/H5Olink.c b/src/H5Olink.c
index 9331019..8b7afbb 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -30,6 +30,8 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5Gpkg.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Lprivate.h" /* Links */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
@@ -41,7 +43,7 @@ static void *H5O_link_copy(const void *_mesg, void *_dest, unsigned update_flags
static size_t H5O_link_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_link_reset(void *_mesg);
static herr_t H5O_link_free(void *_mesg);
-static herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
+/* static herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); */
static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type,
void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
static void *H5O_link_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
@@ -489,31 +491,61 @@ H5O_link_free(void *_mesg)
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link)
{
const H5O_link_t *lnk = (const H5O_link_t *)_mesg;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_link_delete)
+ FUNC_ENTER_NOAPI(H5O_link_delete, FAIL)
/* check args */
HDassert(f);
HDassert(lnk);
- /* Decrement reference count to the object (if requested), for hard links */
- if(lnk->type == H5L_TYPE_HARD && adj_link) {
- H5O_loc_t oloc;
-
- /* Construct object location for object, in order to decrement it's ref count */
- H5O_loc_reset(&oloc);
- oloc.file = f;
- HDassert(H5F_addr_defined(lnk->u.hard.addr));
- oloc.addr = lnk->u.hard.addr;
+ /* Check for adjusting the link count when the link is removed */
+ if(adj_link) {
+ /* Adjust the reference count of the object when a hard link is removed */
+ if(lnk->type == H5L_TYPE_HARD) {
+ H5O_loc_t oloc;
+
+ /* Construct object location for object, in order to decrement it's ref count */
+ H5O_loc_reset(&oloc);
+ oloc.file = f;
+ HDassert(H5F_addr_defined(lnk->u.hard.addr));
+ oloc.addr = lnk->u.hard.addr;
+
+ /* Decrement the ref count for the object */
+ if(H5O_link(&oloc, -1, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to decrement object link count")
+ } /* end if */
+ /* Perform the "delete" callback when a user-defined link is removed */
+ else if(lnk->type >= H5L_TYPE_UD_MIN) {
+ const H5L_class_t *link_class; /* User-defined link class */
+
+ /* Get the link class for this type of link. */
+ if(NULL == (link_class = H5L_find_class(lnk->type)))
+ HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "link class not registered")
+
+ /* Check for delete callback */
+ if(link_class->del_func) {
+ hid_t file_id; /* ID for the file the link is located in (passed to user callback) */
+
+ /* Get a file ID for the file the link is in */
+ if((file_id = H5F_get_id(f)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get file ID")
+
+ /* Call user-defined link's 'delete' callback */
+ if((link_class->del_func)(lnk->name, file_id, lnk->u.ud.udata, lnk->u.ud.size) < 0) {
+ H5I_dec_ref(file_id);
+ HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "link deletion callback returned failure")
+ } /* end if */
- /* Decrement the ref count for the object */
- if(H5O_link(&oloc, -1, dxpl_id) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to decrement object link count")
+ /* Release the file ID */
+ if(H5I_dec_ref(file_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "can't close file")
+ } /* end if */
+ } /* end if */
} /* end if */
done: