diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2010-10-13 15:42:01 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2010-10-13 15:42:01 (GMT) |
commit | d99e23638ba96b71a39c46cbe1cb6369a3b7467c (patch) | |
tree | fc7be3c604fd16f3e26b6179d620a1ad1604b452 /src | |
parent | 2342d695dce629e1ee19610e97e873546ab91a82 (diff) | |
download | hdf5-d99e23638ba96b71a39c46cbe1cb6369a3b7467c.zip hdf5-d99e23638ba96b71a39c46cbe1cb6369a3b7467c.tar.gz hdf5-d99e23638ba96b71a39c46cbe1cb6369a3b7467c.tar.bz2 |
[svn-r19587] Description:
Address issue with object headers being created getting evicted from
the metadata cache cache before they are completely initialized. This is
done by pinning the object header in the cache until it is completely
initialized and attached to a group.
Tested on:
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, w/threadsafe, in production mode
Linux/PPC 2.6 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode
Mac OS X/32 10.6.4 (amazon) in debug mode
Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode
Diffstat (limited to 'src')
-rw-r--r-- | src/H5C.c | 2 | ||||
-rw-r--r-- | src/H5D.c | 14 | ||||
-rw-r--r-- | src/H5Dint.c | 4 | ||||
-rw-r--r-- | src/H5Fpkg.h | 3 | ||||
-rw-r--r-- | src/H5Fsuper.c | 61 | ||||
-rw-r--r-- | src/H5Fsuper_cache.c | 4 | ||||
-rw-r--r-- | src/H5G.c | 16 | ||||
-rw-r--r-- | src/H5Gobj.c | 5 | ||||
-rw-r--r-- | src/H5Groot.c | 4 | ||||
-rw-r--r-- | src/H5Gtraverse.c | 10 | ||||
-rw-r--r-- | src/H5L.c | 22 | ||||
-rw-r--r-- | src/H5O.c | 57 | ||||
-rw-r--r-- | src/H5Opkg.h | 1 | ||||
-rw-r--r-- | src/H5Oprivate.h | 3 | ||||
-rw-r--r-- | src/H5Otest.c | 49 | ||||
-rw-r--r-- | src/H5Tcommit.c | 17 |
16 files changed, 231 insertions, 41 deletions
@@ -7792,7 +7792,7 @@ end_of_inner_loop: */ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Pinned entry count not decreasing.") + "Pinned entry count not decreasing, cur_pel_len = %d, old_pel_len = %d", (int)cur_pel_len, (int)old_pel_len) } else if ( ( cur_pel_len == 0 ) && ( old_pel_len == 0 ) ) { @@ -256,6 +256,20 @@ H5Dcreate_anon(hid_t loc_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset") done: + /* Release the dataset's object header, if it was created */ + if(dset) { + H5O_loc_t *oloc; /* Object location for dataset */ + + /* Get the new dataset's object location */ + if(NULL == (oloc = H5D_oloc(dset))) + HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get object location of dataset") + + /* Decrement refcount on dataset's object header in memory */ + if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") + } /* end if */ + + /* Cleanup on failure */ if(ret_value < 0) if(dset && H5D_close(dset) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") diff --git a/src/H5Dint.c b/src/H5Dint.c index 4c076f7..8782f58 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -789,7 +789,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id) ohdr_size += layout->storage.u.compact.size; /* Create an object header for the dataset */ - if(H5O_create(file, dxpl_id, ohdr_size, dset->shared->dcpl_id, oloc/*out*/) < 0) + if(H5O_create(file, dxpl_id, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header") HDassert(file == dset->oloc.file); @@ -1063,6 +1063,8 @@ done: if(new_dset->shared->type && H5I_dec_ref(new_dset->shared->type_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype") if(H5F_addr_defined(new_dset->oloc.addr)) { + if(H5O_dec_rc_by_loc(&(new_dset->oloc), dxpl_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") if(H5O_close(&(new_dset->oloc)) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release object header") if(file) { diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index d264d04..4a4d49c 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -310,7 +310,8 @@ H5_DLL herr_t H5F_super_free(H5F_super_t *sblock); H5_DLL herr_t H5F_super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr); H5_DLL herr_t H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create); H5_DLL herr_t H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id); -H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr); +H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id, + hbool_t was_created); /* Metadata accumulator routines */ H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index a259dde..2510487 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -204,7 +204,7 @@ H5F_super_ext_create(H5F_t *f, hid_t dxpl_id, H5O_loc_t *ext_ptr) * extension. */ H5O_loc_reset(ext_ptr); - if(H5O_create(f, dxpl_id, 0, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0) + if(H5O_create(f, dxpl_id, 0, (size_t)1, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "unable to create superblock extension") /* Record the address of the superblock extension */ @@ -267,7 +267,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr) +H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id, + hbool_t was_created) { herr_t ret_value = SUCCEED; /* Return value */ @@ -277,6 +278,17 @@ H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr) HDassert(f); HDassert(ext_ptr); + /* Check if extension was created */ + if(was_created) { + /* Increment link count on superblock extension's object header */ + if(H5O_link(ext_ptr, 1, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_LINKCOUNT, FAIL, "unable to increment hard link count") + + /* Decrement refcount on superblock extension's object header in memory */ + if(H5O_dec_rc_by_loc(ext_ptr, dxpl_id) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement refcount on superblock extension") + } /* end if */ + /* Twiddle the number of open objects to avoid closing the file. */ f->nopen_objs++; if(H5O_close(ext_ptr) < 0) @@ -384,7 +396,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) hsize_t superblock_size; /* Size of superblock, in bytes */ size_t driver_size; /* Size of driver info block (bytes) */ unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */ + H5O_loc_t ext_loc; /* Superblock extension object location */ hbool_t need_ext; /* Whether the superblock extension is needed */ + hbool_t ext_created = FALSE; /* Whether the extension has been created */ herr_t ret_value = SUCCEED; /* Return Value */ FUNC_ENTER_NOAPI_TAG(H5F_super_init, dxpl_id, H5AC__SUPERBLOCK_TAG, FAIL) @@ -545,8 +559,6 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) /* Create the superblock extension for "extra" superblock data, if necessary. */ if(need_ext) { - H5O_loc_t ext_loc; /* Superblock extension object location */ - /* The superblock extension isn't actually a group, but the * default group creation list should work fine. * If we don't supply a size for the object header, HDF5 will @@ -557,6 +569,7 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) */ if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension") + ext_created = TRUE; /* Create the Shared Object Header Message table and register it with * the metadata cache, if this file supports shared messages. @@ -615,13 +628,13 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) if(H5O_msg_create(&ext_loc, H5O_FSINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &fsinfo, dxpl_id) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update free-space info header message") } /* end if */ - - /* Close superblock extension */ - if(H5F_super_ext_close(f, &ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") } /* end if */ done: + /* Close superblock extension, if it was created */ + if(ext_created && H5F_super_ext_close(f, &ext_loc, dxpl_id, ext_created) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") + /* Cleanup on failure */ if(ret_value < 0) { /* Check if the superblock has been allocated yet */ @@ -786,7 +799,8 @@ done: herr_t H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create) { - hbool_t sblock_dirty = FALSE; /* Whether superblock was dirtied */ + hbool_t ext_created = FALSE; /* Whether superblock extension was created */ + hbool_t ext_opened = FALSE; /* Whether superblock extension was opened */ H5O_loc_t ext_loc; /* "Object location" for superblock extension */ htri_t status; /* Indicate whether the message exists or not */ herr_t ret_value = SUCCEED; /* Return value */ @@ -807,9 +821,10 @@ H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_ HDassert(may_create); if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create file's superblock extension") - sblock_dirty = TRUE; + ext_created = TRUE; } /* end else */ HDassert(H5F_addr_defined(ext_loc.addr)); + ext_opened = TRUE; /* Check if message with ID does not exist in the object header */ if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0) @@ -833,15 +848,14 @@ H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to write the message in object header") } /* end else */ - /* Close the superblock extension object header */ - if(H5F_super_ext_close(f, &ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") - done: - /* Mark superblock dirty in cache, if necessary */ - if(sblock_dirty) - if(H5AC_mark_entry_dirty(f->shared->sblock) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + /* Close the superblock extension, if it was opened */ + if(ext_opened && H5F_super_ext_close(f, &ext_loc, dxpl_id, ext_created) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") + + /* Mark superblock dirty in cache, if superblock extension was created */ + if(ext_created && H5AC_mark_entry_dirty(f->shared->sblock) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") FUNC_LEAVE_NOAPI(ret_value) } /* H5F_super_ext_write_msg() */ @@ -861,9 +875,10 @@ done: herr_t H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id) { - htri_t status; /* Indicate whether the message exists or not */ H5O_loc_t ext_loc; /* "Object location" for superblock extension */ + hbool_t ext_opened = FALSE; /* Whether the superblock extension was opened */ int null_count = 0; /* # of null messages */ + htri_t status; /* Indicate whether the message exists or not */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_super_ext_remove_msg, FAIL) @@ -874,6 +889,7 @@ H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id) /* Open superblock extension object header */ if(H5F_super_ext_open(f, f->shared->sblock->ext_addr, &ext_loc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in starting file's superblock extension") + ext_opened = TRUE; /* Check if message with ID exists in the object header */ if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0) @@ -902,10 +918,11 @@ H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id) } /* end if */ } /* end if */ - /* Close superblock extension object header */ - if(H5F_super_ext_close(f, &ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") done: + /* Close superblock extension object header, if opened */ + if(ext_opened && H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") + FUNC_LEAVE_NOAPI(ret_value) } /* H5F_super_ext_remove_msg() */ diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index f9a29e8..56f9219 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -595,7 +595,7 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, void *_udata) } /* end if */ /* Close superblock extension */ - if(H5F_super_ext_close(f, &ext_loc) < 0) + if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "unable to close file's superblock extension") } /* end if */ @@ -794,7 +794,7 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to update driver info header message") /* Close the superblock extension object header */ - if(H5F_super_ext_close(f, &ext_loc) < 0) + if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension") } /* end if */ } /* end if */ @@ -353,6 +353,20 @@ H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") done: + /* Release the group's object header, if it was created */ + if(grp) { + H5O_loc_t *oloc; /* Object location for group */ + + /* Get the new group's object location */ + if(NULL == (oloc = H5G_oloc(grp))) + HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object location of group") + + /* Decrement refcount on group's object header in memory */ + if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") + } /* end if */ + + /* Cleanup on failure */ if(ret_value < 0) if(grp && H5G_close(grp) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") @@ -901,6 +915,8 @@ done: if(ret_value == NULL) { /* Check if we need to release the file-oriented symbol table info */ if(oloc_init) { + if(H5O_dec_rc_by_loc(&(grp->oloc), dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object") if(H5O_close(&(grp->oloc)) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header") if(H5O_delete(file, dxpl_id, grp->oloc.addr) < 0) diff --git a/src/H5Gobj.c b/src/H5Gobj.c index ce11990..b0add06 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -160,8 +160,7 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, H5G_obj_create_t *gcrt_info, HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group info") /* Call the "real" group creation routine now */ - if(H5G_obj_create_real(f, dxpl_id, &ginfo, &linfo, &pline, gcrt_info, oloc) - < 0) + if(H5G_obj_create_real(f, dxpl_id, &ginfo, &linfo, &pline, gcrt_info, oloc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create group") done: @@ -264,7 +263,7 @@ H5G_obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, * since nothing refers to it yet. The link count will be * incremented if the object is added to the group directed graph. */ - if(H5O_create(f, dxpl_id, hdr_size, gcpl_id, oloc/*out*/) < 0) + if(H5O_create(f, dxpl_id, hdr_size, (size_t)1, gcpl_id, oloc/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header") /* Check for format of group to create */ diff --git a/src/H5Groot.c b/src/H5Groot.c index a79a5dd..b8ba0fd 100644 --- a/src/H5Groot.c +++ b/src/H5Groot.c @@ -148,6 +148,10 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, hbool_t create_root) if(1 != H5O_link(root_loc.oloc, 1, dxpl_id)) HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "internal error (wrong link count)") + /* Decrement refcount on root group's object header in memory */ + if(H5O_dec_rc_by_loc(root_loc.oloc, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on root group's object header") + /* Mark superblock dirty, so root group info is flushed */ sblock_dirty = TRUE; diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 4016068..bb8e590 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -792,15 +792,17 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, gcrt_info.gcpl_id = H5P_GROUP_CREATE_DEFAULT; gcrt_info.cache_type = H5G_NOTHING_CACHED; HDmemset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache)); - if(H5G_obj_create_real(grp_oloc.file, dxpl_id, ginfo, linfo, - pline, &gcrt_info, obj_loc.oloc/*out*/) < 0) + if(H5G_obj_create_real(grp_oloc.file, dxpl_id, ginfo, linfo, pline, &gcrt_info, obj_loc.oloc/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry") /* Insert new group into current group's symbol table */ - if(H5G_loc_insert(&grp_loc, H5G_comp_g, &obj_loc, - H5O_TYPE_GROUP, &gcrt_info, dxpl_id) < 0) + if(H5G_loc_insert(&grp_loc, H5G_comp_g, &obj_loc, H5O_TYPE_GROUP, &gcrt_info, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert intermediate group") + /* Decrement refcount on intermediate group's object header in memory */ + if(H5O_dec_rc_by_loc(obj_loc.oloc, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") + /* Close new group */ if(H5O_close(obj_loc.oloc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") @@ -1664,8 +1664,9 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED 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; - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t temp_loc_init = FALSE; /* Temporary location for UD callback (temp_loc) has been initialized */ + hbool_t obj_created = FALSE; /* Whether an object was created (through a hard link) */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5L_link_cb) @@ -1690,6 +1691,9 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED /* Set object path to use for setting object name (below) */ udata->path = new_loc.path; + + /* Indicate that an object was created */ + obj_created = TRUE; } /* end if */ else { /* Check that both objects are in same file */ @@ -1763,6 +1767,20 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED } /* end if */ done: + /* Check if an object was created */ + if(obj_created) { + H5O_loc_t oloc; /* Object location for created object */ + + /* Set up object location */ + HDmemset(&oloc, 0, sizeof(oloc)); + oloc.file = grp_loc->oloc->file; + oloc.addr = udata->lnk->u.hard.addr; + + /* Decrement refcount on superblock extension's object header in memory */ + if(H5O_dec_rc_by_loc(&oloc, udata->dxpl_id) < 0) + HDONE_ERROR(H5E_LINK, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") + } /* end if */ + /* Close the location given to the user callback if it was created */ if(grp_id >= 0) { if(H5I_dec_app_ref(grp_id) < 0) @@ -1106,14 +1106,15 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, - H5O_loc_t *loc/*out*/) +H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, size_t initial_rc, + hid_t ocpl_id, H5O_loc_t *loc/*out*/) { H5P_genplist_t *oc_plist; /* Object creation property list */ H5O_t *oh = NULL; /* Object header created */ haddr_t oh_addr; /* Address of initial object header */ size_t oh_size; /* Size of initial object header */ uint8_t oh_flags; /* Object header's initial status flags */ + unsigned insert_flags = H5AC__NO_FLAGS_SET; /* Flags for inserting object header into cache */ hbool_t store_msg_crt_idx; /* Whether to always store message creation indices for this file */ herr_t ret_value = SUCCEED; /* return value */ @@ -1243,11 +1244,18 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh); oh->mesg[0].chunkno = 0; + /* Check for non-zero initial refcount on the object header */ + if(initial_rc > 0) { + /* Set the initial refcount & pin the header when its inserted */ + oh->rc = initial_rc; + insert_flags |= H5AC__PIN_ENTRY_FLAG; + } /* end if */ + /* Set metadata tag in dxpl_id */ H5_BEGIN_TAG(dxpl_id, oh_addr, FAIL); /* Cache object header */ - if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR, oh_addr, oh, H5AC__NO_FLAGS_SET) < 0) + if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR, oh_addr, oh, insert_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header") oh = NULL; @@ -3422,6 +3430,49 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_dec_rc_by_loc + * + * Purpose: Decrement the refcount of an object header, using its + * object location information. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 08 2010 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_dec_rc_by_loc, FAIL) + + /* check args */ + HDassert(loc); + + /* Get header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header") + + /* Decrement the reference count on the object header */ + /* (which will unpin it, if appropriate) */ + if(H5O_dec_rc(oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header") + +done: + /* Release the object header from the cache */ + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_dec_rc_by_loc() */ + + +/*------------------------------------------------------------------------- * Function: H5O_free * * Purpose: Destroys an object header. diff --git a/src/H5Opkg.h b/src/H5Opkg.h index a14d471..54e7233 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -610,6 +610,7 @@ H5_DLL herr_t H5O_num_attrs_test(hid_t oid, hsize_t *nattrs); H5_DLL herr_t H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count); H5_DLL herr_t H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val); H5_DLL herr_t H5O_expunge_chunks_test(const H5O_loc_t *oloc, hid_t dxpl_id); +H5_DLL herr_t H5O_get_rc(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc); #endif /* H5O_TESTING */ /* Object header debugging routines */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 63264d8..c0bff03 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -623,13 +623,14 @@ struct H5P_genplist_t; /* Object header routines */ H5_DLL herr_t H5O_init(void); H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, - hid_t ocpl_id, H5O_loc_t *loc/*out*/); + size_t initial_rc, hid_t ocpl_id, H5O_loc_t *loc/*out*/); H5_DLL herr_t H5O_open(H5O_loc_t *loc); H5_DLL herr_t H5O_close(H5O_loc_t *loc); H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id); H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot); H5_DLL H5O_t *H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id); H5_DLL herr_t H5O_unpin(H5O_t *oh); +H5_DLL herr_t H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id); H5_DLL herr_t H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh, unsigned oh_flags); H5_DLL herr_t H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id); diff --git a/src/H5Otest.c b/src/H5Otest.c index 557ac9e..883bfcd 100644 --- a/src/H5Otest.c +++ b/src/H5Otest.c @@ -536,3 +536,52 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5O_expunge_chunks_test() */ + +/*-------------------------------------------------------------------------- + NAME + H5O_get_rc + PURPOSE + Retrieve the refcount for the object header + USAGE + herr_t H5O_expunge_chunks_test(loc, dxpl_id, rc) + const H5O_loc_t *loc; IN: Object location for object header to query + hid_t dxpl_id; IN: DXPL to use for operation + unsigned *rc; OUT: Pointer to refcount for object header + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Protects object header, retrieves the object header's refcount, and + unprotects object header. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_get_rc(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_get_rc, FAIL) + + /* Sanity check */ + HDassert(loc); + HDassert(rc); + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header") + + /* Save the refcount for the object header */ + *rc = oh->nlink; + +done: + /* Release the object header */ + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_expunge_chunks_test() */ + diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index b924b61..e109f95 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -302,6 +302,19 @@ H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id) if(H5T_commit(loc.oloc->file, type, tcpl_id, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype") + /* Release the datatype's object header */ + { + H5O_loc_t *oloc; /* Object location for datatype */ + + /* Get the new committed datatype's object location */ + if(NULL == (oloc = H5T_oloc(type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get object location of committed datatype") + + /* Decrement refcount on committed datatype's object header in memory */ + if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") + } /* end if */ + done: FUNC_LEAVE_API(ret_value) } /* end H5Tcommit_anon() */ @@ -379,7 +392,7 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id) * Create the object header and open it for write access. Insert the data * type message and then give the object header a name. */ - if(H5O_create(file, dxpl_id, dtype_size, tcpl_id, &temp_oloc) < 0) + if(H5O_create(file, dxpl_id, dtype_size, (size_t)1, tcpl_id, &temp_oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header") if(H5O_msg_create(&temp_oloc, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, type, dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") @@ -415,6 +428,8 @@ done: H5G_name_free(&temp_path); } /* end if */ if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED)) { + if(H5O_dec_rc_by_loc(&(type->oloc), dxpl_id) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object") if(H5O_close(&(type->oloc)) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header") if(H5O_delete(file, dxpl_id, type->sh_loc.u.loc.oh_addr) < 0) |