[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
This commit is contained in:
Quincey Koziol 2005-10-03 00:50:05 -05:00
parent c13178a42d
commit e21f821fc3
11 changed files with 555 additions and 17 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

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

View File

@ -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 */

View File

@ -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 */

View File

@ -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
*/

View File

@ -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");

View File

@ -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));

View File

@ -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")

View File

@ -1633,6 +1633,173 @@ test_file_getname(void)
} /* end test_file_getname() */
/****************************************************************
**
** 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() */