[svn-r11093] 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
This commit is contained in:
Quincey Koziol 2005-07-21 09:48:26 -05:00
parent e9d54ca186
commit bb31e94a92
20 changed files with 1520 additions and 771 deletions

View File

@ -622,7 +622,6 @@ a------------------------------------------------------------------------------
./test/family_v1.6_00001.h5
./test/family_v1.6_00002.h5
./test/family_v1.6_00003.h5
./test/filename.c
./test/fill_old.h5
./test/fillval.c
./test/flush1.c

108
src/H5.c
View File

@ -2098,9 +2098,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;
@ -2300,60 +2297,57 @@ 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_UNINIT:
fprintf (out, "H5I_UNINIT");
break;
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_ERROR_CLASS:
fprintf (out, "H5I_ERROR_CLASS");
break;
case H5I_ERROR_MSG:
fprintf (out, "H5I_ERROR_MSG");
break;
case H5I_ERROR_STACK:
fprintf (out, "H5I_ERROR_STACK");
break;
case H5I_NTYPES:
fprintf (out, "H5I_NTYPES");
break;
default:
fprintf (out, "%ld", (long)id_type);
break;
case H5I_UNINIT:
fprintf (out, "H5I_UNINIT");
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_ERROR_CLASS:
fprintf (out, "H5I_ERROR_CLASS");
break;
case H5I_ERROR_MSG:
fprintf (out, "H5I_ERROR_MSG");
break;
case H5I_ERROR_STACK:
fprintf (out, "H5I_ERROR_STACK");
break;
case H5I_NTYPES:
fprintf (out, "H5I_NTYPES");
break;
default:
fprintf (out, "%ld", (long)id_type);
break;
}
}
break;

View File

@ -4101,8 +4101,6 @@ done:
*
* Date: August 14, 2002
*
* Comments: Just flushing the compact data information currently.
*
* Modifications:
*
*-------------------------------------------------------------------------
@ -4110,11 +4108,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)
@ -4122,18 +4120,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 */

715
src/H5F.c
View File

@ -60,6 +60,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 */
#ifdef NOT_YET
@ -67,19 +73,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
@ -220,15 +238,9 @@ H5F_init_interface(void)
FUNC_ENTER_NOAPI_NOINIT(H5F_init_interface)
/*
* Initialize the atom group for the file IDs. There are two groups:
* the H5I_FILE group contains all the ID's for files which are currently
* open at the public API level while the H5I_FILE_CLOSING group contains
* ID's for files for which the application has called H5Fclose() but
* which are pending completion because there are object headers still
* open within the file.
* Initialize the atom group for the file IDs.
*/
if (H5I_register_type(H5I_FILE, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<H5I_FILE ||
H5I_register_type(H5I_FILE_CLOSING, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<H5I_FILE)
if (H5I_register_type(H5I_FILE, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<H5I_FILE)
HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
/* ========== File Creation Property Class Initialization ============*/
@ -438,13 +450,11 @@ H5F_term_interface(void)
if (H5_interface_initialize_g) {
if ((n=H5I_nmembers(H5I_FILE))!=0) {
H5I_clear_type(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_dec_type_ref(H5I_FILE);
H5I_dec_type_ref(H5I_FILE_CLOSING);
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
}
@ -962,17 +972,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)
}
@ -1014,7 +1022,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5F_get_object_ids
* Function: H5F_get_obj_ids
*
* Purpose: Private function to return a list of opened object IDs.
*
@ -1027,17 +1035,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)
}
@ -1057,12 +1063,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)
@ -1084,45 +1090,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)
}
@ -1294,39 +1297,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* 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
@ -1557,20 +1527,19 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
* The cache might be created with a different number of elements and
* the access property list should be updated to reflect that.
*/
if ( SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg)) ) {
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, \
"unable to create meta data cache")
}
if ( SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg)) )
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache")
/* 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;
@ -1627,77 +1596,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 */
/* Sanity check */
HDassert(f);
/* 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) {
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 */
} /* 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 */
/* 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 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 */
/* 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;
}
/* 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*/
}
/* 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 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() */
/*-------------------------------------------------------------------------
@ -1836,8 +1811,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
@ -1847,24 +1821,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;
@ -2608,26 +2575,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:
@ -2642,134 +2641,81 @@ 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 */
/* If there are other open files in the hierarchy, we can leave now */
if(nopen_files > 0)
HGOTO_DONE(SUCCEED)
/* 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 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.
/* Mark this file as closing (prevents re-entering file shutdown code below) */
f->closing = TRUE;
/* 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);
/* 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.
*/
assert(NULL==f->mtab.parent);
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 file")
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
/* Invalidate file ID */
f->file_id = -1;
/* Flush at this point since the file will be closed */
/* 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) {
#ifdef H5_HAVE_FPHDF5
/*
@ -2803,12 +2749,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() */
/*-------------------------------------------------------------------------
@ -2835,14 +2781,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
@ -2898,6 +2872,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")
@ -2906,7 +2883,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)
}
@ -3292,15 +3269,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)
@ -4154,21 +4125,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 */
@ -4179,3 +4162,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() */

