summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-07-21 14:49:11 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-07-21 14:49:11 (GMT)
commit1e2ddfc8b1847c4b1f67c764d4920c5d1e0c538d (patch)
tree60e8d8ee4b4fa77ef7a01ebf106d53b9d7675a32
parentc9b45e24d5f1935d5356cf90f0521d1e82efc4e3 (diff)
downloadhdf5-1e2ddfc8b1847c4b1f67c764d4920c5d1e0c538d.zip
hdf5-1e2ddfc8b1847c4b1f67c764d4920c5d1e0c538d.tar.gz
hdf5-1e2ddfc8b1847c4b1f67c764d4920c5d1e0c538d.tar.bz2
[svn-r11094] Purpose:
Bug fix Description: Rewrite code for mounting files to clean up layers of kludges and implement a much cleaner and more maintainable design. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4
-rw-r--r--MANIFEST1
-rw-r--r--release_docs/RELEASE.txt8
-rw-r--r--src/H5.c84
-rw-r--r--src/H5D.c17
-rw-r--r--src/H5F.c714
-rw-r--r--src/H5Fmount.c195
-rw-r--r--src/H5Fpkg.h9
-rw-r--r--src/H5Fprivate.h4
-rw-r--r--src/H5G.c90
-rw-r--r--src/H5Gpkg.h3
-rw-r--r--src/H5Gprivate.h2
-rw-r--r--src/H5I.c37
-rw-r--r--src/H5Iprivate.h1
-rw-r--r--src/H5Ipublic.h1
-rw-r--r--src/H5O.c31
-rw-r--r--test/Makefile.in10
-rw-r--r--test/filename.c154
-rw-r--r--test/mount.c715
-rw-r--r--test/testhdf5.h15
-rw-r--r--test/tfile.c155
20 files changed, 1507 insertions, 739 deletions
diff --git a/MANIFEST b/MANIFEST
index 798868f..4c9d4a8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1267,7 +1267,6 @@
./test/family_v1.7_00002.h5
./test/family_v1.7_00003.h5
./test/file_handle.c
-./test/filename.c
./test/fill_old.h5
./test/fillval.c
./test/flush1.c
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 50a08ce..982345c 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -72,6 +72,14 @@ Bug Fixes since HDF5-1.6.4 release
Library
-------
+ - Made H5Fget_name() be consistent and always return name of actual
+ file the ID is in. (Instead of the name of the top file in a
+ file mounting hierarchy). QAK - 2005/07/19
+ - Reworked internal file mounting semantics to hopefully eliminate
+ mounting problems. We now require that files that are mounting
+ together all have the same "file close degree". QAK - 2005/07/19
+ - More bug fixes on holding open files that are mounted and have
+ IDs open. QAK - 2005/07/14
- More bug fixes on holding open files that are mounted and have
IDs open. QAK - 2005/07/14
- Dataset sieve buffer cache was inadvertantly disabled - re-enable
diff --git a/src/H5.c b/src/H5.c
index ae4fbdc..e563e46 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -2054,9 +2054,6 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5I_FILE:
fprintf(out, "%ld (file)", (long)obj);
break;
- case H5I_FILE_CLOSING:
- fprintf(out, "%ld (file closing)", (long)obj);
- break;
case H5I_GROUP:
fprintf(out, "%ld (group)", (long)obj);
break;
@@ -2247,48 +2244,45 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
} else {
H5I_type_t id_type = va_arg (ap, H5I_type_t); /*lint !e64 Type mismatch not really occuring */
switch (id_type) {
- case H5I_BADID:
- fprintf (out, "H5I_BADID");
- break;
- case H5I_FILE:
- fprintf (out, "H5I_FILE");
- break;
- case H5I_FILE_CLOSING:
- fprintf (out, "H5I_FILE_CLOSING");
- break;
- case H5I_GROUP:
- fprintf (out, "H5I_GROUP");
- break;
- case H5I_DATATYPE:
- fprintf (out, "H5I_DATATYPE");
- break;
- case H5I_DATASPACE:
- fprintf (out, "H5I_DATASPACE");
- break;
- case H5I_DATASET:
- fprintf (out, "H5I_DATASET");
- break;
- case H5I_ATTR:
- fprintf (out, "H5I_ATTR");
- break;
- case H5I_REFERENCE:
- fprintf (out, "H5I_REFERENCE");
- break;
- case H5I_VFL:
- fprintf (out, "H5I_VFL");
- break;
- case H5I_GENPROP_CLS:
- fprintf (out, "H5I_GENPROP_CLS");
- break;
- case H5I_GENPROP_LST:
- fprintf (out, "H5I_GENPROP_LST");
- break;
- case H5I_NGROUPS:
- fprintf (out, "H5I_NGROUPS");
- break;
- default:
- fprintf (out, "%ld", (long)id_type);
- break;
+ case H5I_BADID:
+ fprintf (out, "H5I_BADID");
+ break;
+ case H5I_FILE:
+ fprintf (out, "H5I_FILE");
+ break;
+ case H5I_GROUP:
+ fprintf (out, "H5I_GROUP");
+ break;
+ case H5I_DATATYPE:
+ fprintf (out, "H5I_DATATYPE");
+ break;
+ case H5I_DATASPACE:
+ fprintf (out, "H5I_DATASPACE");
+ break;
+ case H5I_DATASET:
+ fprintf (out, "H5I_DATASET");
+ break;
+ case H5I_ATTR:
+ fprintf (out, "H5I_ATTR");
+ break;
+ case H5I_REFERENCE:
+ fprintf (out, "H5I_REFERENCE");
+ break;
+ case H5I_VFL:
+ fprintf (out, "H5I_VFL");
+ break;
+ case H5I_GENPROP_CLS:
+ fprintf (out, "H5I_GENPROP_CLS");
+ break;
+ case H5I_GENPROP_LST:
+ fprintf (out, "H5I_GENPROP_LST");
+ break;
+ case H5I_NGROUPS:
+ fprintf (out, "H5I_NGROUPS");
+ break;
+ default:
+ fprintf (out, "%ld", (long)id_type);
+ break;
}
}
break;
diff --git a/src/H5D.c b/src/H5D.c
index 2a063b8..cd63c53 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -3989,8 +3989,6 @@ done:
*
* Date: August 14, 2002
*
- * Comments: Just flushing the compact data information currently.
- *
* Modifications:
*
*-------------------------------------------------------------------------
@@ -3998,11 +3996,11 @@ done:
herr_t
H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags)
{
- int num_dsets; /* Number of datasets in file */
+ unsigned num_dsets; /* Number of datasets in file */
hid_t *id_list=NULL; /* list of dataset IDs */
H5D_t *dataset=NULL; /* Dataset pointer */
+ unsigned u; /* Index variable */
herr_t ret_value = SUCCEED; /* Return value */
- int j; /* Index variable */
FUNC_ENTER_NOAPI(H5D_flush, FAIL)
@@ -4010,18 +4008,17 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags)
assert(f);
/* Update layout message for compact dataset */
- if((num_dsets=H5F_get_obj_count(f, H5F_OBJ_DATASET))<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset count")
+ num_dsets=H5F_get_obj_count(f, H5F_OBJ_DATASET);
/* Check for something to do */
if(num_dsets>0) {
- H5_CHECK_OVERFLOW(num_dsets,int,size_t);
+ H5_CHECK_OVERFLOW(num_dsets,unsigned,size_t);
if(NULL==(id_list=H5MM_malloc((size_t)num_dsets*sizeof(hid_t))))
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate memory for ID list")
- if(H5F_get_obj_ids(f, H5F_OBJ_DATASET, -1, id_list)<0)
+ if(H5F_get_obj_ids(f, H5F_OBJ_DATASET, -1, id_list) != num_dsets)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset ID list")
- for(j=0; j<num_dsets; j++) {
- if(NULL==(dataset=H5I_object_verify(id_list[j], H5I_DATASET)))
+ for(u = 0; u < num_dsets; u++) {
+ if(NULL==(dataset=H5I_object_verify(id_list[u], H5I_DATASET)))
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset object")
/* Flush the raw data buffer, if we have a dirty one */
diff --git a/src/H5F.c b/src/H5F.c
index dd940c8..e441246 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -61,6 +61,12 @@ typedef struct H5F_olist_t {
int max_index; /* Maximum # of IDs to put into array */
} H5F_olist_t;
+/* Struct for tracking "shared" file structs */
+typedef struct H5F_sfile_node_t {
+ H5F_file_t *shared; /* Pointer to "shared" struct */
+ struct H5F_sfile_node_t *next; /* Pointer to next node */
+} H5F_sfile_node_t;
+
/* PRIVATE PROTOTYPES */
static H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id,
hid_t fapl_id, hid_t dxpl_id);
@@ -70,19 +76,31 @@ static herr_t H5F_flush_all(hbool_t invalidate);
static int H5F_flush_all_cb(void *f, hid_t fid, void *_invalidate);
#endif /* NOT_YET */
+static herr_t H5F_close(H5F_t *f);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id);
static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id);
static herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags);
-static int H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
+static unsigned H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle);
+/* Routines to operate on the shared file list */
+static herr_t H5F_shared_add(H5F_file_t *shared);
+static H5F_file_t * H5F_shared_search(H5FD_t *lf);
+static herr_t H5F_shared_remove(H5F_file_t *shared);
+
/* Declare a free list to manage the H5F_t struct */
H5FL_DEFINE_STATIC(H5F_t);
/* Declare a free list to manage the H5F_file_t struct */
H5FL_DEFINE_STATIC(H5F_file_t);
+/* Declare a free list to manage the H5F_sfile_node_t struct */
+H5FL_DEFINE_STATIC(H5F_sfile_node_t);
+
+/* Declare a local variable to track the shared file information */
+H5F_sfile_node_t *H5F_sfile_head_g = NULL;
+
/*-------------------------------------------------------------------------
* Function: H5F_init
@@ -222,8 +240,7 @@ H5F_init_interface(void)
* which are pending completion because there are object headers still
* open within the file.
*/
- if (H5I_init_group(H5I_FILE, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0 ||
- H5I_init_group(H5I_FILE_CLOSING, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0)
+ if (H5I_init_group(H5I_FILE, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0)
HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
/* ========== File Creation Property Class Initialization ============*/
@@ -424,13 +441,11 @@ H5F_term_interface(void)
if (H5_interface_initialize_g) {
if ((n=H5I_nmembers(H5I_FILE))!=0) {
H5I_clear_group(H5I_FILE, FALSE);
- } else if ((n=H5I_nmembers(H5I_FILE_CLOSING))!=0) {
- /* Attempt to unmount any child files from files that are closing */
- (void)H5I_search(H5I_FILE_CLOSING, H5F_term_unmount_cb, NULL);
- }
- else {
+ } else {
+ /* Make certain we've cleaned up all the shared file objects */
+ HDassert(H5F_sfile_head_g == NULL);
+
H5I_destroy_group(H5I_FILE);
- H5I_destroy_group(H5I_FILE_CLOSING);
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
}
@@ -899,17 +914,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-int
+unsigned
H5F_get_obj_count(const H5F_t *f, unsigned types)
{
- int ret_value; /* Return value */
+ unsigned ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5F_get_obj_count)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_count)
- if((ret_value=H5F_get_objects(f, types, -1, NULL)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get counts of opened file IDs and object IDs in the file")
+ ret_value=H5F_get_objects(f, types, -1, NULL);
-done:
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -951,7 +964,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_object_ids
+ * Function: H5F_get_obj_ids
*
* Purpose: Private function to return a list of opened object IDs.
*
@@ -964,17 +977,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-int
+unsigned
H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *oid_list)
{
- int ret_value; /* Return value */
+ unsigned ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5F_get_obj_ids)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_ids)
- if((ret_value=H5F_get_objects(f, types, max_objs, oid_list)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object IDs opened in the file")
+ ret_value = H5F_get_objects(f, types, max_objs, oid_list);
-done:
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -994,12 +1005,12 @@ done:
*
*---------------------------------------------------------------------------
*/
-static int
+static unsigned
H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_list)
{
unsigned obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
- int ret_value; /* Return value */
+ unsigned ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_objects)
@@ -1021,45 +1032,42 @@ H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_lis
/* Search through file IDs to count the number, and put their
* IDs on the object list */
- if( (types & H5F_OBJ_FILE) && H5I_nmembers(H5I_FILE) > 0 ) {
+ if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
(void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist);
- }
+ } /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
- if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_DATASET) && H5I_nmembers(H5I_DATASET) > 0 ) {
+ if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_DATASET) ) {
olist.obj_type = H5I_DATASET;
(void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist);
}
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
- if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_GROUP) && H5I_nmembers(H5I_GROUP) > 0 ) {
+ if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_GROUP) ) {
olist.obj_type = H5I_GROUP;
(void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist);
}
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
- if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_DATATYPE) && H5I_nmembers(H5I_DATATYPE) > 0 ) {
+ if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_DATATYPE) ) {
olist.obj_type = H5I_DATATYPE;
(void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist);
}
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
- if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_ATTR) && H5I_nmembers(H5I_ATTR) > 0 ) {
+ if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_ATTR) ) {
olist.obj_type = H5I_ATTR;
(void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist);
}
/* Set the number of objects currently open */
- H5_ASSIGN_OVERFLOW(ret_value,obj_id_count,unsigned,int);
+ ret_value = obj_id_count;
-#ifdef LATER
-done:
-#endif /* LATER */
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -1233,39 +1241,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_equal
- *
- * Purpose: Compares NEEDLE to a file from the HAYSTACK.
- *
- * Return: Success: Returns positive if two files are equal,
- * zero otherwise.
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Monday, August 2, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5F_equal(void *_haystack, hid_t UNUSED id, void *_needle)
-{
- H5F_t *haystack = (H5F_t*)_haystack;
- const H5FD_t *needle = (const H5FD_t*)_needle;
- int retval;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_equal)
-
- retval = (0==H5FD_cmp(haystack->shared->lf, needle));
-
- FUNC_LEAVE_NOAPI(retval)
-}
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_locate_signature
*
* Purpose: Finds the HDF5 super block signature in a file. The signature
@@ -1415,7 +1390,6 @@ static H5F_t *
H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
{
H5F_t *f=NULL, *ret_value;
- int n;
H5P_genplist_t *plist; /* Property list */
FUNC_ENTER_NOAPI_NOINIT(H5F_new)
@@ -1426,6 +1400,8 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
if (shared) {
f->shared = shared;
} else {
+ int n;
+
f->shared = H5FL_CALLOC(H5F_file_t);
f->shared->super_addr = HADDR_UNDEF;
f->shared->base_addr = HADDR_UNDEF;
@@ -1498,11 +1474,14 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
/* Create the file's "open object" information */
if(H5FO_create(f)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object TBBT")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
+
+ /* Add new "shared" struct to list of open files */
+ if(H5F_shared_add(f->shared) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
} /* end else */
f->shared->nrefs++;
- f->nrefs = 1;
/* Set return value */
ret_value = f;
@@ -1559,77 +1538,83 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
FUNC_ENTER_NOAPI_NOINIT(H5F_dest)
- if (f && 1==f->nrefs) {
- if (1==f->shared->nrefs) {
- /*
- * Do not close the root group since we didn't count it, but free
- * the memory associated with it.
- */
- if (f->shared->root_grp) {
- /* Free the ID to name buffer */
- if(H5G_free_grp_name(f->shared->root_grp)<0) {
- HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
- ret_value = FAIL; /*but keep going*/
- } /* end if */
-
- /* Free the memory for the root group */
- if(H5G_free(f->shared->root_grp)<0) {
- HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
- ret_value = FAIL; /*but keep going*/
- } /* end if */
- f->shared->root_grp=NULL;
- }
- if (H5AC_dest(f, dxpl_id)) {
- HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
- ret_value = FAIL; /*but keep going*/
- }
- if (H5FO_dest(f)<0) {
+ /* Sanity check */
+ HDassert(f);
+
+ if (1==f->shared->nrefs) {
+ /* Remove shared file struct from list of open files */
+ if(H5F_shared_remove(f->shared) < 0) {
+ HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ } /* end if */
+
+ /*
+ * Do not close the root group since we didn't count it, but free
+ * the memory associated with it.
+ */
+ if (f->shared->root_grp) {
+ /* Free the ID to name buffer */
+ if(H5G_free_grp_name(f->shared->root_grp)<0) {
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
ret_value = FAIL; /*but keep going*/
- } /* end if */
- f->shared->cwfs = H5MM_xfree (f->shared->cwfs);
- if (H5G_node_close(f)<0) {
+ } /* end if */
+
+ /* Free the memory for the root group */
+ if(H5G_free(f->shared->root_grp)<0) {
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
ret_value = FAIL; /*but keep going*/
- } /* end if */
-
- /* Destroy file creation properties */
- if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
- if((ret_value=H5I_dec_ref(f->shared->fcpl_id)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close property list")
-
- /* Destroy shared file struct */
- if (H5FD_close(f->shared->lf)<0) {
- HERROR(H5E_FILE, H5E_CANTINIT, "problems closing file");
- ret_value = FAIL; /*but keep going*/
- }
- f->shared = H5FL_FREE(H5F_file_t,f->shared);
-
- } else if (f->shared->nrefs>0) {
- /*
- * There are other references to the shared part of the file.
- * Only decrement the reference count.
- */
- --f->shared->nrefs;
- }
+ } /* end if */
+ f->shared->root_grp=NULL;
+ }
+ if (H5AC_dest(f, dxpl_id)) {
+ HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ }
+ if (H5FO_dest(f)<0) {
+ HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ } /* end if */
+ f->shared->cwfs = H5MM_xfree (f->shared->cwfs);
+ if (H5G_node_close(f)<0) {
+ HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ } /* end if */
- /* Free the non-shared part of the file */
- f->name = H5MM_xfree(f->name);
- f->mtab.child = H5MM_xfree(f->mtab.child);
- f->mtab.nalloc = 0;
- H5FL_FREE(H5F_t,f);
- } else if (f && f->nrefs>0) {
- /*
- * There are other references to this file. Only decrement the
- * reference count.
- */
- --f->nrefs;
+ /* Destroy file creation properties */
+ if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id)) {
+ HERROR(H5E_PLIST, H5E_BADTYPE, "not a property list");
+ ret_value = FAIL; /*but keep going*/
+ } /* end if */
+ if((ret_value=H5I_dec_ref(f->shared->fcpl_id)) < 0) {
+ HERROR(H5E_PLIST, H5E_CANTFREE, "can't close property list");
+ ret_value = FAIL; /*but keep going*/
+ } /* end if */
+
+ /* Close low-level file */
+ if (H5FD_close(f->shared->lf)<0) {
+ HERROR(H5E_FILE, H5E_CANTINIT, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ }
+
+ /* Destroy shared file struct */
+ f->shared = H5FL_FREE(H5F_file_t,f->shared);
+
+ } else if (f->shared->nrefs>0) {
+ /*
+ * There are other references to the shared part of the file.
+ * Only decrement the reference count.
+ */
+ --f->shared->nrefs;
}
-done:
+ /* Free the non-shared part of the file */
+ f->name = H5MM_xfree(f->name);
+ f->mtab.child = H5MM_xfree(f->mtab.child);
+ f->mtab.nalloc = 0;
+ H5FL_FREE(H5F_t,f);
+
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5F_dest() */
/*-------------------------------------------------------------------------
@@ -1767,8 +1752,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
} /* end if */
/* Is the file already open? */
- if ((file=H5I_search(H5I_FILE, H5F_equal, lf))!=NULL ||
- (file=H5I_search(H5I_FILE_CLOSING, H5F_equal, lf))!=NULL) {
+ if ((shared = H5F_shared_search(lf)) != NULL) {
/*
* The file is already open, so use that one instead of the one we
* just opened. We only one one H5FD_t* per file so one doesn't
@@ -1778,24 +1762,17 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
* exists), or if the new request adds write access (since the
* readers don't expect the file to change under them).
*/
- if(H5FD_close(lf)<0) {
- file = NULL; /*to prevent destruction of wrong file*/
+ if(H5FD_close(lf)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
- } /* end if */
- if (flags & H5F_ACC_TRUNC) {
- file = NULL; /*to prevent destruction of wrong file*/
+ if (flags & H5F_ACC_TRUNC)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
- }
- if (flags & H5F_ACC_EXCL) {
- file = NULL; /*to prevent destruction of wrong file*/
+ if (flags & H5F_ACC_EXCL)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
- }
- if ((flags & H5F_ACC_RDWR) && 0==(file->intent & H5F_ACC_RDWR)) {
- file = NULL; /*to prevent destruction of wrong file*/
+ if ((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
- }
- if ((file = H5F_new(file->shared, fcpl_id, fapl_id)) == NULL)
+ /* Allocate new "high-level" file struct */
+ if ((file = H5F_new(shared, fcpl_id, fapl_id)) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
lf = file->shared->lf;
@@ -2384,26 +2361,58 @@ H5F_close(H5F_t *f)
FUNC_ENTER_NOAPI_NOINIT(H5F_close)
- assert(f->nrefs>0);
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
- /*
- * If this file is referenced more than once then just decrement the
- * count and return.
- */
- if (f->nrefs>1) {
- /* Decrement reference counts */
- if (H5F_dest(f, H5AC_dxpl_id)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
- HGOTO_DONE(SUCCEED)
- } /* end if */
+ /* Reset the file ID for this file */
+ f->file_id = -1;
- /* Double-check that this file should be closed */
- assert(1==f->nrefs);
-
- /* if close degree if "semi" and there are objects left open and we are
- * holding open the file with this file ID, fail now */
- if(f->shared->fc_degree==H5F_CLOSE_SEMI && f->nopen_objs>0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
+ /* Attempt to close the file/mount hierarchy */
+ if(H5F_try_close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_try_close
+ *
+ * Purpose: Attempts to close a file due to one of several actions:
+ * - The reference count on the file ID dropped to zero
+ * - The last open object was closed in the file
+ * - The file was unmounted
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_try_close(H5F_t *f)
+{
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_try_close)
+
+ /* Sanity check */
+ HDassert(f);
+
+ /* Check if this file is already in the process of closing */
+ if(f->closing)
+ HGOTO_DONE(SUCCEED)
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
/*
* Close file according to close degree:
@@ -2418,138 +2427,84 @@ H5F_close(H5F_t *f)
switch(f->shared->fc_degree) {
case H5F_CLOSE_WEAK:
/*
- * If object headers are still open then delay deletion of
+ * If file or object IDS are still open then delay deletion of
* resources until they have all been closed. Flush all
- * caches and update the object eader anyway so that failing toi
- * close all objects isn't a major problem. If the file is on
- * the H5I_FILE list then move it to the H5I_FILE_CLOSING list
- * instead.
+ * caches and update the object header anyway so that failing to
+ * close all objects isn't a major problem.
*/
- if (f->nopen_objs>0) {
-#ifdef H5F_DEBUG
- if (H5DEBUG(F)) {
- fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
- "open (file close will complete when %s closed)\n",
- f->name,
- f->nopen_objs,
- 1 == f->nopen_objs?" is":"s are",
- 1 == f->nopen_objs?"that header is":"those headers are");
- }
-#endif
- /* If the only open objects are the groups that are mount points, */
- /* allow the file to close and shut things down */
- if(f->nopen_objs == f->mtab.nmounts) {
- unsigned u; /* Local index variable */
- hbool_t really_close; /* Whether to delay the file close by going to a "closing" state */
-
- /* Check for open groups on mount points */
- really_close = TRUE;
- for(u = 0; u < f->mtab.nmounts; u++) {
- if(H5G_get_shared_count(f->mtab.child[u].group) > 1) {
- really_close = FALSE;
- break;
- } /* end if */
- } /* end for */
-
- /* If we really want to close this file now */
- if(really_close)
- break;
- } /* end if */
-
- /* Register an ID for closing the file later */
- if (!f->closing)
- f->closing = H5I_register(H5I_FILE_CLOSING, f);
-
- /* Invalidate file ID */
- f->file_id = -1;
-
+ if ((nopen_files + nopen_objs) > 0)
HGOTO_DONE(SUCCEED)
- } else {
- if (f->closing) {
-
-#ifdef H5F_DEBUG
- if (H5DEBUG(F))
- fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
-#endif
- } /* end if */
- } /* end else */
break;
case H5F_CLOSE_SEMI:
+ /* Can leave safely if file IDs are still open on this file */
+ if (nopen_files > 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Sanity check: If close degree if "semi" and we have gotten this
+ * far and there are objects left open, bail out now */
+ HDassert(nopen_files == 0 && nopen_objs == 0);
+
/* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */
break;
case H5F_CLOSE_STRONG:
- /* Force to close all opened objects in file */
- while(f->nopen_objs > 0) {
- int obj_count; /* # of open objects */
- hid_t objs[128]; /* Array of objects to close */
- int i; /* Local index variable */
-
- /* Get the list of IDs of open dataset objects */
- while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) {
-
- /* Try to close all the open objects */
- for(i=0; i<obj_count; i++)
- if(H5I_dec_ref(objs[i]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
-
- /* Get the list of IDs of open group objects */
- while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_GROUP, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) {
-
- /* Try to close all the open objects */
- for(i=0; i<obj_count; i++)
- if(H5I_dec_ref(objs[i]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
-
- /* Get the list of IDs of open named datatype objects */
- while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) {
-
- /* Try to close all the open objects */
- for(i=0; i<obj_count; i++)
- if(H5I_dec_ref(objs[i]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
-
- /* Get the list of IDs of open attribute objects */
- while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) {
-
- /* Try to close all the open objects */
- for(i=0; i<obj_count; i++)
- if(H5I_dec_ref(objs[i]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
- } /* end while */
+ /* If there are other open files in the hierarchy, we can leave now */
+ if(nopen_files > 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */
break;
default:
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
} /* end switch */
- /*
- * Unmount and close each child before closing the current file.
- */
- assert(NULL==f->mtab.parent);
- if(H5F_close_mounts(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child file")
+ /* Mark this file as closing (prevents re-entering file shutdown code below) */
+ f->closing = TRUE;
- /* Invalidate file ID */
- f->file_id = -1;
+ /* If the file close degree is "strong", close all the open objects in this file */
+ if(f->shared->fc_degree == H5F_CLOSE_STRONG) {
+ HDassert(nopen_files == 0);
- /* Flush at this point since the file will be closed */
+ /* Forced close of all opened objects in this file */
+ if(f->nopen_objs > 0) {
+ unsigned obj_count; /* # of open objects */
+ hid_t objs[128]; /* Array of objects to close */
+ unsigned u; /* Local index variable */
+
+ /* Get the list of IDs of open dataset, group, named datatype & attribute objects */
+ while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs)) != 0) {
+
+ /* Try to close all the open objects in this file */
+ for(u = 0; u < obj_count; u++)
+ if(H5I_dec_ref(objs[u]) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
+ } /* end while */
+ } /* end if */
+ } /* end if */
+
+ /* Check if this is a child file in a mounting hierarchy & proceed up the
+ * hierarchy if so.
+ */
+ if(f->mtab.parent)
+ if(H5F_try_close(f->mtab.parent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
+
+ /* Unmount and close each child before closing the current file. */
+ if(H5F_close_mounts(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
- /* Dump debugging info */
#if H5AC_DUMP_STATS_ON_CLOSE
+ /* Dump debugging info */
H5AC_stats(f);
#endif /* H5AC_DUMP_STATS_ON_CLOSE */
- /* Only try to flush the file if it was opened with write access */
+ /* Flush at this point since the file will be closed */
+ /* (Only try to flush the file if it was opened with write access) */
if(f->intent&H5F_ACC_RDWR) {
/* Flush and destroy all caches */
- if (H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL,
- H5F_FLUSH_INVALIDATE | H5F_FLUSH_CLOSING) < 0)
+ if (H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5F_FLUSH_INVALIDATE | H5F_FLUSH_CLOSING) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
} /* end if */
@@ -2558,12 +2513,12 @@ H5F_close(H5F_t *f)
* shared H5F_file_t struct. If the reference count for the H5F_file_t
* struct reaches zero then destroy it also.
*/
- if (H5F_dest(f,H5AC_dxpl_id)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
+ if (H5F_dest(f, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_close() */
+} /* end H5F_try_close() */
/*-------------------------------------------------------------------------
@@ -2590,14 +2545,42 @@ done:
herr_t
H5Fclose(hid_t file_id)
{
+ H5F_t *f;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fclose, FAIL)
H5TRACE1("e","i",file_id);
/* Check/fix arguments. */
- if (NULL==H5I_object_verify(file_id,H5I_FILE))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom")
+ if (NULL == (f = H5I_object_verify(file_id,H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID")
+
+ /* Perform checks for "semi" file close degree here, since closing the
+ * file ID will mess things up if we need to return FAIL */
+ if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
+ int ref_count; /* Reference count for file's ID */
+
+ /* Get the reference count for this ID */
+ if((ref_count = H5I_get_ref(file_id)) < 0)
+ HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
+
+ /* If we will be decrementing the reference count to zero, check for objects open */
+ if(ref_count == 1) {
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
+
+ /* If there are no other file IDs open on this file/mount hier., but
+ * there are still open objects, issue an error and bail out now,
+ * before decrementing the file ID's reference count and triggering
+ * a "real" attempt at closing the file */
+ if(nopen_files == 1 && nopen_objs > 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
+ } /* end if */
+ } /* end if */
/*
* Decrement reference count on atom. When it reaches zero the file will
@@ -2653,6 +2636,9 @@ H5Freopen(hid_t file_id)
/* Keep old file's read/write intent in new file */
new_file->intent=old_file->intent;
+ /* Duplicate old file's name */
+ new_file->name = H5MM_xstrdup(old_file->name);
+
if ((ret_value=H5I_register(H5I_FILE, new_file))<0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
@@ -2661,7 +2647,7 @@ H5Freopen(hid_t file_id)
done:
if (ret_value<0 && new_file)
- if(H5F_close(new_file)<0)
+ if(H5F_dest(new_file, H5AC_dxpl_id)<0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
FUNC_LEAVE_API(ret_value)
}
@@ -3047,15 +3033,9 @@ H5F_get_id(H5F_t *file)
assert(file);
if(file->file_id == -1) {
- if(H5I_remove(file->closing)==NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_READERROR, FAIL, "unable to remove from closing list")
-
/* Get an atom for the file */
if ((file->file_id = H5I_register(H5I_FILE, file))<0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
-
- /* Indicate file is not closing */
- file->closing = 0;
} else {
/* Increment reference count on atom. */
if (H5I_inc_ref(file->file_id)<0)
@@ -3615,21 +3595,33 @@ done:
ssize_t
H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
{
- H5G_entry_t *ent; /*symbol table entry */
+ H5G_entry_t *ent; /*symbol table entry */
+ H5F_t *f; /* Top file in mount hierarchy */
size_t len=0;
ssize_t ret_value;
FUNC_ENTER_API (H5Fget_name, FAIL)
H5TRACE3("Zs","ixz",obj_id,name,size);
- /* get symbol table entry */
- if((ent = H5G_loc(obj_id))==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
+ /* For file IDs, get the file object directly */
+ /* (This prevents the H5G_loc() call from returning the file pointer for
+ * the top file in a mount hierarchy)
+ */
+ if(H5I_get_type(obj_id) == H5I_FILE ) {
+ if (NULL==(f=H5I_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+ } /* end if */
+ else {
+ /* Get symbol table entry */
+ if((ent = H5G_loc(obj_id))==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
+ f = ent->file;
+ } /* end else */
- len = HDstrlen(ent->file->name);
+ len = HDstrlen(f->name);
if(name) {
- HDstrncpy(name, ent->file->name, MIN(len+1,size));
+ HDstrncpy(name, f->name, MIN(len+1,size));
if(len >= size)
name[size-1]='\0';
} /* end if */
@@ -3640,3 +3632,143 @@ H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_shared_add
+ *
+ * Purpose: Add a "shared" file struct to the list of open files
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_shared_add(H5F_file_t *shared)
+{
+ H5F_sfile_node_t *new; /* New shared file node */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_shared_add)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Allocate new shared file node */
+ if (NULL == (new = H5FL_CALLOC(H5F_sfile_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set shared file value */
+ new->shared = shared;
+
+ /* Prepend to list of shared files open */
+ new->next = H5F_sfile_head_g;
+ H5F_sfile_head_g = new;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_add() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_shared_search
+ *
+ * Purpose: Search for a "shared" file with low-level file info that
+ * matches
+ *
+ * Return: Non-NULL on success / NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5F_file_t *
+H5F_shared_search(H5FD_t *lf)
+{
+ H5F_sfile_node_t *curr; /* Current shared file node */
+ H5F_file_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_shared_search)
+
+ /* Sanity check */
+ HDassert(lf);
+
+ /* Iterate through low-level files for matching low-level file info */
+ curr = H5F_sfile_head_g;
+ while(curr) {
+ /* Check for match */
+ if(0==H5FD_cmp(curr->shared->lf, lf))
+ HGOTO_DONE(curr->shared)
+
+ /* Advance to next shared file node */
+ curr = curr->next;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_search() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_shared_remove
+ *
+ * Purpose: Remove a "shared" file struct from the list of open files
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_shared_remove(H5F_file_t *shared)
+{
+ H5F_sfile_node_t *curr; /* Current shared file node */
+ H5F_sfile_node_t *last; /* Last shared file node */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_shared_remove)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Locate shared file node with correct shared file */
+ last = NULL;
+ curr = H5F_sfile_head_g;
+ while(curr && curr->shared != shared) {
+ /* Advance to next node */
+ last = curr;
+ curr = curr->next;
+ } /* end while */
+
+ /* Indicate error if the node wasn't found */
+ if(curr == NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTFOUND, FAIL, "can't find shared file info")
+
+ /* Remove node found from list */
+ if(last != NULL)
+ /* Removing middle or tail node in list */
+ last->next = curr->next;
+ else
+ /* Removing head node in list */
+ H5F_sfile_head_g = curr->next;
+
+ /* Release the shared file node struct */
+ /* (the shared file info itself is freed elsewhere) */
+ H5FL_FREE(H5F_sfile_node_t, curr);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_remove() */
+
diff --git a/src/H5Fmount.c b/src/H5Fmount.c
index 5714415..7e234a5 100644
--- a/src/H5Fmount.c
+++ b/src/H5Fmount.c
@@ -86,7 +86,7 @@ H5F_close_mounts(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group")
/* Close the child file */
- if(H5F_close(f->mtab.child[u].file) < 0)
+ if(H5F_try_close(f->mtab.child[u].file) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
} /* end if */
f->mtab.nmounts = 0;
@@ -97,46 +97,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_term_unmount_cb
- *
- * Purpose: H5F_term_interface' callback function. This routine
- * unmounts child files from files that are in the "closing"
- * state.
- *
- * Programmer: Quincey Koziol
- * Thursday, Jun 30, 2005
- *
- * Modification:
- *
- *-------------------------------------------------------------------------
- */
-int
-H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void UNUSED *key)
-{
- H5F_t *f = (H5F_t *)obj_ptr; /* Alias for search info */
- int ret_value = FALSE; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5F_term_unmount_cb)
-
- assert(f);
-
- if(f->mtab.nmounts) {
- /* Unmount all child files */
- if(H5F_close_mounts(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child file")
-
- /* Decrement reference count for file */
- H5I_dec_ref(obj_id);
- } /* end if */
- else
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "no files to unmount")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5F_term_unmount_cb() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_mount
*
* Purpose: Mount file CHILD onto the group specified by LOC and NAME,
@@ -181,7 +141,8 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child,
assert(TRUE==H5P_isa_class(plist_id,H5P_MOUNT));
/*
- * Check that the child isn't mounted, that the mount point exists, and
+ * Check that the child isn't mounted, that the mount point exists, that
+ * the parent & child files have the same file close degree, and
* that the mount wouldn't introduce a cycle in the mount tree.
*/
if (child->mtab.parent)
@@ -197,6 +158,9 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child,
if (ancestor==child)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle")
}
+
+ if(parent->shared->fc_degree != child->shared->fc_degree)
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mounted file has different file close degree than parent")
/*
* Use a binary search to locate the position that the child should be
@@ -239,7 +203,10 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child,
parent->mtab.child[md].group = mount_point;
parent->mtab.child[md].file = child;
child->mtab.parent = parent;
- child->nrefs++;
+
+ /* Set the group's mountpoint flag */
+ if(H5G_mount(parent->mtab.child[md].group)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to set group mounted flag")
/* Search the open IDs and replace names for mount operation */
/* We pass H5G_UNKNOWN as object type; search all IDs */
@@ -317,8 +284,7 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
mnt_ent = H5G_entof(mounted);
ent = H5G_entof(child->shared->root_grp);
- if (child->mtab.parent &&
- H5F_addr_eq(mnt_ent->header, ent->header)) {
+ if (child->mtab.parent && H5F_addr_eq(mnt_ent->header, ent->header)) {
/*
* We've been given the root group of the child. We do a reverse
* lookup in the parent's mount table to find the correct entry.
@@ -332,18 +298,21 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
/* Unmount the child */
parent->mtab.nmounts -= 1;
+ if(H5G_unmount(parent->mtab.child[md].group)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag")
if(H5G_close(parent->mtab.child[i].group)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
child->mtab.parent = NULL;
- if(H5F_close(child)<0)
+ if(H5F_try_close(child)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
+
+ /* Eliminate the mount point from the table */
HDmemmove(parent->mtab.child+i, parent->mtab.child+i+1,
(parent->mtab.nmounts-i)* sizeof(parent->mtab.child[0]));
ret_value = SUCCEED;
}
}
- assert(ret_value>=0);
-
+ HDassert(ret_value>=0);
} else {
/*
* We've been given the mount point in the parent. We use a binary
@@ -368,11 +337,15 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
/* Unmount the child */
parent->mtab.nmounts -= 1;
+ if(H5G_unmount(parent->mtab.child[md].group)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag")
if(H5G_close(parent->mtab.child[md].group)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
parent->mtab.child[md].file->mtab.parent = NULL;
- if(H5F_close(parent->mtab.child[md].file)<0)
+ if(H5F_try_close(parent->mtab.child[md].file)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
+
+ /* Eliminate the mount point from the table */
HDmemmove(parent->mtab.child+md, parent->mtab.child+md+1,
(parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
ret_value = SUCCEED;
@@ -621,109 +594,89 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_check_mounts_recurse
+ * Function: H5F_mount_count_ids_recurse
*
- * Purpose: Helper routine for checking for file mounting hierarchies to
- * close.
+ * Purpose: Helper routine for counting number of open IDs in mount
+ * hierarchy.
*
- * Return: TRUE if entire hierarchy can be closed / FALSE otherwise
+ * Return: <none>
*
* Programmer: Quincey Koziol
- * Saturday, July 2, 2005
+ * Tuesday, July 19, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
-static hbool_t
-H5F_check_mounts_recurse(H5F_t *f)
+static void
+H5F_mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs)
{
- hbool_t ret_value = FALSE; /* Return value */
+ unsigned u; /* Local index value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_check_mounts_recurse)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_mount_count_ids_recurse)
- /* Check if this file is closing and if the only objects left open are
- * the mount points */
- if((f->closing || (f->nrefs == 1 && f->mtab.parent)) && f->nopen_objs == f->mtab.nmounts) {
- unsigned u;
+ /* Sanity check */
+ HDassert(f);
+ HDassert(nopen_files);
+ HDassert(nopen_objs);
- /* Iterate over files mounted in this file and check if all can be closed */
- for(u = 0; u < f->mtab.nmounts; u++) {
- if(H5G_get_shared_count(f->mtab.child[u].group) > 1
- || !H5F_check_mounts_recurse(f->mtab.child[u].file))
- HGOTO_DONE(FALSE)
- } /* end for */
+ /* If this file is still open, increment number of file IDs open */
+ if(f->file_id > 0)
+ *nopen_files += 1;
- /* Set return value */
- ret_value = TRUE;
- } /* end if */
+ /* Increment number of open objects in file
+ * (Reduced by number of mounted files, we'll add back in the mount point's
+ * groups later, if they are open)
+ */
+ *nopen_objs += (f->nopen_objs - f->mtab.nmounts);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_check_mounts_recurse() */
+ /* Iterate over files mounted in this file and add in their open ID counts also */
+ for(u = 0; u < f->mtab.nmounts; u++) {
+ /* Increment the open object count if the mount point group has an open ID */
+ if(H5G_get_shared_count(f->mtab.child[u].group) > 1)
+ *nopen_objs += 1;
+
+ H5F_mount_count_ids_recurse(f->mtab.child[u].file, nopen_files, nopen_objs);
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_mount_count_ids_recurse() */
/*-------------------------------------------------------------------------
- * Function: H5F_check_mounts
+ * Function: H5F_mount_count_ids
*
- * Purpose: Check for file mounting hierarchies that have been created
- * and that now are composed completely of files that are closing
- * and have no more open objects in them.
+ * Purpose: Count the number of open file & object IDs in a mount hierarchy
*
- * When such a mounting hierarchy is detected, unmount and close
- * all the files involved.
- *
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
- * Saturday, July 2, 2005
+ * Tues, July 19, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
-H5F_check_mounts(H5F_t *f)
+H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5F_check_mounts, FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: f->name=%s\n", FUNC, f->name);
-HDfprintf(stderr, "%s: f->nrefs=%u\n", FUNC, f->nrefs);
-HDfprintf(stderr, "%s: f->shared->nrefs=%u\n", FUNC, f->shared->nrefs);
-HDfprintf(stderr, "%s: f->mtab.parent=%p\n", FUNC, f->mtab.parent);
-HDfprintf(stderr, "%s: f->mtab.nmounts=%u\n", FUNC, f->mtab.nmounts);
-HDfprintf(stderr, "%s: f->nopen_objs=%u\n", FUNC, f->nopen_objs);
-HDfprintf(stderr, "%s: f->closing=%x\n", FUNC, f->closing);
-#endif /* QAK */
-
- /* Only try to close files for files involved in a mounting hierarchy */
- if(f->mtab.parent || f->mtab.nmounts) {
- H5F_t *top = f; /* Pointer to the top file in the hierarchy */
-
- /* Find the top file in the mounting hierarchy */
- while(top->mtab.parent) {
- /* Get out early if we detect that this hierarchy won't close */
- if(top->nopen_objs != top->mtab.nmounts || !top->closing)
- HGOTO_DONE(SUCCEED)
-
- /* Advance toward the top of the hierarchy */
- top = top->mtab.parent;
- } /* end while */
-
- /* Check for closing the hierarchy */
- if(H5F_check_mounts_recurse(top)) {
- /* Unmount all child files */
- if(H5F_close_mounts(top) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child file")
-
- if(H5I_dec_ref(top->closing) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't decrement file closing ID")
- } /* end if */
- } /* end if */
+ FUNC_ENTER_NOAPI(H5F_mount_count_ids, FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(nopen_files);
+ HDassert(nopen_objs);
+
+ /* Find the top file in the mounting hierarchy */
+ while(f->mtab.parent)
+ f = f->mtab.parent;
+
+ /* Count open IDs in the hierarchy */
+ H5F_mount_count_ids_recurse(f, nopen_files, nopen_objs);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_check_mounts() */
+} /* end H5F_mount_count_ids() */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 1c91b8e..4a2c128 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -96,8 +96,8 @@ typedef struct H5F_file_t {
unsigned super_chksum; /* Superblock checksum */
unsigned drvr_chksum; /* Driver info block checksum */
H5AC_t *cache; /* The object cache */
- hid_t fcpl_id; /* File creation property list ID */
int mdc_nelmts; /* Size of meta data cache (elements) */
+ hid_t fcpl_id; /* File creation property list ID */
H5F_close_degree_t fc_degree; /* File close behavior degree */
size_t rdcc_nelmts; /* Size of raw data chunk cache (elmts) */
size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */
@@ -139,13 +139,12 @@ typedef struct H5F_mtab_t {
* indicate that the file is mounted on some other file).
*/
struct H5F_t {
- unsigned nrefs; /* Reference count */
unsigned intent; /* The flags passed to H5F_open()*/
char *name; /* Name used to open file */
H5F_file_t *shared; /* The shared file info */
unsigned nopen_objs; /* Number of open object headers*/
hid_t file_id; /* ID of this file */
- hid_t closing; /* H5I_FILE_CLOSING ID or zero */
+ hbool_t closing; /* File is in the process of being closed */
H5F_mtab_t mtab; /* File mount table */
};
@@ -160,14 +159,14 @@ H5_DLL void H5F_encode_length_unusual(const H5F_t *f, uint8_t **p, uint8_t *l);
#endif /* NOT_YET */
/* General routines */
-H5_DLL herr_t H5F_close(H5F_t *f);
+H5_DLL herr_t H5F_try_close(H5F_t *f);
H5_DLL haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id);
/* File mount related routines */
H5_DLL herr_t H5F_mountpoint(struct H5G_entry_t *find/*in,out*/);
H5_DLL herr_t H5F_close_mounts(H5F_t *f);
H5_DLL int H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void *key);
-H5_DLL herr_t H5F_check_mounts(H5F_t *f);
+H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs);
/* Superblock related routines */
H5_DLL herr_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index ba978a8..abe4752 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -418,8 +418,8 @@ H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
H5_DLL unsigned H5F_get_intent(const H5F_t *f);
H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
H5_DLL hid_t H5F_get_id(H5F_t *file);
-H5_DLL int H5F_get_obj_count(const H5F_t *f, unsigned types);
-H5_DLL int H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
+H5_DLL unsigned H5F_get_obj_count(const H5F_t *f, unsigned types);
+H5_DLL unsigned H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
H5_DLL haddr_t H5F_get_eoa(const H5F_t *f);
#ifdef H5_HAVE_PARALLEL
diff --git a/src/H5G.c b/src/H5G.c
index 76c024f..1a16d1a 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -1011,7 +1011,7 @@ done:
static herr_t
H5G_init_interface(void)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_init_interface);
@@ -1995,7 +1995,8 @@ 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")
}
- grp->shared->fo_count =1;
+ /* Set open object count */
+ grp->shared->fo_count = 1;
}
else {
if(NULL == (grp = H5FL_CALLOC(H5G_t)))
@@ -2005,7 +2006,10 @@ H5G_open(H5G_entry_t *ent, hid_t dxpl_id)
if(H5G_ent_copy(&(grp->ent), ent, H5G_COPY_SHALLOW)<0)
HGOTO_ERROR (H5E_SYM, H5E_CANTCOPY, NULL, "can't copy group entry")
- grp->shared=shared_fo;
+ /* Point to shared group info */
+ grp->shared = shared_fo;
+
+ /* Increment shared reference count */
shared_fo->fo_count++;
}
@@ -2158,11 +2162,14 @@ H5G_close(H5G_t *grp)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close");
H5FL_FREE (H5G_shared_t, grp->shared);
} else {
- /* Check if this group was the last object holding open a mounted file
- * hierarchy and close down the file hierarchy if so */
- if(grp->shared->fo_count == 1)
- if(H5F_check_mounts(grp->ent.file) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy");
+ /* 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
+ */
+ if(grp->shared->mounted && grp->shared->fo_count == 1) {
+ /* Attempt to close down the file hierarchy */
+ if(H5F_try_close(grp->ent.file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
+ } /* end if */
if(H5G_free_ent_name(&(grp->ent))<0)
{
@@ -2175,7 +2182,7 @@ H5G_close(H5G_t *grp)
done:
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5G_close() */
/*-------------------------------------------------------------------------
@@ -2435,6 +2442,9 @@ H5G_loc (hid_t loc_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry for root group");
/* Patch up root group's symbol table entry to reflect this file */
+ /* (Since the root group info is only stored once for files which
+ * share an underlying low-level file)
+ */
/* (but only for non-mounted files) */
if(!f->mtab.parent)
ret_value->file = f;
@@ -4001,8 +4011,68 @@ H5G_get_shared_count(H5G_t *grp)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_get_shared_count);
/* Check args */
- assert(grp && grp->shared);
+ HDassert(grp && grp->shared);
FUNC_LEAVE_NOAPI(grp->shared->fo_count);
} /* end H5G_get_shared_count() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_mount
+ *
+ * Purpose: Sets the 'mounted' flag for a group
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_mount(H5G_t *grp)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_mount);
+
+ /* Check args */
+ HDassert(grp && grp->shared);
+ HDassert(grp->shared->mounted == FALSE);
+
+ /* Set the 'mounted' flag */
+ grp->shared->mounted = TRUE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* end H5G_mount() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_unmount
+ *
+ * Purpose: Resets the 'mounted' flag for a group
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_unmount(H5G_t *grp)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_unmount);
+
+ /* Check args */
+ HDassert(grp && grp->shared);
+ HDassert(grp->shared->mounted == TRUE);
+
+ /* Reset the 'mounted' flag */
+ grp->shared->mounted = FALSE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* end H5G_unmount() */
+
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index bc14364..11bd437 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -47,10 +47,11 @@ typedef struct H5G_node_t {
} H5G_node_t;
/*
- * Reference count shared between all instances of an open group
+ * Shared information for all open group objects
*/
struct H5G_shared_t {
int fo_count; /* open file object count */
+ hbool_t mounted; /* Group is mount point */
};
/*
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 9eb8d85..912e7d5 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -157,6 +157,8 @@ H5_DLL herr_t H5G_replace_name(int type, H5G_entry_t *loc,
H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op);
H5_DLL herr_t H5G_free_grp_name(H5G_t *grp);
H5_DLL herr_t H5G_get_shared_count(H5G_t *grp);
+H5_DLL herr_t H5G_mount(H5G_t *grp);
+H5_DLL herr_t H5G_unmount(H5G_t *grp);
/*
* These functions operate on symbol table nodes.
diff --git a/src/H5I.c b/src/H5I.c
index f500c85..04c88f4 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -114,7 +114,6 @@ H5FL_DEFINE_STATIC(H5I_id_info_t);
/*--------------------- Local function prototypes ---------------------------*/
static H5I_id_info_t *H5I_find_id(hid_t id);
static hid_t H5I_get_file_id(hid_t obj_id);
-static int H5I_get_ref(hid_t id);
#ifdef H5I_DEBUG_OUTPUT
static herr_t H5I_debug(H5I_type_t grp);
#endif /* H5I_DEBUG_OUTPUT */
@@ -311,9 +310,6 @@ int
H5I_nmembers(H5I_type_t grp)
{
H5I_id_group_t *grp_ptr = NULL;
- H5I_id_info_t *cur=NULL;
- int n=0;
- unsigned i;
int ret_value;
FUNC_ENTER_NOAPI(H5I_nmembers, FAIL);
@@ -323,12 +319,8 @@ H5I_nmembers(H5I_type_t grp)
if (NULL==(grp_ptr=H5I_id_group_list_g[grp]) || grp_ptr->count<=0)
HGOTO_DONE(0);
- for (i=0; i<grp_ptr->hash_size; i++)
- for (cur=grp_ptr->id_list[i]; cur; cur=cur->next)
- n++;
-
/* Set return value */
- ret_value=n;
+ H5_ASSIGN_OVERFLOW(ret_value, grp_ptr->ids, unsigned, int);
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -1127,7 +1119,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static int
+int
H5I_get_ref(hid_t id)
{
H5I_type_t grp; /*group the object is in*/
@@ -1203,20 +1195,23 @@ H5I_search(H5I_type_t grp, H5I_search_func_t func, void *key)
if (grp_ptr == NULL || grp_ptr->count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid group");
- /* Start at the beginning of the array */
- for (i=0; i<grp_ptr->hash_size; i++) {
- id_ptr = grp_ptr->id_list[i];
- while (id_ptr) {
- next_id= id_ptr->next; /* Protect against ID being deleted in callback */
- if ((*func)(id_ptr->obj_ptr, id_ptr->id, key))
- HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
- id_ptr = next_id;
- }
- }
+ /* Only iterate through hash table if there are IDs in group */
+ if(grp_ptr->ids > 0) {
+ /* Start at the beginning of the array */
+ for (i=0; i<grp_ptr->hash_size; i++) {
+ id_ptr = grp_ptr->id_list[i];
+ while (id_ptr) {
+ next_id= id_ptr->next; /* Protect against ID being deleted in callback */
+ if ((*func)(id_ptr->obj_ptr, id_ptr->id, key))
+ HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
+ id_ptr = next_id;
+ } /* end while */
+ } /* end for */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5I_search() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index a244d31..fb4b282 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -66,6 +66,7 @@ H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type);
H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_search(H5I_type_t grp, H5I_search_func_t func, void *key);
+H5_DLL int H5I_get_ref(hid_t id);
H5_DLL int H5I_inc_ref(hid_t id);
H5_DLL int H5I_dec_ref(hid_t id);
#endif
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index ce29be3..33ad2ad 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -35,7 +35,6 @@
typedef enum {
H5I_BADID = (-1), /*invalid Group */
H5I_FILE = 1, /*group ID for File objects */
- H5I_FILE_CLOSING, /*files pending close due to open objhdrs */
H5I_GROUP, /*group ID for Group objects */
H5I_DATATYPE, /*group ID for Datatype objects */
H5I_DATASPACE, /*group ID for Dataspace objects */
diff --git a/src/H5O.c b/src/H5O.c
index 2a8745f..3f3ca8a 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -405,7 +405,7 @@ H5O_close(H5G_entry_t *obj_ent)
#ifdef H5O_DEBUG
if (H5DEBUG(O)) {
- if (obj_ent->file->closing && 1==obj_ent->file->shared->nrefs) {
+ if (obj_ent->file->file_id < 0 && 1==obj_ent->file->shared->nrefs) {
HDfprintf(H5DEBUG(O), "< %a auto %lu remaining\n",
obj_ent->header,
(unsigned long)(obj_ent->file->nopen_objs));
@@ -416,28 +416,13 @@ H5O_close(H5G_entry_t *obj_ent)
#endif
/*
- * If the file open-lock count has reached the number of open mount points
- * (each of which has a group open in the file) and the file has a close
- * pending then close the file and remove it from the H5I_FILE_CLOSING ID
- * group.
+ * If the file open object count has reached the number of open mount points
+ * (each of which has a group open in the file) attempt to close the file.
*/
- /* Check for just mount points holding file open */
- if(obj_ent->file->mtab.nmounts == obj_ent->file->nopen_objs && obj_ent->file->closing) {
- unsigned u; /* Local index variable */
- hbool_t really_close; /* Whether to delay the file close by going to a "closing" state */
-
- /* Check for open groups on mount points */
- really_close = TRUE;
- for(u = 0; u < obj_ent->file->mtab.nmounts; u++) {
- if(H5G_get_shared_count(obj_ent->file->mtab.child[u].group) > 1) {
- really_close = FALSE;
- break;
- } /* end if */
- } /* end for */
-
- /* If we really want to close this file now */
- if(really_close)
- H5I_dec_ref(obj_ent->file->closing);
+ if(obj_ent->file->nopen_objs == obj_ent->file->mtab.nmounts) {
+ /* Attempt to close down the file hierarchy */
+ if(H5F_try_close(obj_ent->file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
} /* end if */
/* Free the ID to name buffers */
@@ -445,7 +430,7 @@ H5O_close(H5G_entry_t *obj_ent)
done:
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5O_close() */
/*-------------------------------------------------------------------------
diff --git a/test/Makefile.in b/test/Makefile.in
index 83b2f94..26f144c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -28,7 +28,7 @@ TEST_PROGS=testhdf5 lheap ohdr stab gheap cache hyperslab istore bittests \
dtypes dsets cmpd_dset extend external links unlink big mtime fillval \
mount flush1 flush2 enum gass_write gass_read gass_append set_extent \
srb_write srb_append srb_read ttsafe stream_test getname file_handle \
- ntypes dangle filename reserved
+ ntypes dangle reserved
TIMINGS=testmeta
@@ -61,7 +61,7 @@ MOSTLYCLEAN=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5 \
getname.h5 getname1.h5 getname2.h5 getname3.h5 sec2_file.h5 \
family_file000[0-3][0-9].h5 multi_file-[rs].h5 core_file \
new_move_[ab].h5 ntypes.h5 dangle.h5 test_filters.h5 \
- get_file_name.h5 tstint[1-2].h5 unlink_chunked.h5
+ tstint[1-2].h5 unlink_chunked.h5
CLEAN=$(TIMINGS)
@@ -79,8 +79,7 @@ TEST_SRC=big.c bittests.c cache.c cmpd_dset.c dsets.c dtypes.c extend.c \
unlink.c enum.c ttsafe.c ttsafe_dcreate.c ttsafe_error.c \
ttsafe_cancel.c ttsafe_acreate.c gass_write.c gass_read.c \
gass_append.c srb_read.c srb_write.c srb_append.c stream_test.c \
- set_extent.c getname.c file_handle.c ntypes.c dangle.c filename.c \
- reserved.c
+ set_extent.c getname.c file_handle.c ntypes.c dangle.c reserved.c
TEST_OBJ=$(TEST_SRC:.c=.lo)
@@ -225,9 +224,6 @@ ntypes: ntypes.lo
dangle: dangle.lo
@$(LT_LINK_EXE) $(CFLAGS) -o $@ dangle.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS)
-filename: filename.lo
- @$(LT_LINK_EXE) $(CFLAGS) -o $@ filename.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS)
-
reserved: reserved.lo
@$(LT_LINK_EXE) $(CFLAGS) -o $@ reserved.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS)
diff --git a/test/filename.c b/test/filename.c
deleted file mode 100644
index 32dfd63..0000000
--- a/test/filename.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright by the Board of Trustees of the University of Illinois. *
- * All rights reserved. *
- * *
- * This file is part of HDF5. The full HDF5 copyright notice, including *
- * terms governing use, modification, and redistribution, is contained in *
- * the files COPYING and Copyright.html. COPYING can be found at the root *
- * of the source code distribution tree; Copyright.html can be found at the *
- * root level of an installed copy of the electronic HDF5 document set and *
- * is linked from the top-level documents page. It can also be found at *
- * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
- * June 29, 2004
- *
- * Purpose: Tests the "H5Fget_name" functionality
- */
-
-#include "testhdf5.h"
-
-#define FILENAME "get_file_name"
-#define GROUPNAME "group"
-#define DSETNAME "dataset"
-#define ATTRNAME "attribute"
-#define DTYPENAME "compound"
-#define NAME_BUF_SIZE 64
-
-#define RANK 2
-#define NX 4
-#define NY 5
-
-/* Compound datatype */
-typedef struct s1_t {
- unsigned int a;
- float b;
-} s1_t;
-
-/* Used to make certain a return name _is_ the file name */
-#define VERIFY_NAME(x, val, where) do { \
- if (GetTestVerbosity()>=VERBO_HI) { \
- print_func(" Call to routine: %15s at line %4d in %s had value " \
- "%ld \n", (where), (int)__LINE__, __FILE__, (long)(x)); \
- } \
- if (strcmp(x, val)) { \
- TestErrPrintf("*** UNEXPECTED VALUE from %s should be %s, but is %s at line %4d " \
- "in %s\n", where, val, x, (int)__LINE__, __FILE__); \
- H5Eprint (stdout); \
- } \
-} while(0)
-
-int main( void )
-{
- char filename[NAME_BUF_SIZE];
- hid_t fapl;
- hid_t file_id;
- hid_t group_id;
- hid_t dataset_id;
- hid_t space_id;
- hid_t type_id;
- hid_t attr_id;
- hsize_t dims[RANK] = {NX, NY};
- char name[NAME_BUF_SIZE];
- ssize_t name_len;
- herr_t ret;
-
- TESTING("H5Fget_name");
-
- /* Reset the library and get the file access property list */
- h5_reset();
- fapl = h5_fileaccess();
-
- /* Initialize the file names */
- h5_fixname(FILENAME, fapl, filename, sizeof filename);
-
- /* Create a new file_id using default properties. */
- file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl );
- CHECK(file_id, FAIL, "H5Fcreate");
-
- /* Get and verify file name */
- name_len = H5Fget_name(file_id, name, NAME_BUF_SIZE);
- CHECK(name_len, FAIL, "H5Fget_name");
- VERIFY_NAME(name, filename, "H5Fget_name");
-
- /* Create a group in the root group */
- group_id = H5Gcreate(file_id, GROUPNAME, 0);
- CHECK(group_id, FAIL, "H5Gcreate");
-
- /* Get and verify file name */
- name_len = H5Fget_name(group_id, name, NAME_BUF_SIZE);
- CHECK(name_len, FAIL, "H5Fget_name");
- VERIFY_NAME(name, filename, "H5Fget_name");
-
- /* Create the data space */
- space_id = H5Screate_simple(RANK, dims, NULL);
- CHECK(space_id, FAIL, "H5Screate_simple");
-
- /* Try get file name from data space. Supposed to fail because
- * it's illegal operation. */
- H5E_BEGIN_TRY {
- name_len = H5Fget_name(space_id, name, NAME_BUF_SIZE);
- } H5E_END_TRY;
- VERIFY(name_len, FAIL, "H5Fget_name");
-
- /* Create a new dataset */
- dataset_id = H5Dcreate(file_id, DSETNAME, H5T_NATIVE_INT, space_id, H5P_DEFAULT);
- CHECK(dataset_id, FAIL, "H5Dcreate");
-
- /* Get and verify file name */
- name_len = H5Fget_name(dataset_id, name, NAME_BUF_SIZE);
- CHECK(name_len, FAIL, "H5Fget_name");
- VERIFY_NAME(name, filename, "H5Fget_name");
-
- /* Create an attribute for the dataset */
- attr_id = H5Acreate(dataset_id,ATTRNAME,H5T_NATIVE_INT,space_id,H5P_DEFAULT);
- CHECK(attr_id, FAIL, "H5Acreate");
-
- /* Get and verify file name */
- name_len = H5Fget_name(attr_id, name, NAME_BUF_SIZE);
- CHECK(name_len, FAIL, "H5Fget_name");
- VERIFY_NAME(name, filename, "H5Fget_name");
-
- /* Create a compound datatype */
- type_id = H5Tcreate(H5T_COMPOUND, sizeof(s1_t));
- CHECK(type_id, FAIL, "H5Tcreate");
-
- /* Insert fields */
- ret = H5Tinsert (type_id, "a", HOFFSET(s1_t,a), H5T_NATIVE_INT);
- CHECK(ret, FAIL, "H5Tinsert");
-
- ret = H5Tinsert (type_id, "b", HOFFSET(s1_t,b), H5T_NATIVE_FLOAT);
- CHECK(ret, FAIL, "H5Tinsert");
-
- /* Save it on file */
- ret = H5Tcommit(file_id, DTYPENAME, type_id);
- CHECK(ret, FAIL, "H5Tcommit");
-
- /* Get and verify file name */
- name_len = H5Fget_name(type_id, name, NAME_BUF_SIZE);
- CHECK(name_len, FAIL, "H5Fget_name");
- VERIFY_NAME(name, filename, "H5Fget_name");
-
- H5Tclose(type_id);
- H5Aclose(attr_id);
- H5Dclose(dataset_id);
- H5Sclose(space_id);
- H5Gclose(group_id);
- H5Fclose(file_id);
-
- PASSED();
- return 0;
-}
diff --git a/test/mount.c b/test/mount.c
index 8df2b21..9da01f2 100644
--- a/test/mount.c
+++ b/test/mount.c
@@ -124,15 +124,21 @@ test_basic(hid_t fapl)
h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
- if ((file1=H5Fopen(filename1, H5F_ACC_RDONLY, fapl))<0 ||
- (file2=H5Fopen(filename2, H5F_ACC_RDONLY, fapl))<0)
- goto error;
- if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
- if ((grp=H5Gopen(file1, "/mnt1/file2"))<0) goto error;
- if (H5Gclose(grp)<0) goto error;
- if (H5Funmount(file1, "/mnt1")<0) goto error;
- if (H5Fclose(file1)<0) goto error;
- if (H5Fclose(file2)<0) goto error;
+ if ((file1 = H5Fopen(filename1, H5F_ACC_RDONLY, fapl)) < 0 ||
+ (file2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if ((grp = H5Gopen(file1, "/mnt1/file2")) < 0)
+ TEST_ERROR
+ if (H5Gclose(grp) < 0)
+ TEST_ERROR
+ if (H5Funmount(file1, "/mnt1") < 0)
+ TEST_ERROR
+ if (H5Fclose(file1) < 0)
+ TEST_ERROR
+ if (H5Fclose(file2) < 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -974,7 +980,6 @@ test_close(hid_t fapl)
{
hid_t file1=-1, file2=-1;
char filename1[1024], filename2[1024];
- herr_t status;
TESTING("file handle close");
h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
@@ -987,21 +992,21 @@ test_close(hid_t fapl)
if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
/*
- * Close file1 unmounting it from the virtual file. Objects in file2 are
- * still accessible through the file2 handle, but nothing in file1 is
- * accessible.
+ * Close file1 unmounting it from the virtual file. Objects in file1 are
+ * still accessible through the file2 handle.
*/
if (H5Fclose(file1)<0) goto error;
- H5E_BEGIN_TRY {
- status = H5Gget_objinfo(file2, "/mnt1", TRUE, NULL);
- } H5E_END_TRY;
- if (status>=0) {
+ if(H5Gget_objinfo(file2, "/mnt1", TRUE, NULL) < 0) {
H5_FAILED();
- puts(" File1 contents are still accessible!");
+ puts(" File1 contents are not accessible!");
goto error;
}
if (H5Fclose(file2)<0) goto error;
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
/* Build the virtual file again */
if ((file1=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0 ||
(file2=H5Fopen(filename2, H5F_ACC_RDWR, fapl))<0)
@@ -1015,6 +1020,10 @@ test_close(hid_t fapl)
if (H5Gget_objinfo(file1, "/mnt1/file2", TRUE, NULL)<0) goto error;
if (H5Fclose(file1)<0) goto error;
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
/* Shut down */
PASSED();
return 0;
@@ -1659,10 +1668,6 @@ test_missing_unmount(hid_t fapl)
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
- /* Check that all "file closing" IDs have been closed */
- if(H5I_nmembers(H5I_FILE_CLOSING) != 0)
- TEST_ERROR
-
PASSED();
return 0;
@@ -1797,10 +1802,6 @@ test_hold_open_file(hid_t fapl)
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
- /* Check that all "file closing" IDs have been closed */
- if(H5I_nmembers(H5I_FILE_CLOSING) != 0)
- TEST_ERROR
-
PASSED();
return 0;
@@ -1837,7 +1838,7 @@ static int
test_hold_open_group(hid_t fapl)
{
hid_t fid1 = -1, fid2 = -1; /* File IDs */
- hid_t gidA = -1, gidM = -1, gidAM = -1, gidAM2 = -1; /* Group IDs */
+ hid_t gid = -1, gidA = -1, gidM = -1, gidAM = -1, gidAM2 = -1; /* Group IDs */
char filename1[1024],
filename2[1024]; /* Name of files to mount */
@@ -1918,21 +1919,326 @@ test_hold_open_group(hid_t fapl)
if((gidAM2 = H5Gopen(fid1, "/A/M")) < 0)
TEST_ERROR
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Get ID of file #2 */
+ if((fid2 = H5Iget_file_id(gidAM2)) < 0)
+ TEST_ERROR
+
+ /* Close group in mounted file */
+ if(H5Gclose(gidAM2) < 0)
+ TEST_ERROR
+
+ /* Attempt to open group in mounted file */
+ /* (Should work because file is still mounted) */
+ if((gidAM2 = H5Gopen(fid2, "/A/M")) < 0)
+ TEST_ERROR
+
+ /* Close file #2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Attempt to open group in parent file */
+ /* (Should work because files should be mounted together) */
+ if((gid = H5Gopen(gidAM2, "/")) < 0)
+ TEST_ERROR
+
/* Close group in mounted file */
if(H5Gclose(gidAM2) < 0)
TEST_ERROR
+ /* Close group in parent file */
+ if(H5Gclose(gid) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidM);
+ H5Gclose(gidAM);
+ H5Gclose(gidAM2);
+ H5Gclose(gidA);
+ H5Gclose(gid);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_hold_open_group() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_fcdegree_same
+ *
+ * Purpose: Test that the library will only allow files with same file
+ * close degree to be mounted together.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_fcdegree_same(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1; /* File IDs */
+ hid_t gidA = -1, gidM = -1, gidAM = -1; /* Group IDs */
+ hid_t fapl_id = -1; /* FAPL IDs */
+ herr_t ret; /* Generic return value */
+ char filename1[1024],
+ filename2[1024]; /* Name of files to mount */
+
+ TESTING("file close degrees must be same");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ /* Create FAPL & set file close degree for file #2 to be different */
+ if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR
+
+ /* Set file close mode to H5F_CLOSE_STRONG */
+ if(H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ /* Try mounting file with different file close degree (should fail) */
+ H5E_BEGIN_TRY {
+ ret = H5Fmount(gidA, ".", fid2, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Set file close mode to H5F_CLOSE_WEAK */
+ if(H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK) < 0)
+ TEST_ERROR
+
+ /* Close file #2 & re-open with same file close degree as file #1 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ /* Try mounting files again (should work now) */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Verify opening group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Close group in mounted file */
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+
+ /* Close group in parent file */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Close file #2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
/* Close file #1 */
- /* (should unmount file #2 also) */
if(H5Fclose(fid1) < 0)
TEST_ERROR
+ /* Close FAPL ID */
+ if(H5Pclose(fapl_id) < 0)
+ TEST_ERROR
+
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
- /* Check that all "file closing" IDs have been closed */
- if(H5I_nmembers(H5I_FILE_CLOSING) != 0)
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_id);
+ H5Gclose(gidM);
+ H5Gclose(gidAM);
+ H5Gclose(gidA);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_fcdegree_same() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_fcdegree_semi
+ *
+ * Purpose: Test that the library perform correct actions when using
+ * "semi" file close degree on mounted files
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_fcdegree_semi(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1; /* File IDs */
+ hid_t gidA = -1, gidM = -1, gidAM = -1; /* Group IDs */
+ hid_t fapl_id = -1; /* FAPL IDs */
+ herr_t ret; /* Generic return value */
+ char filename1[1024],
+ filename2[1024]; /* Name of files to mount */
+
+ TESTING("'semi' file close degree");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create FAPL & set file close degree to be "semi" */
+ if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR
+
+ /* Set file close mode to H5F_CLOSE_SEMI */
+ if(H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI) < 0)
+ TEST_ERROR
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Verify opening group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Close file #1 (should succeed, since file #2 is open still) */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Try closing file #2 (should fail, since there are still objects open) */
+ H5E_BEGIN_TRY {
+ ret = H5Fclose(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close group in parent file */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Try closing file #2 (should still fail, since there are still objects open in child file) */
+ H5E_BEGIN_TRY {
+ ret = H5Fclose(fid2);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close group in mounted file */
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+
+ /* Close file #2 (should succeed now) */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Close FAPL ID */
+ if(H5Pclose(fapl_id) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
PASSED();
@@ -1940,15 +2246,356 @@ test_hold_open_group(hid_t fapl)
error:
H5E_BEGIN_TRY {
+ H5Pclose(fapl_id);
H5Gclose(gidM);
H5Gclose(gidAM);
- H5Gclose(gidAM2);
H5Gclose(gidA);
H5Fclose(fid2);
H5Fclose(fid1);
} H5E_END_TRY;
return 1;
-} /* end test_hold_open_group() */
+} /* end test_fcdegree_semi() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_fcdegree_strong
+ *
+ * Purpose: Test that the library perform correct actions when using
+ * "strong" file close degree on mounted files
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_fcdegree_strong(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1; /* File IDs */
+ hid_t gidA = -1, gidM = -1, gidAM = -1; /* Group IDs */
+ hid_t fapl_id = -1; /* FAPL IDs */
+ herr_t ret; /* Generic return value */
+ char filename1[1024],
+ filename2[1024]; /* Name of files to mount */
+
+ TESTING("'strong' file close degree");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create FAPL & set file close degree to be "strong" */
+ if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR
+
+ /* Set file close mode to H5F_CLOSE_STRONG */
+ if(H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG) < 0)
+ TEST_ERROR
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl_id)) < 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Check that objects are still open */
+ if (H5Gget_objinfo(gidA, ".", TRUE, NULL) < 0)
+ TEST_ERROR
+ if (H5Gget_objinfo(gidAM, ".", TRUE, NULL) < 0)
+ TEST_ERROR
+
+ /* Close file #2 (should close open objects also) */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Check that objects are closed */
+ H5E_BEGIN_TRY {
+ ret = H5Gget_objinfo(gidA, ".", TRUE, NULL);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+ H5E_BEGIN_TRY {
+ ret = H5Gget_objinfo(gidAM, ".", TRUE, NULL);
+ } H5E_END_TRY;
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close FAPL ID */
+ if(H5Pclose(fapl_id) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_id);
+ H5Gclose(gidM);
+ H5Gclose(gidAM);
+ H5Gclose(gidA);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_fcdegree_strong() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_acc_perm
+ *
+ * Purpose: Test that the library correctly segregates operations in
+ * parts of mounted file hierarchy with files that have different
+ * R/W access permissions.
+ *
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_acc_perm(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1, fid3 = -1; /* File IDs */
+ hid_t gidA = -1, gidB = -1, gidC = -1, gidM = -1, gidAM = -1, gidAMZ = -1; /* Group IDs */
+ hid_t bad_id = -1; /* Bad ID from object create */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ ssize_t name_len; /* Filename length */
+ char filename1[1024],
+ filename2[1024],
+ filename3[1024]; /* Name of files to mount */
+
+ TESTING("access permissions");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ /* Get and verify file name */
+ if((name_len = H5Fget_name(gidA, name, NAME_BUF_SIZE)) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, filename1) != 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Get and verify file name */
+ if((name_len = H5Fget_name(fid2, name, NAME_BUF_SIZE)) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, filename2) != 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Get and verify file name */
+ if((name_len = H5Fget_name(fid2, name, NAME_BUF_SIZE)) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, filename2) != 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Get and verify file name */
+ if((name_len = H5Fget_name(gidAM, name, NAME_BUF_SIZE)) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, filename2) != 0)
+ TEST_ERROR
+
+ /* Attempt to create objects in read only file (should fail) */
+ H5E_BEGIN_TRY {
+ bad_id = H5Gcreate(gidAM, "Z", (size_t)0);
+ } H5E_END_TRY;
+ if(bad_id >= 0)
+ TEST_ERROR
+ H5E_BEGIN_TRY {
+ bad_id = H5Gcreate(fid1, "/A/L", (size_t)0);
+ } H5E_END_TRY;
+ if(bad_id >= 0)
+ TEST_ERROR
+
+ /* Attempt to create objects in read/write file (should succeed) */
+ if((gidB = H5Gcreate(fid2, "/B", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+
+ /* (Note that this object should get created in the "hidden" group for "A" in parent file) */
+ if((gidC = H5Gcreate(gidA, "C", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidC) < 0)
+ TEST_ERROR
+
+ /* Create file #3 (it will have R/W permissions) */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 on file #2 */
+ if(H5Fmount(gidAM, ".", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Attempt to create objects in read/write file (should succeed) */
+ if((gidAMZ = H5Gcreate(fid1, "/A/M/Z", (size_t)0)) < 0)
+ TEST_ERROR
+
+ /* Get and verify file name */
+ if((name_len = H5Fget_name(gidAMZ, name, NAME_BUF_SIZE)) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, filename3) != 0)
+ TEST_ERROR
+
+ /* Close object in file #3 */
+ if(H5Gclose(gidAMZ) < 0)
+ TEST_ERROR
+
+
+ /* Attempt to create objects in read only file again (should fail) */
+ H5E_BEGIN_TRY {
+ bad_id = H5Gcreate(fid1, "/A/L", (size_t)0);
+ } H5E_END_TRY;
+ if(bad_id >= 0)
+ TEST_ERROR
+
+ /* Close group in mounted file */
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+
+ /* Close group in parent file */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Close file #3 */
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Close file #2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidM);
+ H5Gclose(gidAMZ);
+ H5Gclose(gidAM);
+ H5Gclose(gidC);
+ H5Gclose(gidB);
+ H5Gclose(gidA);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_acc_perm() */
/*-------------------------------------------------------------------------
@@ -1995,6 +2642,10 @@ main(void)
nerrors += test_missing_unmount(fapl);
nerrors += test_hold_open_file(fapl);
nerrors += test_hold_open_group(fapl);
+ nerrors += test_fcdegree_same(fapl);
+ nerrors += test_fcdegree_semi(fapl);
+ nerrors += test_fcdegree_strong(fapl);
+ nerrors += test_acc_perm(fapl);
if (nerrors) goto error;
puts("All mount tests passed.");
diff --git a/test/testhdf5.h b/test/testhdf5.h
index ffea037..a29093b 100644
--- a/test/testhdf5.h
+++ b/test/testhdf5.h
@@ -67,7 +67,7 @@
} \
}
-/* Used to make certain a return value _is_ a value */
+/* Used to make certain a scalar return value _is_ a value */
#define VERIFY(x, val, where) do { \
if (GetTestVerbosity()>=VERBO_HI) { \
print_func(" Call to routine: %15s at line %4d in %s had value " \
@@ -80,6 +80,19 @@
} \
} while(0)
+/* Used to make certain a string return value _is_ a value */
+#define VERIFY_STR(x, val, where) do { \
+ if (GetTestVerbosity()>=VERBO_HI) { \
+ print_func(" Call to routine: %15s at line %4d in %s had value " \
+ "%s \n", (where), (int)__LINE__, __FILE__, x); \
+ } \
+ if (HDstrcmp(x, val)) { \
+ TestErrPrintf("*** UNEXPECTED VALUE from %s should be %s, but is %s at line %4d " \
+ "in %s\n", where, val, x, (int)__LINE__, __FILE__); \
+ H5Eprint (stdout); \
+ } \
+} while(0)
+
/* Used to document process through a test and to check for errors */
#define RESULT(ret,func) do { \
if (GetTestVerbosity()>VERBO_MED) { \
diff --git a/test/tfile.c b/test/tfile.c
index dbe974b..057ebb5 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -69,6 +69,15 @@
#define DSET1 "Dataset1"
#define DSET2 "/Group1/Dataset2"
+#define TESTA_GROUPNAME "group"
+#define TESTA_DSETNAME "dataset"
+#define TESTA_ATTRNAME "attribute"
+#define TESTA_DTYPENAME "compound"
+#define TESTA_NAME_BUF_SIZE 64
+#define TESTA_RANK 2
+#define TESTA_NX 4
+#define TESTA_NY 5
+
static void
create_objects(hid_t, hid_t, hid_t *, hid_t *, hid_t *, hid_t *);
static void
@@ -1455,64 +1464,181 @@ test_file_open_overlap(void)
/* Create file */
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- assert(fid1 > 0);
+ CHECK(fid1, FAIL, "H5Fcreate");
/* Open file also */
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
- assert(fid2 > 0);
+ CHECK(fid2, FAIL, "H5Fopen");
/* Create a group in file */
gid = H5Gcreate(fid1, GROUP1, (size_t)0);
- assert(gid > 0);
+ CHECK(gid, FAIL, "H5Gcreate");
/* Create dataspace for dataset */
sid = H5Screate(H5S_SCALAR);
- assert(sid > 0);
+ CHECK(sid, FAIL, "H5Screate");
/* Create dataset in group w/first file ID */
did1 = H5Dcreate(gid, DSET1, H5T_NATIVE_INT, sid, H5P_DEFAULT);
- assert(did1 > 0);
+ CHECK(did1, FAIL, "H5Dcreate");
/* Check number of objects opened in first file */
nobjs = H5Fget_obj_count(fid1, H5F_OBJ_LOCAL|H5F_OBJ_ALL);
- assert(nobjs == 3); /* 3 == file, dataset & group */
+ VERIFY(nobjs, 3, "H5Fget_obj_count"); /* 3 == file, dataset & group */
/* Close dataset */
ret = H5Dclose(did1);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Dclose");
/* Close group */
ret = H5Gclose(gid);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Gclose");
/* Close first file ID */
ret = H5Fclose(fid1);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Fclose");
/* Create dataset with second file ID */
did2 = H5Dcreate(fid2, DSET2, H5T_NATIVE_INT, sid, H5P_DEFAULT);
- assert(did2 > 0);
+ CHECK(did2, FAIL, "H5Dcreate");
/* Check number of objects opened in first file */
nobjs = H5Fget_obj_count(fid2, H5F_OBJ_ALL);
- assert(nobjs == 2); /* 2 == file & dataset */
+ VERIFY(nobjs, 2, "H5Fget_obj_count"); /* 3 == file & dataset */
/* Close dataspace */
ret = H5Sclose(sid);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Sclose");
/* Close second dataset */
ret = H5Dclose(did2);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Dclose");
/* Close second file */
ret = H5Fclose(fid2);
- assert(ret >= 0);
+ CHECK(ret, FAIL, "H5Fclose");
} /* end test_file_open_overlap() */
/****************************************************************
**
+** test_file_getname(): low-level file test routine.
+** This test checks whether H5Fget_name works correctly.
+**
+*****************************************************************/
+static void
+test_file_getname(void)
+{
+ /* Compound datatype */
+ typedef struct s1_t {
+ unsigned int a;
+ float b;
+ } s1_t;
+
+ hid_t file_id;
+ hid_t group_id;
+ hid_t dataset_id;
+ hid_t space_id;
+ hid_t type_id;
+ hid_t attr_id;
+ hsize_t dims[TESTA_RANK] = {TESTA_NX, TESTA_NY};
+ char name[TESTA_NAME_BUF_SIZE];
+ ssize_t name_len;
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing H5Fget_name() functionality\n"));
+
+ /* Create a new file_id using default properties. */
+ file_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
+ CHECK(file_id, FAIL, "H5Fcreate");
+
+ /* Get and verify file name */
+ name_len = H5Fget_name(file_id, name, TESTA_NAME_BUF_SIZE);
+ CHECK(name_len, FAIL, "H5Fget_name");
+ VERIFY_STR(name, FILE1, "H5Fget_name");
+
+ /* Create a group in the root group */
+ group_id = H5Gcreate(file_id, TESTA_GROUPNAME, 0);
+ CHECK(group_id, FAIL, "H5Gcreate");
+
+ /* Get and verify file name */
+ name_len = H5Fget_name(group_id, name, TESTA_NAME_BUF_SIZE);
+ CHECK(name_len, FAIL, "H5Fget_name");
+ VERIFY_STR(name, FILE1, "H5Fget_name");
+
+ /* Create the data space */
+ space_id = H5Screate_simple(TESTA_RANK, dims, NULL);
+ CHECK(space_id, FAIL, "H5Screate_simple");
+
+ /* Try get file name from data space. Supposed to fail because
+ * it's illegal operation. */
+ H5E_BEGIN_TRY {
+ name_len = H5Fget_name(space_id, name, TESTA_NAME_BUF_SIZE);
+ } H5E_END_TRY;
+ VERIFY(name_len, FAIL, "H5Fget_name");
+
+ /* Create a new dataset */
+ dataset_id = H5Dcreate(file_id, TESTA_DSETNAME, H5T_NATIVE_INT, space_id, H5P_DEFAULT);
+ CHECK(dataset_id, FAIL, "H5Dcreate");
+
+ /* Get and verify file name */
+ name_len = H5Fget_name(dataset_id, name, TESTA_NAME_BUF_SIZE);
+ CHECK(name_len, FAIL, "H5Fget_name");
+ VERIFY_STR(name, FILE1, "H5Fget_name");
+
+ /* Create an attribute for the dataset */
+ attr_id = H5Acreate(dataset_id,TESTA_ATTRNAME,H5T_NATIVE_INT,space_id,H5P_DEFAULT);
+ CHECK(attr_id, FAIL, "H5Acreate");
+
+ /* Get and verify file name */
+ name_len = H5Fget_name(attr_id, name, TESTA_NAME_BUF_SIZE);
+ CHECK(name_len, FAIL, "H5Fget_name");
+ VERIFY_STR(name, FILE1, "H5Fget_name");
+
+ /* Create a compound datatype */
+ type_id = H5Tcreate(H5T_COMPOUND, sizeof(s1_t));
+ CHECK(type_id, FAIL, "H5Tcreate");
+
+ /* Insert fields */
+ ret = H5Tinsert (type_id, "a", HOFFSET(s1_t,a), H5T_NATIVE_INT);
+ CHECK(ret, FAIL, "H5Tinsert");
+
+ ret = H5Tinsert (type_id, "b", HOFFSET(s1_t,b), H5T_NATIVE_FLOAT);
+ CHECK(ret, FAIL, "H5Tinsert");
+
+ /* Save it on file */
+ ret = H5Tcommit(file_id, TESTA_DTYPENAME, type_id);
+ CHECK(ret, FAIL, "H5Tcommit");
+
+ /* Get and verify file name */
+ name_len = H5Fget_name(type_id, name, TESTA_NAME_BUF_SIZE);
+ CHECK(name_len, FAIL, "H5Fget_name");
+ VERIFY_STR(name, FILE1, "H5Fget_name");
+
+ /* Close things down */
+ ret = H5Tclose(type_id);
+ CHECK(ret, FAIL, "H5Tclose");
+
+ ret = H5Aclose(attr_id);
+ CHECK(ret, FAIL, "H5Aclose");
+
+ ret = H5Dclose(dataset_id);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ ret = H5Sclose(space_id);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ ret = H5Gclose(group_id);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Fclose(file_id);
+ CHECK(ret, FAIL, "H5Fclose");
+
+} /* end test_file_getname() */
+
+/****************************************************************
+**
** test_file(): Main low-level file I/O test routine.
**
****************************************************************/
@@ -1533,6 +1659,7 @@ test_file(void)
test_file_ishdf5(); /* Test detecting HDF5 files correctly */
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() */