diff options
-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() */ |