View File

@ -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;
@ -95,46 +95,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_close_mounts() */
/*-------------------------------------------------------------------------
* 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
@ -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,100 +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)
FUNC_ENTER_NOAPI(H5F_mount_count_ids, FAIL)
/* 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 */
/* Sanity check */
HDassert(f);
HDassert(nopen_files);
HDassert(nopen_objs);
/* 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)
/* Find the top file in the mounting hierarchy */
while(f->mtab.parent)
f = f->mtab.parent;
/* 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 */
/* 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() */

View File

@ -93,7 +93,7 @@ typedef struct H5F_file_t {
haddr_t freespace_addr; /* Relative address of free-space info */
haddr_t driver_addr; /* File driver information block address*/
hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2 */
unsigned super_chksum; /* Superblock checksum */
unsigned drvr_chksum; /* Driver info block checksum */
H5AC_t *cache; /* The object cache */
@ -144,13 +144,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 */
};
@ -165,14 +164,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 hsize_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id);

View File

@ -438,8 +438,8 @@ H5_DLL hid_t H5F_get_access_plist(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

View File

@ -2091,7 +2091,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)))
@ -2101,7 +2102,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++;
}
@ -2254,11 +2258,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)
{
@ -2271,7 +2278,7 @@ H5G_close(H5G_t *grp)
done:
FUNC_LEAVE_NOAPI(ret_value);
}
} /* end H5G_close() */
/*-------------------------------------------------------------------------
@ -2547,6 +2554,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;
@ -4121,8 +4131,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() */

View File

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

View File

