From f494ab7674dc39225deb4a06ba211f82f3e9df5e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 13 Nov 2006 16:45:35 -0500 Subject: [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) --- src/H5Gcompact.c | 71 +++++++++++--------------------------------------------- src/H5Gdense.c | 41 +++++++------------------------- src/H5Glink.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Gpkg.h | 2 ++ src/H5L.c | 48 -------------------------------------- src/H5Lpublic.h | 2 +- src/H5O.c | 13 ++++------- src/H5Olayout.c | 22 ++++++++++-------- src/H5Olink.c | 62 +++++++++++++++++++++++++++++++++++++------------ src/H5Oprivate.h | 6 ++++- src/H5Oshared.c | 18 +++++++------- test/links.c | 20 ++++++++-------- 12 files changed, 180 insertions(+), 191 deletions(-) diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 50e661b..9dd9275 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -38,7 +38,7 @@ typedef struct { H5G_link_table_t *ltable; /* Pointer to link table to build */ size_t curr_lnk; /* Current link to operate on */ -} H5G_compact_ud1_t; +} H5G_iter_bt_t; /* User data for deleting a link in the link messages */ typedef struct { @@ -49,20 +49,9 @@ typedef struct { /* upward */ H5G_obj_t *obj_type; /* Type of object deleted */ -} H5G_compact_ud2_t; +} H5G_iter_rm_t; -/* User data for link message iteration when querying object info */ -typedef struct { - /* downward */ - const char *name; /* Name to search for */ - H5F_t *file; /* File that object header is located within */ - hid_t dxpl_id; /* DXPL during insertion */ - - /* upward */ - H5G_stat_t *statbuf; /* Stat buffer for info */ -} H5G_compact_ud3_t; - -/* User data for link message iteration when querying object location */ +/* User data for link message iteration when querying link info */ typedef struct { /* downward */ const char *name; /* Name to search for */ @@ -70,17 +59,7 @@ typedef struct { /* upward */ H5O_link_t *lnk; /* Link struct to fill in */ hbool_t found; /* Flag to indicate that the object was found */ -} H5G_compact_ud4_t; - -/* User data for link message iteration when querying soft link value */ -typedef struct { - /* downward */ - const char *name; /* Name to search for */ - size_t size; /* Buffer size for link value */ - - /* upward */ - char *buf; /* Buffer to fill with link value */ -} H5G_compact_ud5_t; +} H5G_iter_lkp_t; /* Private macros */ @@ -109,7 +88,7 @@ static herr_t H5G_compact_build_table_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) { const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ - H5G_compact_ud1_t *udata = (H5G_compact_ud1_t *)_udata; /* 'User data' passed in */ + H5G_iter_bt_t *udata = (H5G_iter_bt_t *)_udata; /* 'User data' passed in */ herr_t ret_value=H5O_ITER_CONT; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_compact_build_table_cb) @@ -164,7 +143,7 @@ H5G_compact_build_table(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo /* Allocate space for the table entries */ if(ltable->nlinks > 0) { - H5G_compact_ud1_t udata; /* User data for iteration callback */ + H5G_iter_bt_t udata; /* User data for iteration callback */ if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") @@ -376,7 +355,7 @@ static herr_t H5G_compact_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) { const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ - H5G_compact_ud2_t *udata = (H5G_compact_ud2_t *)_udata; /* 'User data' passed in */ + 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) @@ -387,32 +366,10 @@ H5G_compact_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) /* If we've found the right link, get the object type */ if(HDstrcmp(lnk->name, udata->name) == 0) { - switch(lnk->type) - { - case H5L_TYPE_HARD: - { - H5O_loc_t tmp_oloc; /* Temporary object location */ - - /* Build temporary object location */ - tmp_oloc.file = udata->file; - tmp_oloc.addr = lnk->u.hard.addr; - - /* Get the type of the object */ - /* Note: no way to check for error :-( */ - *(udata->obj_type) = H5O_obj_type(&tmp_oloc, udata->dxpl_id); - } - break; - - case H5L_TYPE_SOFT: - *(udata->obj_type) = H5G_LINK; - break; - - default: /* User-defined link */ - if(lnk->type < H5L_TYPE_UD_MIN) - HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown link type") - - *(udata->obj_type) = H5G_UDLINK; - } + /* Determine the object's type */ + if(H5G_link_obj_type(udata->file, udata->dxpl_id, lnk, udata->obj_type) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5O_ITER_ERROR, "unable to get object type") + /* Stop the iteration, we found the correct link */ HGOTO_DONE(H5O_ITER_STOP) } /* end if */ @@ -438,7 +395,7 @@ herr_t H5G_compact_remove(const H5O_loc_t *oloc, const char *name, H5G_obj_t *obj_type, hid_t dxpl_id) { - H5G_compact_ud2_t udata; /* Data to pass through OH iteration */ + H5G_iter_rm_t udata; /* Data to pass through OH iteration */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_compact_remove, FAIL) @@ -543,7 +500,7 @@ static herr_t H5G_compact_lookup_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) { const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ - H5G_compact_ud4_t *udata = (H5G_compact_ud4_t *)_udata; /* 'User data' passed in */ + H5G_iter_lkp_t *udata = (H5G_iter_lkp_t *)_udata; /* 'User data' passed in */ herr_t ret_value = H5O_ITER_CONT; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_compact_lookup_cb) @@ -589,7 +546,7 @@ herr_t H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id) { - H5G_compact_ud4_t udata; /* User data for iteration callback */ + H5G_iter_lkp_t udata; /* User data for iteration callback */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_compact_lookup, FAIL) diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 3b8be2f..4213076 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -1352,39 +1352,14 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, H5B2_ITER_ERROR, "unable to remove link from creation order index v2 B-tree") } /* end if */ - /* Retrieve the link's object type & decr. the ref. count on hard links, if requested */ - switch(lnk->type) { - case H5L_TYPE_HARD: - { - H5O_loc_t tmp_oloc; /* Temporary object location */ - - /* Build temporary object location */ - tmp_oloc.file = udata->f; - tmp_oloc.addr = lnk->u.hard.addr; - - /* Get the type of the object */ - /* Note: no way to check for error :-( */ - if(udata->obj_type) - *(udata->obj_type) = H5O_obj_type(&tmp_oloc, udata->dxpl_id); - - /* Decrement the ref count for the object, if requested */ - if(udata->adj_link) - if(H5O_link(&tmp_oloc, -1, udata->dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to decrement object link count") - } - break; - - case H5L_TYPE_SOFT: - if(udata->obj_type) - *(udata->obj_type) = H5G_LINK; - break; - - default: /* User-defined link */ - if(lnk->type < H5L_TYPE_UD_MIN) - HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown link type") - if(udata->obj_type) - *(udata->obj_type) = H5G_UDLINK; - } /* end switch */ + /* Determine the object's type */ + if(H5G_link_obj_type(udata->f, udata->dxpl_id, lnk, udata->obj_type) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object type") + + /* Perform the deletion action on the link */ + /* (call link message "delete" callback directly: *ick* - QAK) */ + if(H5O_link_delete(udata->f, udata->dxpl_id, lnk, udata->adj_link) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link") /* Release the space allocated for the link */ H5O_free(H5O_LINK_ID, lnk); diff --git a/src/H5Glink.c b/src/H5Glink.c index 0600e97..9144096 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -37,6 +37,9 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Gpkg.h" /* Groups */ #include "H5HLprivate.h" /* Local Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Lprivate.h" /* Links */ +#include "H5MMprivate.h" /* Memory management */ /****************/ @@ -418,3 +421,66 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_release_table() */ + +/*------------------------------------------------------------------------- + * Function: H5G_link_obj_type + * + * Purpose: Determine the type of object referred to (for hard links) or + * the link type (for soft links and user-defined links). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 13 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_obj_type(H5F_t *file, hid_t dxpl_id, const H5O_link_t *lnk, + H5G_obj_t *obj_type) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_obj_type, FAIL) + + /* check arguments */ + HDassert(file); + HDassert(lnk); + + /* Check if we are able to retrieve the object's type */ + if(obj_type) { + /* Look up the object type for each type of link */ + switch(lnk->type) { + case H5L_TYPE_HARD: + { + H5O_loc_t tmp_oloc; /* Temporary object location */ + + /* Build temporary object location */ + tmp_oloc.file = file; + tmp_oloc.addr = lnk->u.hard.addr; + + /* Get the type of the object */ + /* Note: no way to check for error :-( */ + *obj_type = H5O_obj_type(&tmp_oloc, dxpl_id); + } + break; + + case H5L_TYPE_SOFT: + /* Get the object's type */ + *obj_type = H5G_LINK; + break; + + default: /* User-defined link */ + if(lnk->type < H5L_TYPE_UD_MIN) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown link type") + + /* Get the object's type */ + *obj_type = H5G_UDLINK; + } /* end switch */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_obj_type() */ + diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index b3dc299..47342dd 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -423,6 +423,8 @@ H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk, const H5O_loc_t *src_oloc, H5O_link_t *dst_lnk, H5O_copy_t *cpy_info); H5_DLL herr_t H5G_link_release_table(H5G_link_table_t *ltable); +H5_DLL herr_t H5G_link_obj_type(H5F_t *file, hid_t dxpl_id, const H5O_link_t *lnk, + H5G_obj_t *obj_type); /* Functions that understand "compact" link storage */ H5_DLL herr_t H5G_compact_insert(H5O_loc_t *grp_oloc, H5O_link_t *obj_lnk, diff --git a/src/H5L.c b/src/H5L.c index 1dff29d..2b2363d 100644 --- a/src/H5L.c +++ b/src/H5L.c @@ -1958,10 +1958,6 @@ H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSE H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/) { H5L_trav_rm_t *udata = (H5L_trav_rm_t *)_udata; /* User data passed in */ - H5G_t *grp = NULL; /* H5G_t for this group, opened to pass to user callback */ - hid_t grp_id = FAIL; /* ID for this group (passed to user callback) */ - H5G_loc_t temp_loc; /* For UD callback */ - hbool_t temp_loc_init = FALSE; /* Temporary location has been initialized? */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5L_delete_cb) @@ -1974,55 +1970,11 @@ H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSE if(lnk == NULL) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "can't delete self") - /* If there is a user-defined callback, call it before deleting the link */ - 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") - - if(link_class->del_func != NULL) - { - H5O_loc_t temp_oloc; - H5G_name_t temp_path; - - H5G_name_reset(&temp_path); - - /* Get object location for link's parent group */ - if(H5O_loc_copy(&temp_oloc, grp_loc->oloc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location") - - temp_loc.oloc = &temp_oloc; - temp_loc.path = &temp_path; - temp_loc_init = TRUE; - - /* Set up group for user-defined callback */ - if((grp = H5G_open(&temp_loc, udata->dxpl_id)) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open group") - if((grp_id = H5I_register(H5I_GROUP, grp)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") - - /* Call user-defined link's 'delete' callback */ - if((link_class->del_func)(name, grp_id, lnk->u.ud.udata, lnk->u.ud.size) < 0) - HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "link deletion callback returned failure") - } /* end if */ - } /* end if */ - /* Remove the link from the group */ if(H5G_loc_remove(grp_loc, name, obj_loc, udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to remove link from group") done: - /* Close the location given to the user callback if it was created */ - if(grp_id >= 0) - H5I_dec_ref(grp_id); - else if(grp != NULL) - H5G_close(grp); - else if(temp_loc_init) - H5G_loc_free(&temp_loc); - /* Indicate that this callback didn't take ownership of the group * * location for the object */ *own_loc = H5G_OWN_NONE; diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h index d8744ca..f003173 100644 --- a/src/H5Lpublic.h +++ b/src/H5Lpublic.h @@ -101,7 +101,7 @@ typedef herr_t (*H5L_copy_func_t)(const char * new_name, hid_t new_loc, void * u typedef herr_t (*H5L_traverse_func_t)(const char * link_name, hid_t cur_group, void * udata, size_t udata_size, hid_t lapl_id); /* Callback for when the link is deleted */ -typedef herr_t (*H5L_delete_func_t)(const char * link_name, hid_t loc_group, void * udata, size_t udata_size); +typedef herr_t (*H5L_delete_func_t)(const char * link_name, hid_t file, void * udata, size_t udata_size); /* Callback for querying the link */ /* Returns the size of the buffer needed */ diff --git a/src/H5O.c b/src/H5O.c index 89194b5..5a7d1f0 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -4350,8 +4350,8 @@ done: static herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) { - const H5O_msg_class_t *type; /* Type of object to free */ - herr_t ret_value=SUCCEED; /* Return value */ + const H5O_msg_class_t *type; /* Type of object to free */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_delete_mesg) @@ -4369,13 +4369,10 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) /* Check if there is a file space deletion callback for this type of message */ if(type->del) { - /* - * Decode the message if necessary. - */ + /* Decode the message if necessary. */ if(NULL == mesg->native) { HDassert(type->decode); - mesg->native = (type->decode) (f, dxpl_id, mesg->raw); - if(NULL == mesg->native) + if(NULL == (mesg->native = (type->decode)(f, dxpl_id, mesg->raw))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") } /* end if */ @@ -4955,7 +4952,7 @@ H5O_loc_copy(H5O_loc_t *dst, const H5O_loc_t *src, H5_copy_depth_t depth) /* Deep copy the names */ if(depth == H5_COPY_DEEP) { - /* If the original entry has holding open the file, this one should + /* If the original entry was holding open the file, this one should * hold it open, too. */ if(src->holding_file) diff --git a/src/H5Olayout.c b/src/H5Olayout.c index a420301..3b4d7e5 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -38,7 +38,8 @@ static void *H5O_layout_copy(const void *_mesg, void *_dest, unsigned update_fla static size_t H5O_layout_size(const H5F_t *f, const void *_mesg); static herr_t H5O_layout_reset(void *_mesg); static herr_t H5O_layout_free(void *_mesg); -static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); +static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, + hbool_t adj_link); static void *H5O_layout_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, @@ -567,16 +568,17 @@ H5O_layout_free (void *_mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t UNUSED adj_link) +H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, + hbool_t UNUSED adj_link) { - const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; - herr_t ret_value=SUCCEED; /* Return value */ + const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_layout_delete); + FUNC_ENTER_NOAPI_NOINIT(H5O_layout_delete) /* check args */ - assert(f); - assert(mesg); + HDassert(f); + HDassert(mesg); /* Perform different actions, depending on the type of storage */ switch(mesg->type) { @@ -586,13 +588,13 @@ H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t UNUSED adj case H5D_CONTIGUOUS: /* Contiguous block on disk */ /* Free the file space for the raw data */ - if (H5D_contig_delete(f, dxpl_id, mesg)<0) + if(H5D_contig_delete(f, dxpl_id, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data") break; case H5D_CHUNKED: /* Chunked blocks on disk */ /* Free the file space for the raw data */ - if (H5D_istore_delete(f, dxpl_id, mesg)<0) + if(H5D_istore_delete(f, dxpl_id, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data") break; @@ -601,7 +603,7 @@ H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t UNUSED adj } /* end switch */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_layout_delete() */ 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: diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 5aa7c87..30ea804 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -450,4 +450,8 @@ H5_DLL hsize_t H5O_efl_total_size(H5O_efl_t *efl); /* Fill value operators */ H5_DLL herr_t H5O_fill_convert(void *_fill, H5T_t *type, hid_t dxpl_id); -#endif +/* Link operators */ +H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); + +#endif /* _H5Oprivate_H */ + diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 7c69ab9..e90031d 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -42,7 +42,8 @@ static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*); static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*); static void *H5O_shared_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_shared_size (const H5F_t*, const void *_mesg); -static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); +static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, + hbool_t adj_link); static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_shared_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); @@ -512,16 +513,17 @@ H5O_shared_size (const H5F_t *f, const void *_mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) +H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, + hbool_t adj_link) { const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_shared_delete); + FUNC_ENTER_NOAPI_NOINIT(H5O_shared_delete) /* check args */ - assert(f); - assert(shared); + HDassert(f); + HDassert(shared); /* * Committed datatypes increment the OH of the original message when they @@ -534,7 +536,7 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) /* Decrement the reference count on the shared object, if requested */ if(adj_link) - if(H5O_shared_link_adj(f, dxpl_id, shared, -1)<0) + if(H5O_shared_link_adj(f, dxpl_id, shared, -1) < 0) HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") /* JAMES */ @@ -542,7 +544,7 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) H5O_loc_free(&(shared->oloc)); */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_delete() */ diff --git a/test/links.c b/test/links.c index 7a3a4c0..0c1cae2 100644 --- a/test/links.c +++ b/test/links.c @@ -3679,7 +3679,7 @@ done: /* UD_hard_delete decrements the object's reference count */ static herr_t -UD_hard_delete(const char UNUSED * link_name, hid_t loc_group, void * udata, size_t udata_size) +UD_hard_delete(const char UNUSED * link_name, hid_t file, void * udata, size_t udata_size) { haddr_t addr; hid_t target_obj = -1; @@ -3694,7 +3694,7 @@ UD_hard_delete(const char UNUSED * link_name, hid_t loc_group, void * udata, siz addr = *((haddr_t *) udata); /* Open the object this link points to */ - target_obj= H5Oopen_by_addr(loc_group, addr); + target_obj= H5Oopen_by_addr(file, addr); if(target_obj < 0) { ret_value = -1; @@ -4134,8 +4134,8 @@ UD_cb_move(const char * new_name, hid_t new_loc, void * udata, size_t udata_size if(new_loc < 0) TEST_ERROR if(udata_size > 0 && !udata) TEST_ERROR - if(strcmp(new_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR - if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR + if(HDstrcmp(new_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR + if(HDstrcmp(udata, UD_CB_TARGET)) TEST_ERROR if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR return 0; @@ -4146,14 +4146,14 @@ error: /* Callback for when the link is deleted. Also called during move */ static herr_t -UD_cb_delete(const char * link_name, hid_t loc_group, void * udata, size_t udata_size) +UD_cb_delete(const char * link_name, hid_t file, void * udata, size_t udata_size) { if(!link_name) TEST_ERROR - if(loc_group < 0) TEST_ERROR + if(file < 0) TEST_ERROR if(udata_size > 0 && !udata) TEST_ERROR - if(strcmp(link_name, UD_CB_LINK_NAME) && strcmp(link_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR - if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR + if(HDstrcmp(link_name, UD_CB_LINK_NAME) && HDstrcmp(link_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR + if(HDstrcmp(udata, UD_CB_TARGET)) TEST_ERROR if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR return 0; @@ -4528,7 +4528,7 @@ UD_cbsucc_move(const char UNUSED * new_name, hid_t UNUSED new_loc, /* Callback for when the link is deleted. Also called during move */ static herr_t -UD_cbsucc_delete(const char UNUSED * link_name, hid_t UNUSED loc_group, +UD_cbsucc_delete(const char UNUSED * link_name, hid_t UNUSED file, void UNUSED * udata, size_t UNUSED udata_size) { /* This callback will always succeed */ @@ -4537,7 +4537,7 @@ UD_cbsucc_delete(const char UNUSED * link_name, hid_t UNUSED loc_group, /* Callback for when the link is deleted. Also called during move */ static herr_t -UD_cbfail_delete(const char UNUSED * link_name, hid_t UNUSED loc_group, +UD_cbfail_delete(const char UNUSED * link_name, hid_t UNUSED file, void UNUSED * udata, size_t UNUSED udata_size) { /* This traversal function will always fail. */ -- cgit v0.12