summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5D.c36
-rw-r--r--src/H5F.c6
-rw-r--r--src/H5FO.c245
-rw-r--r--src/H5FOprivate.h5
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5G.c36
-rw-r--r--src/H5Gnode.c7
-rw-r--r--src/H5T.c61
-rw-r--r--src/H5Tcommit.c2
-rw-r--r--test/tfile.c171
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
diff --git a/src/H5D.c b/src/H5D.c
index 400d41e..4f7ea5d 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -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 */
diff --git a/src/H5F.c b/src/H5F.c
index cd75a2f..9665e1a 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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)
diff --git a/src/H5FO.c b/src/H5FO.c
index d59b207..762c5a9 100644
--- a/src/H5FO.c
+++ b/src/H5FO.c
@@ -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 */
diff --git a/src/H5G.c b/src/H5G.c
index 67ccf3c..e7fc1cf 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -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");
diff --git a/src/H5T.c b/src/H5T.c
index df98c7c..59ae47d 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -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() */