@ -167,6 +167,8 @@ H5_DLL herr_t H5G_replace_name(H5G_obj_t 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.

View File

@ -125,7 +125,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 type);
#endif /* H5I_DEBUG_OUTPUT */
@ -483,9 +482,6 @@ int
H5I_nmembers(H5I_type_t type)
{
H5I_id_type_t *type_ptr = NULL;
H5I_id_info_t *cur=NULL;
int n=0;
unsigned i;
int ret_value;
FUNC_ENTER_NOAPI(H5I_nmembers, FAIL);
@ -495,12 +491,8 @@ H5I_nmembers(H5I_type_t type)
if (NULL==(type_ptr=H5I_id_type_list_g[type]) || type_ptr->count<=0)
HGOTO_DONE(0);
for (i=0; i<type_ptr->hash_size; i++)
for (cur=type_ptr->id_list[i]; cur; cur=cur->next)
n++;
/* Set return value */
ret_value=n;
H5_ASSIGN_OVERFLOW(ret_value, type_ptr->ids, unsigned, int);
done:
FUNC_LEAVE_NOAPI(ret_value);
@ -971,18 +963,14 @@ void *H5Iobject_verify(hid_t id, H5I_type_t id_type)
FUNC_ENTER_API(H5Iobject_verify, NULL);
if( H5I_IS_LIB_TYPE( id_type ) )
{
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type");
}
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
if(id_type < 1 || id_type >= H5I_next_type)
{
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type");
}
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
ret_value = H5I_object_verify(id, id_type);
done:
done:
FUNC_LEAVE_API(ret_value);
}
@ -1127,9 +1115,7 @@ void *H5Iremove_verify(hid_t id, H5I_type_t id_type)
FUNC_ENTER_API(H5Iremove_verify, NULL);
if( H5I_IS_LIB_TYPE( id_type ) )
{
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type");
}
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
/* Remove the id */
ret_value = H5I_remove_verify(id, id_type);
@ -1516,7 +1502,7 @@ done:
*
*-------------------------------------------------------------------------
*/
static int
int
H5I_get_ref(hid_t id)
{
H5I_type_t type; /*type the object is in*/
@ -1906,20 +1892,23 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key)
if (type_ptr == NULL || type_ptr->count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type");
/* Start at the beginning of the array */
for (i=0; i<type_ptr->hash_size; i++) {
id_ptr = type_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(type_ptr->ids > 0) {
/* Start at the beginning of the array */
for (i=0; i<type_ptr->hash_size; i++) {
id_ptr = type_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() */
/*-------------------------------------------------------------------------

View File

@ -60,6 +60,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
H5_DLL void *H5I_search(H5I_type_t type, 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);
H5_DLL int H5I_inc_type_ref(H5I_type_t type);

View File

@ -36,7 +36,6 @@ typedef enum H5I_type_t {
H5I_UNINIT = (-2), /*uninitialized type */
H5I_BADID = (-1), /*invalid Type */
H5I_FILE = 1, /*type ID for File objects */
H5I_FILE_CLOSING, /*files pending close due to open objhdrs */
H5I_GROUP, /*type ID for Group objects */
H5I_DATATYPE, /*type ID for Datatype objects */
H5I_DATASPACE, /*type ID for Dataspace objects */

View File

@ -412,7 +412,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));
@ -423,28 +423,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 */
@ -452,7 +437,7 @@ H5O_close(H5G_entry_t *obj_ent)
done:
FUNC_LEAVE_NOAPI(ret_value);
}
} /* end H5O_close() */
/*-------------------------------------------------------------------------
@ -1920,7 +1905,7 @@ H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message not found");
} /* end if */
/* Check for creating new message */
/* Check for creating new message */
if (overwrite < 0) {
/* Create a new message */
if((idx=H5O_new_mesg(ent->file,oh,&flags,type,mesg,&sh_mesg,&type,&mesg,dxpl_id,&oh_flags))==UFAIL)
@ -2265,7 +2250,6 @@ H5O_write_mesg(H5O_t *oh, unsigned idx, const H5O_class_t *type,
unsigned * oh_flags_ptr)
{
H5O_mesg_t *idx_msg; /* Pointer to message to modify */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_write_mesg);

View File

@ -34,7 +34,7 @@ TEST_PROG=testhdf5 lheap ohdr stab gheap cache b+tree btree2 blocktrack sheap \
dtypes dsets cmpd_dset extend external links unlink big mtime \
fillval mount flush1 flush2 enum \
set_extent ttsafe stream_test \
getname vfd ntypes dangle dtransform filename reserved
getname vfd ntypes dangle dtransform reserved
# List programs to be built when testing here. error_test and err_compat are
# built at the same time as the other tests, but executed by testerror.sh.

View File

@ -29,7 +29,7 @@
#
# HDF5 Library Test Makefile(.in)
#
SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c filename.c fillval.c flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c fillval.c flush1.c flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@ -81,7 +81,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
flush2$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \
ttsafe$(EXEEXT) stream_test$(EXEEXT) getname$(EXEEXT) \
vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \
dtransform$(EXEEXT) filename$(EXEEXT) reserved$(EXEEXT)
dtransform$(EXEEXT) reserved$(EXEEXT)
b_tree_SOURCES = b+tree.c
b_tree_OBJECTS = b+tree.$(OBJEXT)
b_tree_LDADD = $(LDADD)
@ -150,10 +150,6 @@ external_SOURCES = external.c
external_OBJECTS = external.$(OBJEXT)
external_LDADD = $(LDADD)
external_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1)
filename_SOURCES = filename.c
filename_OBJECTS = filename.$(OBJEXT)
filename_LDADD = $(LDADD)
filename_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1)
fillval_SOURCES = fillval.c
fillval_OBJECTS = fillval.$(OBJEXT)
fillval_LDADD = $(LDADD)
@ -273,19 +269,19 @@ LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c \
blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c \
dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \
error_test.c extend.c external.c filename.c fillval.c flush1.c \
flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c \
links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c \
set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) \
testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
error_test.c extend.c external.c fillval.c flush1.c flush2.c \
getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c \
mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c \
stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c \
$(ttsafe_SOURCES) unlink.c vfd.c
DIST_SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c \
blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c \
dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \
error_test.c extend.c external.c filename.c fillval.c flush1.c \
flush2.c getname.c gheap.c hyperslab.c istore.c lheap.c \
links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c \
set_extent.c sheap.c stab.c stream_test.c $(testhdf5_SOURCES) \
testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
error_test.c extend.c external.c fillval.c flush1.c flush2.c \
getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c \
mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c \
stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c \
$(ttsafe_SOURCES) unlink.c vfd.c
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -532,7 +528,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache b+tree btree2 blocktrack sheap
dtypes dsets cmpd_dset extend external links unlink big mtime \
fillval mount flush1 flush2 enum \
set_extent ttsafe stream_test \
getname vfd ntypes dangle dtransform filename reserved
getname vfd ntypes dangle dtransform reserved
# The libh5test.a library provides common support code for the tests.
@ -677,9 +673,6 @@ extend$(EXEEXT): $(extend_OBJECTS) $(extend_DEPENDENCIES)
external$(EXEEXT): $(external_OBJECTS) $(external_DEPENDENCIES)
@rm -f external$(EXEEXT)
$(LINK) $(external_LDFLAGS) $(external_OBJECTS) $(external_LDADD) $(LIBS)
filename$(EXEEXT): $(filename_OBJECTS) $(filename_DEPENDENCIES)
@rm -f filename$(EXEEXT)
$(LINK) $(filename_LDFLAGS) $(filename_OBJECTS) $(filename_LDADD) $(LIBS)
fillval$(EXEEXT): $(fillval_OBJECTS) $(fillval_DEPENDENCIES)
@rm -f fillval$(EXEEXT)
$(LINK) $(fillval_LDFLAGS) $(fillval_OBJECTS) $(fillval_LDADD) $(LIBS)
@ -776,7 +769,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extend.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/external.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filename.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillval.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush2.Po@am__quote@

View File

@ -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_stack(H5E_DEFAULT, 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;
}

View File

@ -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;
@ -972,7 +978,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);
@ -985,21 +990,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)
@ -1013,6 +1018,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;
@ -1657,10 +1666,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;
@ -1795,10 +1800,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;
@ -1835,7 +1836,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 */
@ -1916,23 +1917,44 @@ 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
/* Close file #1 */
/* (should unmount file #2 also) */
if(H5Fclose(fid1) < 0)
/* 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
/* Check that all "file closing" IDs have been closed */
if(H5I_nmembers(H5I_FILE_CLOSING) != 0)
TEST_ERROR
PASSED();
return 0;
@ -1942,12 +1964,637 @@ error:
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 */
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
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();
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_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() */
/*-------------------------------------------------------------------------
* Function: main
@ -1993,6 +2640,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.");

View File

@ -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_stack(H5E_DEFAULT, stdout); \
} \
} while(0)
/* Used to document process through a test and to check for errors */
#define RESULT(ret,func) do { \
if (GetTestVerbosity()>VERBO_MED) { \

View File

@ -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
@ -1447,62 +1456,179 @@ 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.
@ -1525,6 +1651,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() */