summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-10-03 05:50:05 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-10-03 05:50:05 (GMT)
commite21f821fc3cf10a549ccb849174b8a5a8f7cc90a (patch)
tree200ec069508aa5b2f831cfda31c0b239a0f5d1cc /src
parentc13178a42d007a4fb209d9b07bc2b018ac2756e4 (diff)
downloadhdf5-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
Diffstat (limited to 'src')
-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
9 files changed, 382 insertions, 17 deletions
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")