diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-10-03 05:50:05 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-10-03 05:50:05 (GMT) |
commit | e21f821fc3cf10a549ccb849174b8a5a8f7cc90a (patch) | |
tree | 200ec069508aa5b2f831cfda31c0b239a0f5d1cc | |
parent | c13178a42d007a4fb209d9b07bc2b018ac2756e4 (diff) | |
download | hdf5-e21f821fc3cf10a549ccb849174b8a5a8f7cc90a.zip hdf5-e21f821fc3cf10a549ccb849174b8a5a8f7cc90a.tar.gz hdf5-e21f821fc3cf10a549ccb849174b8a5a8f7cc90a.tar.bz2 |
[svn-r11490] Purpose:
Bug fix
Description:
Fix "double root open" bug and apply same fix to datasets & named datatypes.
Also fix bug in symbol table entry lookup code that would "transfer" an
object from one file handle to another file handle when the two file handles
were opened on the same actual file.
Platforms tested:
FreeBSD 4.11 (sleipnir)
Too minor to require h5committest
-rw-r--r-- | release_docs/RELEASE.txt | 2 | ||||
-rw-r--r-- | src/H5D.c | 36 | ||||
-rw-r--r-- | src/H5F.c | 6 | ||||
-rw-r--r-- | src/H5FO.c | 245 | ||||
-rw-r--r-- | src/H5FOprivate.h | 5 | ||||
-rw-r--r-- | src/H5Fpkg.h | 1 | ||||
-rw-r--r-- | src/H5G.c | 36 | ||||
-rw-r--r-- | src/H5Gnode.c | 7 | ||||
-rw-r--r-- | src/H5T.c | 61 | ||||
-rw-r--r-- | src/H5Tcommit.c | 2 | ||||
-rw-r--r-- | test/tfile.c | 171 |
11 files changed, 555 insertions, 17 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 4f7e5ea..ccd162f 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -372,6 +372,8 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Fixed core dump when closing root groups opened through two different + file handles that operate on the same actual file. QAK - 2005/10/02 - Corrected errors when performing various operations on a group opened by dereferencing an object reference. QAK - 2005/07/30 - Fixed a bug with named datatypes where a copy of a named datatype @@ -2397,6 +2397,8 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset") /* Add the dataset to the list of opened objects in the file */ + if(H5FO_top_incr(new_dset->ent.file, new_dset->ent.header)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count") if(H5FO_insert(new_dset->ent.file,new_dset->ent.header,new_dset->shared)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects") @@ -2535,19 +2537,34 @@ H5D_open(const H5G_entry_t *ent, hid_t dxpl_id) if(H5FO_insert(dataset->ent.file,dataset->ent.header,dataset->shared)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects") + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dataset->ent.file, dataset->ent.header) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count") + dataset->shared->fo_count = 1; } /* end if */ else { - shared_fo->fo_count++; - if(NULL == (dataset = H5FL_CALLOC(H5D_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for dataset") - dataset->shared=shared_fo; - /* Shallow copy (take ownership) of the group entry object */ if(H5G_ent_copy(&(dataset->ent),ent,H5G_COPY_SHALLOW)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy group entry") + + dataset->shared=shared_fo; + + shared_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(dataset->ent.file, dataset->ent.header) == 0) { + /* Open the object through this top file */ + if(H5O_open(&(dataset->ent)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dataset->ent.file, dataset->ent.header) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count") } /* end else */ ret_value = dataset; @@ -2942,6 +2959,8 @@ H5D_close(H5D_t *dataset) H5I_dec_ref(dataset->shared->dcpl_id) < 0); /* Remove the dataset from the list of opened objects in the file */ + if(H5FO_top_decr(dataset->ent.file, dataset->ent.header) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") if(H5FO_delete(dataset->ent.file, H5AC_dxpl_id, dataset->ent.header)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects") @@ -2962,6 +2981,15 @@ H5D_close(H5D_t *dataset) } /* end if */ else { + /* Decrement the ref. count for this object in the top file */ + if(H5FO_top_decr(dataset->ent.file, dataset->ent.header) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") + + /* Check reference count for this object in the top file */ + if(H5FO_top_count(dataset->ent.file, dataset->ent.header) == 0) + if(H5O_close(&(dataset->ent)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to close") + if(H5G_free_ent_name(&dataset->ent)<0) free_failed=TRUE; } /* end else */ @@ -1532,6 +1532,10 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) f->shared->nrefs++; + /* Create the file's "top open object" information */ + if(H5FO_top_create(f)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") + /* Set return value */ ret_value = f; @@ -1651,6 +1655,8 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) f->name = H5MM_xfree(f->name); f->mtab.child = H5MM_xfree(f->mtab.child); f->mtab.nalloc = 0; + if(H5FO_top_dest(f) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file") H5FL_FREE(H5F_t,f); FUNC_LEAVE_NOAPI(ret_value) @@ -31,16 +31,25 @@ /* Private typedefs */ -/* Information about object objects in a file */ +/* Information about open objects in a file */ typedef struct H5FO_open_obj_t { haddr_t addr; /* Address of object header for object */ void *obj; /* Pointer to the object */ hbool_t deleted; /* Flag to indicate that the object was deleted from the file */ } H5FO_open_obj_t; +/* Information about counted objects in a file */ +typedef struct H5FO_obj_count_t { + haddr_t addr; /* Address of object header for object */ + hsize_t count; /* Number of times object is opened */ +} H5FO_obj_count_t; + /* Declare a free list to manage the H5FO_open_obj_t struct */ H5FL_DEFINE_STATIC(H5FO_open_obj_t); +/* Declare a free list to manage the H5FO_obj_count_t struct */ +H5FL_DEFINE_STATIC(H5FO_obj_count_t); + /*-------------------------------------------------------------------------- NAME @@ -322,7 +331,7 @@ H5FO_marked(const H5F_t *f, haddr_t addr) PURPOSE Destroy an open object info set USAGE - herr_t H5FO_create(f) + herr_t H5FO_dest(f) H5F_t *f; IN/OUT: File's opened object info set RETURNS @@ -360,3 +369,235 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_dest() */ + +/*-------------------------------------------------------------------------- + NAME + H5FO_top_create + PURPOSE + Create the "top" open object count set + USAGE + herr_t H5FO_create(f) + H5F_t *f; IN/OUT: File to create opened object count set for + + RETURNS + Returns non-negative on success, negative on failure + DESCRIPTION + Create a new open object count set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_top_create(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_top_create, FAIL) + + /* Sanity check */ + HDassert(f); + + /* Create container used to store open object info */ + if((f->obj_count = H5SL_create(H5SL_TYPE_HADDR, 0.5, 16)) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_top_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_top_incr + PURPOSE + Increment the "top" reference count for an object in a file + USAGE + herr_t H5FO_top_incr(f, addr) + H5F_t *f; IN/OUT: File's opened object info set + haddr_t addr; IN: Address of object to increment + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Increment the reference count for an object in the opened object count set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_top_incr(const H5F_t *f, haddr_t addr) +{ + H5FO_obj_count_t *obj_count; /* Ref. count for object */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_top_incr, FAIL) + + /* Sanity check */ + HDassert(f); + HDassert(f->obj_count); + HDassert(H5F_addr_defined(addr)); + + /* Get the object node from the container */ + if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL) { + (obj_count->count)++; + } /* end if */ + else { + /* Allocate new opened object information structure */ + if((obj_count = H5FL_MALLOC(H5FO_obj_count_t)) == NULL) + HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed") + + /* Assign information */ + obj_count->addr = addr; + obj_count->count = 1; + + /* Insert into container */ + if(H5SL_insert(f->obj_count, &obj_count->addr, obj_count) < 0) + HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into container") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_top_incr() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_top_decr + PURPOSE + Decrement the "top" reference count for an object in a file + USAGE + herr_t H5FO_top_decr(f, addr) + H5F_t *f; IN/OUT: File's opened object info set + haddr_t addr; IN: Address of object to decrement + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Decrement the reference count for an object in the opened object count set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_top_decr(const H5F_t *f, haddr_t addr) +{ + H5FO_obj_count_t *obj_count; /* Ref. count for object */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_top_decr, FAIL) + + /* Sanity check */ + HDassert(f); + HDassert(f->obj_count); + HDassert(H5F_addr_defined(addr)); + + /* Get the object node from the container */ + if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL) { + /* Decrement the reference count for the object */ + (obj_count->count)--; + + if(obj_count->count == 0) { + /* Remove from container */ + if((obj_count = H5SL_remove(f->obj_count, &addr)) == NULL) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "can't remove object from container") + + /* Release the object information */ + H5FL_FREE(H5FO_obj_count_t, obj_count); + } /* end if */ + } /* end if */ + else + HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "can't decrement ref. count") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_top_decr() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_top_count + PURPOSE + Return the "top" reference count for an object in a file + USAGE + hsize_t H5FO_top_incr(f, addr) + H5F_t *f; IN/OUT: File's opened object info set + haddr_t addr; IN: Address of object to increment + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Retrieves the reference count for an object in the opened object count set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t +H5FO_top_count(const H5F_t *f, haddr_t addr) +{ + H5FO_obj_count_t *obj_count; /* Ref. count for object */ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FO_top_count) + + /* Sanity check */ + HDassert(f); + HDassert(f->obj_count); + HDassert(H5F_addr_defined(addr)); + + /* Get the object node from the container */ + if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL) + ret_value = obj_count->count; + else + ret_value = 0; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_top_count() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_top_dest + PURPOSE + Destroy an open object info set + USAGE + herr_t H5FO_top_dest(f) + H5F_t *f; IN/OUT: File's opened object info set + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Destroy an existing open object info set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_top_dest(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_top_dest, FAIL) + + /* Sanity check */ + HDassert(f); + HDassert(f->obj_count); + + /* Check if the object count set is empty */ + if(H5SL_count(f->obj_count) != 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set") + + /* Release the open object count set container */ + if(H5SL_close(f->obj_count) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTCLOSEOBJ, FAIL, "can't close open object info set") + + f->obj_count = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_top_dest() */ + diff --git a/src/H5FOprivate.h b/src/H5FOprivate.h index 8217907..f5b7691 100644 --- a/src/H5FOprivate.h +++ b/src/H5FOprivate.h @@ -42,6 +42,11 @@ H5_DLL herr_t H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); H5_DLL herr_t H5FO_mark(const H5F_t *f, haddr_t addr, hbool_t deleted); H5_DLL htri_t H5FO_marked(const H5F_t *f, haddr_t addr); H5_DLL herr_t H5FO_dest(const H5F_t *f); +H5_DLL herr_t H5FO_top_create(H5F_t *f); +H5_DLL herr_t H5FO_top_incr(const H5F_t *f, haddr_t addr); +H5_DLL herr_t H5FO_top_decr(const H5F_t *f, haddr_t addr); +H5_DLL hsize_t H5FO_top_count(const H5F_t *f, haddr_t addr); +H5_DLL herr_t H5FO_top_dest(H5F_t *f); #endif /* _H5FOprivate_H */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 4458c7a..4cac069 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -148,6 +148,7 @@ struct H5F_t { char *name; /* Name used to open file */ H5F_file_t *shared; /* The shared file info */ unsigned nopen_objs; /* Number of open object headers*/ + H5FO_t *obj_count; /* # of time each object is opened through top file structure */ hid_t file_id; /* ID of this file */ hbool_t closing; /* File is in the process of being closed */ H5F_mtab_t mtab; /* File mount table */ @@ -1960,6 +1960,8 @@ H5G_create(H5G_entry_t *loc, const char *name, HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group"); /* Add group to list of open objects in file */ + if(H5FO_top_incr(grp->ent.file, grp->ent.header)<0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't incr object ref. count") if(H5FO_insert(grp->ent.file, grp->ent.header, grp->shared)<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects") @@ -2110,6 +2112,10 @@ H5G_open(H5G_entry_t *ent, hid_t dxpl_id) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects") } + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(grp->ent.file, grp->ent.header) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count") + /* Set open object count */ grp->shared->fo_count = 1; } @@ -2119,13 +2125,24 @@ H5G_open(H5G_entry_t *ent, hid_t dxpl_id) /* Shallow copy (take ownership) of the group entry object */ if(H5G_ent_copy(&(grp->ent), ent, H5G_COPY_SHALLOW)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTCOPY, NULL, "can't copy group entry") + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy group entry") /* Point to shared group info */ grp->shared = shared_fo; /* Increment shared reference count */ shared_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(grp->ent.file, grp->ent.header) == 0) { + /* Open the object through this top file */ + if(H5O_open(&(grp->ent)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(grp->ent.file, grp->ent.header) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count") } /* Set return value */ @@ -2237,13 +2254,24 @@ H5G_close(H5G_t *grp) if (0 == grp->shared->fo_count) { assert (grp!=H5G_rootof(H5G_fileof(grp))); - /* Remove the dataset from the list of opened objects in the file */ + /* Remove the group from the list of opened objects in the file */ + if(H5FO_top_decr(grp->ent.file, grp->ent.header) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object") if(H5FO_delete(grp->ent.file, H5AC_dxpl_id, grp->ent.header)<0) HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") - if (H5O_close(&(grp->ent)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); + if(H5O_close(&(grp->ent)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") H5FL_FREE (H5G_shared_t, grp->shared); } else { + /* Decrement the ref. count for this object in the top file */ + if(H5FO_top_decr(grp->ent.file, grp->ent.header) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object") + + /* Check reference count for this object in the top file */ + if(H5FO_top_count(grp->ent.file, grp->ent.header) == 0) + if(H5O_close(&(grp->ent)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") + /* If this group is a mount point and the mount point is the last open * reference to the group, then attempt to close down the file hierarchy */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index f21d0fd..faff6ba 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -996,6 +996,13 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key if (H5G_ent_copy(udata->ent, &sn->entry[idx], H5G_COPY_NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to copy entry"); + /* Leave object in same file as lookup occurs in */ + /* If a file is opened through different H5Fopen() calls, the symbol + * table entry from the B-tree lookup ("&sn->entry[idx]" above) will be + * in the "first" file, but the lookup might occur in the second file. - QAK + */ + udata->ent->file = f; + done: if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node"); @@ -3109,6 +3109,10 @@ H5T_open (H5G_entry_t *ent, hid_t dxpl_id) if(H5FO_insert(dt->ent.file, dt->ent.header, dt->shared)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dt->ent.file, dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + /* Mark any datatypes as being in memory now */ if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") @@ -3117,16 +3121,27 @@ H5T_open (H5G_entry_t *ent, hid_t dxpl_id) } else { - shared_fo->fo_count++; - if(NULL == (dt = H5FL_MALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype") - dt->shared=shared_fo; - /* Shallow copy (take ownership) of the group entry object */ if(H5G_ent_copy(&(dt->ent),ent,H5G_COPY_SHALLOW)<0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy group entry") + + dt->shared=shared_fo; + + shared_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(dt->ent.file, dt->ent.header) == 0) { + /* Open the object through this top file */ + if(H5O_open(&(dt->ent)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dt->ent.file, dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } ret_value = dt; @@ -3298,6 +3313,10 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) if(H5FO_insert(old_dt->ent.file, old_dt->ent.header, new_dt->shared)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + new_dt->shared->fo_count=1; } else { /* The object is already open. Free the H5T_shared_t struct @@ -3307,6 +3326,17 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) new_dt->shared = reopened_fo; reopened_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(old_dt->ent.file, old_dt->ent.header) == 0) { + /* Open the object through this top file */ + if(H5O_open(&(old_dt->ent)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } new_dt->shared->state = H5T_STATE_OPEN; } else if (H5T_STATE_IMMUTABLE==old_dt->shared->state) { @@ -3572,10 +3602,12 @@ H5T_free(H5T_t *dt) if (H5T_STATE_OPEN==dt->shared->state) { assert (H5F_addr_defined(dt->ent.header)); /* Remove the datatype from the list of opened objects in the file */ + if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") if(H5FO_delete(dt->ent.file, H5AC_dxpl_id, dt->ent.header)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't remove datatype from list of open objects") if (H5O_close(&(dt->ent))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header"); dt->shared->state = H5T_STATE_NAMED; } @@ -3657,14 +3689,29 @@ H5T_close(H5T_t *dt) assert(dt && dt->shared); - if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 1) + dt->shared->fo_count--; + + if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 0) { if(H5T_free(dt)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); H5FL_FREE(H5T_shared_t, dt->shared); } else { - dt->shared->fo_count--; + /* + * If a named type is being closed then close the object header and + * remove from the list of open objects in the file. + */ + if(H5T_STATE_OPEN==dt->shared->state) { + /* Decrement the ref. count for this object in the top file */ + if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") + + /* Check reference count for this object in the top file */ + if(H5FO_top_count(dt->ent.file, dt->ent.header) == 0) + if(H5O_close(&(dt->ent)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close") + } /* end if */ /* Free the ID to name info since we're not calling H5T_free*/ H5G_free_ent_name(&(dt->ent)); diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 030701e..098450d 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -242,6 +242,8 @@ H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, type->shared->fo_count=1; /* Add datatype to the list of open objects in the file */ + if(H5FO_top_incr(type->ent.file, type->ent.header)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't incr object ref. count") if(H5FO_insert(type->ent.file, type->ent.header, type->shared)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert datatype into list of open objects") diff --git a/test/tfile.c b/test/tfile.c index ea8a7c4..586dd59 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -1635,6 +1635,173 @@ test_file_getname(void) /**************************************************************** ** +** test_file_double_root_open(): low-level file test routine. +** This test checks whether opening the root group from two +** different files works correctly. +** +*****************************************************************/ +static void +test_file_double_root_open(void) +{ + hid_t file1_id, file2_id; + hid_t grp1_id, grp2_id; + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing double root group open\n")); + + file1_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1_id, FAIL, "H5Fcreate"); + file2_id = H5Fopen (FILE1, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file2_id, FAIL, "H5Fopen"); + + grp1_id = H5Gopen(file1_id, "/"); + CHECK(grp1_id, FAIL, "H5Gopen"); + grp2_id = H5Gopen(file2_id, "/"); + CHECK(grp2_id, FAIL, "H5Gopen"); + + /* Note "assymetric" close order */ + ret = H5Gclose(grp1_id); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Gclose(grp2_id); + CHECK(ret, FAIL, "H5Gclose"); + + ret = H5Fclose(file1_id); + CHECK(ret, FAIL, "H5Fclose"); + ret = H5Fclose(file2_id); + CHECK(ret, FAIL, "H5Fclose"); +} /* end test_file_double_root_open() */ + +/**************************************************************** +** +** test_file_double_group_open(): low-level file test routine. +** This test checks whether opening the same group from two +** different files works correctly. +** +*****************************************************************/ +static void +test_file_double_group_open(void) +{ + hid_t file1_id, file2_id; + hid_t grp1_id, grp2_id; + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing double non-root group open\n")); + + file1_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1_id, FAIL, "H5Fcreate"); + file2_id = H5Fopen (FILE1, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file2_id, FAIL, "H5Fopen"); + + grp1_id = H5Gcreate(file1_id, GRP_NAME, (size_t)0); + CHECK(grp1_id, FAIL, "H5Gcreate"); + grp2_id = H5Gopen(file2_id, GRP_NAME); + CHECK(grp2_id, FAIL, "H5Gopen"); + + /* Note "assymetric" close order */ + ret = H5Gclose(grp1_id); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Gclose(grp2_id); + CHECK(ret, FAIL, "H5Gclose"); + + ret = H5Fclose(file1_id); + CHECK(ret, FAIL, "H5Fclose"); + ret = H5Fclose(file2_id); + CHECK(ret, FAIL, "H5Fclose"); +} /* end test_file_double_group_open() */ + +/**************************************************************** +** +** test_file_double_dataset_open(): low-level file test routine. +** This test checks whether opening the same dataset from two +** different files works correctly. +** +*****************************************************************/ +static void +test_file_double_dataset_open(void) +{ + hid_t file1_id, file2_id; + hid_t dset1_id, dset2_id; + hid_t space_id; + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing double dataset open\n")); + + file1_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1_id, FAIL, "H5Fcreate"); + file2_id = H5Fopen (FILE1, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file2_id, FAIL, "H5Fopen"); + + /* Create dataspace for dataset */ + space_id = H5Screate(H5S_SCALAR); + CHECK(space_id, FAIL, "H5Screate"); + + dset1_id = H5Dcreate(file1_id, DSET_NAME, H5T_NATIVE_INT, space_id, H5P_DEFAULT); + CHECK(dset1_id, FAIL, "H5Dcreate"); + dset2_id = H5Dopen(file2_id, DSET_NAME); + CHECK(dset2_id, FAIL, "H5Dopen"); + + /* Close "supporting" dataspace */ + ret = H5Sclose(space_id); + CHECK(ret, FAIL, "H5Sclose"); + + /* Note "assymetric" close order */ + ret = H5Dclose(dset1_id); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Dclose(dset2_id); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Fclose(file1_id); + CHECK(ret, FAIL, "H5Fclose"); + ret = H5Fclose(file2_id); + CHECK(ret, FAIL, "H5Fclose"); +} /* end test_file_double_dataset_open() */ + +/**************************************************************** +** +** test_file_double_datatype_open(): low-level file test routine. +** This test checks whether opening the same named datatype from two +** different files works correctly. +** +*****************************************************************/ +static void +test_file_double_datatype_open(void) +{ + hid_t file1_id, file2_id; + hid_t type1_id, type2_id; + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing double dataset open\n")); + + file1_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1_id, FAIL, "H5Fcreate"); + file2_id = H5Fopen (FILE1, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file2_id, FAIL, "H5Fopen"); + + type1_id = H5Tcopy(H5T_NATIVE_INT); + CHECK(type1_id, FAIL, "H5Tcopy"); + ret = H5Tcommit(file1_id, TYPE_NAME, type1_id); + CHECK(ret, FAIL, "H5Tcommit"); + type2_id = H5Topen(file2_id, TYPE_NAME); + CHECK(type2_id, FAIL, "H5Topen"); + + /* Note "assymetric" close order */ + ret = H5Tclose(type1_id); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Tclose(type2_id); + CHECK(ret, FAIL, "H5Tclose"); + + ret = H5Fclose(file1_id); + CHECK(ret, FAIL, "H5Fclose"); + ret = H5Fclose(file2_id); + CHECK(ret, FAIL, "H5Fclose"); +} /* end test_file_double_dataset_open() */ + +/**************************************************************** +** ** test_file(): Main low-level file I/O test routine. ** ****************************************************************/ @@ -1656,6 +1823,10 @@ test_file(void) test_file_open_dot(); /* Test opening objects with "." for a name */ test_file_open_overlap(); /* Test opening files in an overlapping manner */ test_file_getname(); /* Test basic H5Fget_name() functionality */ + test_file_double_root_open(); /* Test opening root group from two files works properly */ + test_file_double_group_open(); /* Test opening same group from two files works properly */ + test_file_double_dataset_open(); /* Test opening same dataset from two files works properly */ + test_file_double_datatype_open(); /* Test opening same named datatype from two files works properly */ } /* test_file() */ |