mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-19 16:50:46 +08:00
[svn-r4696]
Purpose: Modify H5Fclose behavior Description: The HDF5 actual file close behaves in several ways in terms of if there are still objects(dataset, group, datatype) opened in file. Solution: Added a new file access property, file close degree. It has four values, H5F_CLOSE_DEFAULT H5F_CLOSE_WEAK H5F_CLOSE_SEMI H5F_CLOSE_STRONG The way a file is closed is decided by these values. Platforms tested: IRIX64 6.5, SunOS 5.6, FreeBSD 4.4
This commit is contained in:
parent
33ed41455e
commit
d28fd08f4a
@ -33,7 +33,6 @@
|
||||
*/
|
||||
#include "H5FDmpio.h"
|
||||
|
||||
|
||||
#ifdef H5_HAVE_PARALLEL
|
||||
/* Remove this if H5R_DATASET_REGION is no longer used in this file */
|
||||
# include "H5Rpublic.h"
|
||||
|
505
src/H5F.c
505
src/H5F.c
@ -39,7 +39,7 @@
|
||||
#include "H5Iprivate.h" /*object IDs */
|
||||
#include "H5ACprivate.h" /*cache */
|
||||
#include "H5Eprivate.h" /*error handling */
|
||||
#include "H5Fpkg.h" /*file access */
|
||||
#include "H5Fpkg.h" /*file access */
|
||||
#include "H5FDprivate.h" /*file driver */
|
||||
#include "H5Gprivate.h" /*symbol tables */
|
||||
#include "H5MMprivate.h" /*core memory management */
|
||||
@ -53,13 +53,28 @@ static int interface_initialize_g = 0;
|
||||
#define INTERFACE_INIT H5F_init_interface
|
||||
static herr_t H5F_init_interface(void);
|
||||
|
||||
/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */
|
||||
typedef struct H5F_olist_t {
|
||||
H5I_type_t obj_type;
|
||||
hid_t *obj_id_list;
|
||||
unsigned *obj_id_count;
|
||||
H5F_file_t *shared;
|
||||
unsigned list_index;
|
||||
} H5F_olist_t;
|
||||
|
||||
/* PRIVATE PROTOTYPES */
|
||||
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);
|
||||
static herr_t H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
|
||||
hbool_t alloc_only);
|
||||
static haddr_t H5F_locate_signature(H5FD_t *file);
|
||||
static int H5F_flush_all_cb(H5F_t *f, const void *_invalidate);
|
||||
static int H5F_flush_all_cb(H5F_t *f, hid_t fid, const void *_invalidate);
|
||||
static herr_t H5F_get_obj_count(H5F_t *f, unsigned types,
|
||||
unsigned *obj_id_count);
|
||||
static herr_t H5F_get_obj_ids(H5F_t *f, unsigned types, hid_t *obj_id_list);
|
||||
static herr_t H5F_get_objects(H5F_t *f, unsigned types, hid_t *obj_id_list,
|
||||
unsigned *obj_id_count);
|
||||
static herr_t H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
|
||||
|
||||
/* Declare a free list to manage the H5F_t struct */
|
||||
H5FL_DEFINE_STATIC(H5F_t);
|
||||
@ -184,6 +199,8 @@ H5F_init_interface(void)
|
||||
unsigned gc_ref = H5F_ACS_GARBG_COLCT_REF_DEF;
|
||||
hid_t driver_id = H5F_ACS_FILE_DRV_ID_DEF;
|
||||
void *driver_info = H5F_ACS_FILE_DRV_INFO_DEF;
|
||||
H5F_close_degree_t close_degree = H5F_CLOSE_DEGREE_DEF;
|
||||
|
||||
/* File mount property class variable.
|
||||
* - Mount property class to modify
|
||||
* - whether absolute symlinks is local to file
|
||||
@ -356,6 +373,11 @@ H5F_init_interface(void)
|
||||
/* Register the file driver info */
|
||||
if(H5P_register(acs_pclass,H5F_ACS_FILE_DRV_INFO_NAME,H5F_ACS_FILE_DRV_INFO_SIZE, &driver_info,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class");
|
||||
|
||||
/* Register the file close degree */
|
||||
if(H5P_register(acs_pclass,H5F_CLOSE_DEGREE_NAME,H5F_CLOSE_DEGREE_SIZE, &close_degree,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class");
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Only register the default property list if it hasn't been created yet */
|
||||
@ -610,7 +632,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
H5F_flush_all_cb(H5F_t *f, const void *_invalidate)
|
||||
H5F_flush_all_cb(H5F_t *f, hid_t fid, const void *_invalidate)
|
||||
{
|
||||
hbool_t invalidate = *((const hbool_t*)_invalidate);
|
||||
H5F_flush(f, H5F_SCOPE_LOCAL, invalidate, FALSE);
|
||||
@ -788,7 +810,8 @@ H5Fget_access_plist(hid_t file_id)
|
||||
H5P_genplist_t *new_plist; /* New property list */
|
||||
H5P_genplist_t *old_plist; /* Old property list */
|
||||
hid_t ret_value = SUCCEED;
|
||||
|
||||
void *driver_info=NULL;
|
||||
|
||||
FUNC_ENTER(H5Fget_access_plist, FAIL);
|
||||
H5TRACE1("i","i",file_id);
|
||||
|
||||
@ -828,13 +851,292 @@ H5Fget_access_plist(hid_t file_id)
|
||||
|
||||
if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID");
|
||||
if(H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, H5FD_fapl_get(f->shared->lf)) < 0)
|
||||
|
||||
driver_info = H5FD_fapl_get(f->shared->lf);
|
||||
if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, driver_info) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info");
|
||||
|
||||
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) {
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree");
|
||||
} else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) {
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree");
|
||||
}
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Fget_obj_count
|
||||
*
|
||||
* Purpose: Public function returning the number of opened object IDs
|
||||
* (files, datasets, groups and datatypes) in the same file.
|
||||
*
|
||||
* Return: Non-negative on success; negative on failure.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5Fget_obj_count(hid_t file_id, unsigned types, unsigned *obj_id_count)
|
||||
{
|
||||
H5F_t *f=NULL;
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER(H5Fget_obj_counts, FAIL);
|
||||
H5TRACE3("e","iIu*Iu",file_id,types,obj_id_count);
|
||||
|
||||
if( file_id != H5F_OBJ_ALL && (H5I_FILE != H5I_get_type(file_id) ||
|
||||
NULL==(f=H5I_object(file_id))) )
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id");
|
||||
if( (types&H5F_OBJ_ALL)==0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type");
|
||||
assert(obj_id_count);
|
||||
|
||||
ret_value = H5F_get_obj_count(f, types, obj_id_count);
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_get_obj_count
|
||||
*
|
||||
* Purpose: Private function return the number of opened object IDs
|
||||
* (files, datasets, groups, datatypes) in the same file.
|
||||
*
|
||||
* Return: Non-negative on success; negative on failure.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5F_get_obj_count(H5F_t *f, unsigned types, unsigned *obj_id_count)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER(H5F_get_obj_count, FAIL);
|
||||
*obj_id_count = 0;
|
||||
|
||||
if(H5F_get_objects(f, types, NULL, obj_id_count) < 0)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get counts of opened file IDs and object IDs in the file");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Fget_object_ids
|
||||
*
|
||||
* Purpose: Public function to return a list of opened object IDs.
|
||||
*
|
||||
* Return: Non-negative on success; negative on failure.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5Fget_obj_ids(hid_t file_id, unsigned types, hid_t *oid_list)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
H5F_t *f=NULL;
|
||||
|
||||
FUNC_ENTER(H5Fget_obj_ids, FAIL);
|
||||
H5TRACE3("e","iIu*i",file_id,types,oid_list);
|
||||
if( file_id != H5F_OBJ_ALL && (H5I_FILE != H5I_get_type(file_id) ||
|
||||
NULL==(f=H5I_object(file_id))) )
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id");
|
||||
if( (types&H5F_OBJ_ALL)==0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type");
|
||||
assert(oid_list);
|
||||
|
||||
ret_value = H5F_get_obj_ids(f, types, oid_list);
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_get_object_ids
|
||||
*
|
||||
* Purpose: Private function to return a list of opened object IDs.
|
||||
*
|
||||
* Return: Non-negative on success; negative on failure.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5F_get_obj_ids(H5F_t *f, unsigned types, hid_t *oid_list)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER(H5F_get_obj_ids, FAIL);
|
||||
|
||||
if(H5F_get_objects(f, types, oid_list, NULL) < 0)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object IDs opened in the file");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Function: H5F_get_objects
|
||||
*
|
||||
* Purpose: This function is called by H5F_get_obj_count or
|
||||
* H5F_get_obj_ids to get either number of object IDs or a
|
||||
* list of opened object IDs.
|
||||
* Return: Non-negative on success; negative on failure.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5F_get_objects(H5F_t *f, unsigned types, hid_t *obj_id_list,
|
||||
unsigned *obj_id_count)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
H5F_olist_t *olist = NULL;
|
||||
|
||||
FUNC_ENTER(H5F_get_object, FAIL);
|
||||
|
||||
olist = H5MM_malloc(sizeof(H5F_olist_t));
|
||||
olist->obj_id_list = obj_id_list;
|
||||
olist->obj_id_count = obj_id_count;
|
||||
olist->list_index = 0;
|
||||
/* Shared file structure is used to verify if file IDs refer to the same
|
||||
* file. */
|
||||
if(f != NULL)
|
||||
olist->shared = f->shared;
|
||||
else
|
||||
olist->shared = NULL;
|
||||
|
||||
/* 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 ) {
|
||||
olist->obj_type = H5I_FILE;
|
||||
H5I_search(H5I_FILE, (H5I_search_func_t)H5F_get_objects_cb, olist);
|
||||
}
|
||||
|
||||
/* Search through dataset IDs to count number of dataset, and put their
|
||||
* IDs on the object list */
|
||||
if( (types & H5F_OBJ_DATASET) && H5I_nmembers(H5I_DATASET) > 0 ) {
|
||||
olist->obj_type = H5I_DATASET;
|
||||
H5I_search(H5I_DATASET, (H5I_search_func_t)H5F_get_objects_cb, olist);
|
||||
}
|
||||
|
||||
/* Search through group IDs to count number of group, and put their
|
||||
* IDs on the object list */
|
||||
if( (types & H5F_OBJ_GROUP) && H5I_nmembers(H5I_GROUP) > 0 ) {
|
||||
olist->obj_type = H5I_GROUP;
|
||||
H5I_search(H5I_GROUP, (H5I_search_func_t)H5F_get_objects_cb, olist);
|
||||
}
|
||||
|
||||
/* Search through datatype IDs to count number of datatype, and put their
|
||||
* IDs on the object list */
|
||||
if( (types & H5F_OBJ_DATATYPE) && H5I_nmembers(H5I_DATATYPE) > 0 ) {
|
||||
olist->obj_type = H5I_DATATYPE;
|
||||
H5I_search(H5I_DATATYPE, (H5I_search_func_t)H5F_get_objects_cb, olist);
|
||||
}
|
||||
|
||||
done:
|
||||
if(olist!=NULL)
|
||||
H5MM_xfree(olist);
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_get_objects_cb
|
||||
*
|
||||
* Purpose: H5F_get_objects' callback function. It verifies if an
|
||||
* object is in the file, and either count it or put its ID
|
||||
* on the list.
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Wednesday, Dec 5, 2001
|
||||
*
|
||||
* Modification:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
H5F_olist_t *olist = key;
|
||||
H5G_entry_t *ent = NULL;
|
||||
|
||||
FUNC_ENTER(H5F_get_objects_cb, FAIL);
|
||||
assert(obj_ptr);
|
||||
assert(olist);
|
||||
|
||||
/* Count file IDs */
|
||||
if(olist->obj_type == H5I_FILE) {
|
||||
if( !olist->shared || (olist->shared && ((H5F_t*)obj_ptr)->shared ==
|
||||
olist->shared) ) {
|
||||
if(olist->obj_id_list) {
|
||||
olist->obj_id_list[olist->list_index] = obj_id;
|
||||
olist->list_index++;
|
||||
}
|
||||
if(olist->obj_id_count)
|
||||
(*olist->obj_id_count)++;
|
||||
}
|
||||
} else { /* either count opened object IDs or put the IDs on the list */
|
||||
switch(olist->obj_type) {
|
||||
case H5I_GROUP:
|
||||
ent = H5G_entof((H5G_t*)obj_ptr);
|
||||
break;
|
||||
case H5I_DATASET:
|
||||
ent = H5D_entof((H5D_t*)obj_ptr);
|
||||
break;
|
||||
case H5I_DATATYPE:
|
||||
ent = H5T_entof((H5T_t*)obj_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
if( (!olist->shared && olist->obj_type==H5I_DATATYPE &&
|
||||
H5T_is_immutable((H5T_t*)obj_ptr)==FALSE)
|
||||
|| (!olist->shared && olist->obj_type!=H5I_DATATYPE)
|
||||
|| (ent && ent->file->shared == olist->shared) ) {
|
||||
if(olist->obj_id_list) {
|
||||
olist->obj_id_list[olist->list_index] = obj_id;
|
||||
olist->list_index++;
|
||||
}
|
||||
if(olist->obj_id_count)
|
||||
(*olist->obj_id_count)++;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_equal
|
||||
@ -854,7 +1156,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
H5F_equal(void *_haystack, const void *_needle)
|
||||
H5F_equal(void *_haystack, UNUSED hid_t id, const void *_needle)
|
||||
{
|
||||
H5F_t *haystack = (H5F_t*)_haystack;
|
||||
const H5FD_t *needle = (const H5FD_t*)_needle;
|
||||
@ -1094,7 +1396,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
|
||||
if ((n=H5AC_create(f, f->shared->mdc_nelmts))<0)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache");
|
||||
f->shared->mdc_nelmts = n;
|
||||
|
||||
|
||||
/* Create the chunk cache */
|
||||
H5F_istore_init(f);
|
||||
} /* end else */
|
||||
@ -1319,8 +1621,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
size_t sizeof_size = 0;
|
||||
unsigned sym_leaf_k = 0;
|
||||
int btree_k[H5B_NUM_BTREE_ID];
|
||||
H5P_genplist_t *plist; /* Property list */
|
||||
|
||||
H5P_genplist_t *c_plist;
|
||||
H5P_genplist_t *a_plist; /* Property list */
|
||||
H5F_close_degree_t fc_degree;
|
||||
|
||||
FUNC_ENTER(H5F_open, NULL);
|
||||
|
||||
/*
|
||||
@ -1425,7 +1729,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
file->name = H5MM_xstrdup(name);
|
||||
|
||||
/* Get the shared file creation property list */
|
||||
if(NULL == (plist = H5I_object(shared->fcpl_id)))
|
||||
if(NULL == (c_plist = H5I_object(shared->fcpl_id)))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get property list");
|
||||
|
||||
/*
|
||||
@ -1438,7 +1742,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
* which we have already insured is a proper size. The base address
|
||||
* is set to the same thing as the superblock for now.
|
||||
*/
|
||||
if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0)
|
||||
if(H5P_get(c_plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get user block size");
|
||||
shared->boot_addr = userblock_size;
|
||||
shared->base_addr = shared->boot_addr;
|
||||
@ -1465,21 +1769,21 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
boot_vers = *p++;
|
||||
if(HDF5_BOOTBLOCK_VERSION != boot_vers)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock version number");
|
||||
if(H5P_set(plist, H5F_CRT_BOOT_VERS_NAME, &boot_vers) < 0)
|
||||
if(H5P_set(c_plist, H5F_CRT_BOOT_VERS_NAME, &boot_vers) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set boot version");
|
||||
|
||||
/* Freespace version */
|
||||
freespace_vers = *p++;
|
||||
if(HDF5_FREESPACE_VERSION != freespace_vers)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number");
|
||||
if(H5P_set(plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers)<0)
|
||||
if(H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to free space version");
|
||||
|
||||
/* Root group version number */
|
||||
obj_dir_vers = *p++;
|
||||
if(HDF5_OBJECTDIR_VERSION != obj_dir_vers)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number");
|
||||
if(H5P_set(plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0)
|
||||
if(H5P_set(c_plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set object directory version");
|
||||
|
||||
/* reserved */
|
||||
@ -1489,7 +1793,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
share_head_vers = *p++;
|
||||
if(HDF5_SHAREDHEADER_VERSION != share_head_vers)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number");
|
||||
if(H5P_set(plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0)
|
||||
if(H5P_set(c_plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set shared-header format version");
|
||||
|
||||
/* Size of file addresses */
|
||||
@ -1497,7 +1801,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
if (sizeof_addr != 2 && sizeof_addr != 4 &&
|
||||
sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address");
|
||||
if(H5P_set(plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr)<0)
|
||||
if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address");
|
||||
|
||||
/* Size of file sizes */
|
||||
@ -1505,7 +1809,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
if (sizeof_size != 2 && sizeof_size != 4 &&
|
||||
sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size");
|
||||
if(H5P_set(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size)<0)
|
||||
if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size");
|
||||
|
||||
/* Reserved byte */
|
||||
@ -1515,16 +1819,16 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
UINT16DECODE(p, sym_leaf_k);
|
||||
if(sym_leaf_k < 1)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank");
|
||||
if(H5P_set(plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k)<0)
|
||||
if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes");
|
||||
|
||||
/* Need 'get' call to set other array values */
|
||||
if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0)
|
||||
if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes");
|
||||
UINT16DECODE(p, btree_k[H5B_SNODE_ID]);
|
||||
if(btree_k[H5B_SNODE_ID] < 1)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes");
|
||||
if(H5P_set(plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0)
|
||||
if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for btree internal nodes");
|
||||
|
||||
/* File consistency flags. Not really used yet */
|
||||
@ -1587,7 +1891,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
* The user-defined data is the area of the file before the base
|
||||
* address.
|
||||
*/
|
||||
if(H5P_set(plist, H5F_CRT_USER_BLOCK_NAME, &(shared->base_addr)) < 0)
|
||||
if(H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &(shared->base_addr)) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set usr block size");
|
||||
|
||||
/*
|
||||
@ -1608,6 +1912,29 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to set end-of-address marker for file");
|
||||
}
|
||||
|
||||
/* Decide the file close degree. If it's the first time to open the
|
||||
* file, set the degree to access property list value; if it's the
|
||||
* second time or later, verify the access property list value matches
|
||||
* the degree in shared file structure.
|
||||
*/
|
||||
if(H5P_DEFAULT == fapl_id)
|
||||
fapl_id = H5P_FILE_ACCESS_DEFAULT;
|
||||
if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS) ||
|
||||
NULL == (a_plist = H5I_object(fapl_id)))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list");
|
||||
if(H5P_get(a_plist, H5F_CLOSE_DEGREE_NAME, &fc_degree) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree");
|
||||
|
||||
if(shared->nrefs == 1) {
|
||||
if(fc_degree == H5F_CLOSE_DEFAULT)
|
||||
shared->fc_degree = H5F_CLOSE_DEFAULT;
|
||||
else
|
||||
shared->fc_degree = fc_degree;
|
||||
} else if(shared->nrefs > 1) {
|
||||
if(fc_degree != shared->fc_degree)
|
||||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match");
|
||||
}
|
||||
|
||||
/* Success */
|
||||
ret_value = file;
|
||||
|
||||
@ -2158,7 +2485,10 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
|
||||
herr_t
|
||||
H5F_close(H5F_t *f)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned i;
|
||||
unsigned oid_count;
|
||||
hid_t *oid_list;
|
||||
H5F_close_degree_t fc_degree;
|
||||
|
||||
FUNC_ENTER(H5F_close, FAIL);
|
||||
assert(f->nrefs>0);
|
||||
@ -2187,40 +2517,6 @@ H5F_close(H5F_t *f)
|
||||
}
|
||||
f->mtab.nmounts = 0;
|
||||
|
||||
/*
|
||||
* If object headers are still open then delay deletion of resources until
|
||||
* they have all been closed. Flush all caches and update the object
|
||||
* header anyway so that failing to 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.
|
||||
*/
|
||||
if (f->nopen_objs>0) {
|
||||
if (H5F_flush(f, H5F_SCOPE_LOCAL, FALSE, FALSE)<0) {
|
||||
HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush cache");
|
||||
}
|
||||
#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 (!f->closing) {
|
||||
f->closing = H5I_register(H5I_FILE_CLOSING, f);
|
||||
}
|
||||
HRETURN(SUCCEED);
|
||||
} else if (f->closing) {
|
||||
#ifdef H5F_DEBUG
|
||||
if (H5DEBUG(F)) {
|
||||
fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is the last reference to the shared part of the file then
|
||||
* close it also.
|
||||
@ -2233,6 +2529,95 @@ H5F_close(H5F_t *f)
|
||||
"unable to flush cache");
|
||||
}
|
||||
|
||||
/* Get the number of opened object in file */
|
||||
if(H5F_get_obj_count(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE,
|
||||
&oid_count) < 0)
|
||||
HRETURN_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file counts");
|
||||
|
||||
/* Get the close degree from the file */
|
||||
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT)
|
||||
fc_degree = f->shared->lf->cls->fc_degree;
|
||||
else
|
||||
fc_degree = f->shared->fc_degree;
|
||||
|
||||
/* Close file according to close degree.
|
||||
* H5F_CLOSE_WEAK: if there are still objects open, wait until
|
||||
* they are all closed.
|
||||
* H5F_CLOSE_SEMI: if there are still objects open, return fail;
|
||||
* otherwise, close file.
|
||||
* H5F_CLOSE_STRONG: if there are still objects open, close them
|
||||
* first, then close file.
|
||||
*/
|
||||
switch(fc_degree) {
|
||||
case H5F_CLOSE_WEAK:
|
||||
/*
|
||||
* If object headers 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.
|
||||
*/
|
||||
if (f->nopen_objs>0) {
|
||||
if (H5F_flush(f, H5F_SCOPE_LOCAL, FALSE, FALSE)<0)
|
||||
HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush cache");
|
||||
#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 (!f->closing) {
|
||||
f->closing = H5I_register(H5I_FILE_CLOSING, f);
|
||||
}
|
||||
HRETURN(SUCCEED);
|
||||
} else if (f->closing) {
|
||||
#ifdef H5F_DEBUG
|
||||
if (H5DEBUG(F)) {
|
||||
fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
case H5F_CLOSE_SEMI:
|
||||
if(oid_count > 0)
|
||||
HRETURN_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL,
|
||||
"can't close file, there are objects still open");
|
||||
break;
|
||||
case H5F_CLOSE_STRONG:
|
||||
/*forcefully close all opened objects in file*/
|
||||
do {
|
||||
oid_list = (hid_t*)H5MM_malloc(oid_count*sizeof(hid_t));
|
||||
if(H5F_get_obj_ids(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, oid_list) < 0)
|
||||
HRETURN_ERROR(H5E_FILE, H5E_CANTGET, FAIL,
|
||||
"can't get object list in file");
|
||||
|
||||
/* Try to close all the open objects */
|
||||
for(i=0; i<oid_count; i++)
|
||||
if(H5I_dec_ref(oid_list[i]) < 0)
|
||||
HRETURN_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL,
|
||||
"can't close object");
|
||||
|
||||
if(oid_list != NULL)
|
||||
H5MM_xfree(oid_list);
|
||||
if(H5F_get_obj_count(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, &oid_count) < 0)
|
||||
HRETURN_ERROR(H5E_FILE, H5E_CANTGET, FAIL,
|
||||
"can't get file counts");
|
||||
} while(oid_count > 0);
|
||||
break;
|
||||
default:
|
||||
HRETURN_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL,
|
||||
"can't close file, unknown file close degree");
|
||||
}
|
||||
|
||||
/* Dump debugging info */
|
||||
H5AC_debug(f);
|
||||
H5F_istore_stats(f, FALSE);
|
||||
@ -2284,19 +2669,15 @@ H5F_close(H5F_t *f)
|
||||
herr_t
|
||||
H5Fclose(hid_t file_id)
|
||||
{
|
||||
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
|
||||
FUNC_ENTER(H5Fclose, FAIL);
|
||||
H5TRACE1("e","i",file_id);
|
||||
|
||||
/* Check/fix arguments. */
|
||||
if (H5I_FILE != H5I_get_type(file_id)) {
|
||||
if (H5I_FILE != H5I_get_type(file_id) || NULL==H5I_object(file_id)) {
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom");
|
||||
}
|
||||
if (NULL == H5I_object(file_id)) {
|
||||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to unatomize file");
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement reference count on atom. When it reaches zero the file will
|
||||
|
@ -92,6 +92,7 @@ static herr_t H5FD_core_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, had
|
||||
static const H5FD_class_t H5FD_core_g = {
|
||||
"core", /*name */
|
||||
MAXADDR, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /*fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -140,6 +140,7 @@ static herr_t H5FD_dpss_write (H5FD_t *_file, H5FD_mem_t type, hid_t UNUSED fapl
|
||||
static const H5FD_class_t H5FD_dpss_g = {
|
||||
"dpss", /* name */
|
||||
MAXADDR, /* maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /* sb_size */
|
||||
NULL, /* sb_encode */
|
||||
NULL, /* sb_decode */
|
||||
|
@ -87,6 +87,7 @@ static herr_t H5FD_family_flush(H5FD_t *_file);
|
||||
static const H5FD_class_t H5FD_family_g = {
|
||||
"family", /*name */
|
||||
HADDR_MAX, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -133,6 +133,7 @@ typedef struct H5FD_gass_fapl_t {
|
||||
static const H5FD_class_t H5FD_gass_g = {
|
||||
"gass", /*name */
|
||||
MAXADDR, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -193,6 +193,7 @@ static herr_t H5FD_log_flush(H5FD_t *_file);
|
||||
static const H5FD_class_t H5FD_log_g = {
|
||||
"log", /*name */
|
||||
MAXADDR, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -93,6 +93,7 @@ typedef struct H5FD_mpio_fapl_t {
|
||||
static const H5FD_class_t H5FD_mpio_g = {
|
||||
"mpio", /*name */
|
||||
HADDR_MAX, /*maxaddr */
|
||||
H5F_CLOSE_SEMI, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -133,6 +133,7 @@ static herr_t H5FD_multi_flush(H5FD_t *_file);
|
||||
static const H5FD_class_t H5FD_multi_g = {
|
||||
"multi", /*name */
|
||||
HADDR_MAX, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
H5FD_multi_sb_size, /*sb_size */
|
||||
H5FD_multi_sb_encode, /*sb_encode */
|
||||
H5FD_multi_sb_decode, /*sb_decode */
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define _H5FDpublic_H
|
||||
|
||||
#include "H5public.h"
|
||||
#include "H5Fpublic.h" /*for H5F_close_degree_t */
|
||||
|
||||
#define H5_HAVE_VFL 1 /*define a convenient app feature test*/
|
||||
#define H5FD_VFD_DEFAULT 0 /* Default VFL driver value */
|
||||
@ -108,6 +109,7 @@ typedef struct H5FD_t H5FD_t;
|
||||
typedef struct H5FD_class_t {
|
||||
const char *name;
|
||||
haddr_t maxaddr;
|
||||
H5F_close_degree_t fc_degree;
|
||||
hsize_t (*sb_size)(H5FD_t *file);
|
||||
herr_t (*sb_encode)(H5FD_t *file, char *name/*out*/,
|
||||
unsigned char *p/*out*/);
|
||||
@ -149,28 +151,28 @@ typedef struct H5FD_free_t {
|
||||
* declared here and the driver appends private fields in memory.
|
||||
*/
|
||||
struct H5FD_t {
|
||||
hid_t driver_id; /*driver ID for this file */
|
||||
const H5FD_class_t *cls; /*constant class info */
|
||||
hid_t driver_id; /*driver ID for this file*/
|
||||
const H5FD_class_t *cls; /*constant class info */
|
||||
|
||||
unsigned long feature_flags; /* VFL Driver feature Flags */
|
||||
hsize_t threshold; /* Threshold for alignment */
|
||||
hsize_t alignment; /* Allocation alignment */
|
||||
unsigned long feature_flags; /* VFL Driver feature Flags */
|
||||
hsize_t threshold; /* Threshold for alignment */
|
||||
hsize_t alignment; /* Allocation alignment */
|
||||
|
||||
/* Metadata aggregation fields */
|
||||
hsize_t def_meta_block_size; /* Metadata allocation block size (if aggregating metadata) */
|
||||
hsize_t cur_meta_block_size; /* Current size of metadata allocation region left */
|
||||
haddr_t eoma; /* End of metadata allocated region */
|
||||
hsize_t def_meta_block_size; /* Metadata allocation block size (if aggregating metadata) */
|
||||
hsize_t cur_meta_block_size; /* Current size of metadata allocation region left */
|
||||
haddr_t eoma; /*End of metadata allocated region*/
|
||||
|
||||
/* Metadata accumulator fields */
|
||||
unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */
|
||||
haddr_t accum_loc; /* File location (offset) of the accumulated metadata */
|
||||
size_t accum_size; /* Size of the accumulated metadata buffer used (in bytes) */
|
||||
size_t accum_buf_size; /* Size of the accumulated metadata buffer allocated (in bytes) */
|
||||
unsigned accum_dirty; /* Flag to indicate that the accumulated metadata is dirty */
|
||||
unsigned char *meta_accum; /*Buffer to hold the accumulated metadata */
|
||||
haddr_t accum_loc; /* File location (offset) of the accumulated metadata */
|
||||
size_t accum_size; /* Size of the accumulated metadata buffer used (in bytes) */
|
||||
size_t accum_buf_size; /* Size of the accumulated metadata buffer allocated (in bytes) */
|
||||
unsigned accum_dirty; /* Flag to indicate that the accumulated metadata is dirty */
|
||||
|
||||
haddr_t maxaddr; /*for this file, overrides class*/
|
||||
H5FD_free_t *fl[H5FD_MEM_NTYPES];/*freelist per allocation type*/
|
||||
hsize_t maxsize; /*largest object on FL, or zero */
|
||||
haddr_t maxaddr;/*for this file, overrides class*/
|
||||
H5FD_free_t *fl[H5FD_MEM_NTYPES];/*freelist per allocation type*/
|
||||
hsize_t maxsize;/*largest object on FL, or zero */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -149,6 +149,7 @@ static herr_t H5FD_sec2_flush(H5FD_t *_file);
|
||||
static const H5FD_class_t H5FD_sec2_g = {
|
||||
"sec2", /*name */
|
||||
MAXADDR, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -144,6 +144,7 @@ static herr_t H5FD_stdio_flush(H5FD_t *_file);
|
||||
static const H5FD_class_t H5FD_stdio_g = {
|
||||
"stdio", /*name */
|
||||
MAXADDR, /*maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /*sb_size */
|
||||
NULL, /*sb_encode */
|
||||
NULL, /*sb_decode */
|
||||
|
@ -171,6 +171,7 @@ static const H5FD_class_t H5FD_stream_g =
|
||||
{
|
||||
"stream", /* name */
|
||||
MAXADDR, /* maxaddr */
|
||||
H5F_CLOSE_WEAK, /* fc_degree */
|
||||
NULL, /* sb_size */
|
||||
NULL, /* sb_encode */
|
||||
NULL, /* sb_decode */
|
||||
|
@ -119,6 +119,7 @@ typedef struct H5F_file_t {
|
||||
unsigned sieve_dirty; /* Flag to indicate that the data sieve buffer is dirty */
|
||||
|
||||
H5F_rdcc_t rdcc; /* Raw data chunk cache */
|
||||
H5F_close_degree_t fc_degree; /* File close behavior degree */
|
||||
} H5F_file_t;
|
||||
|
||||
/* A record of the mount table */
|
||||
|
@ -306,6 +306,11 @@ __DLL__ size_t H5F_sizeof_size(const H5F_t *f);
|
||||
#define H5F_ACS_FILE_DRV_INFO_SIZE sizeof(void*)
|
||||
#define H5F_ACS_FILE_DRV_INFO_DEF NULL
|
||||
|
||||
/* Definition for file close degree */
|
||||
#define H5F_CLOSE_DEGREE_NAME "close_degree"
|
||||
#define H5F_CLOSE_DEGREE_SIZE sizeof(H5F_close_degree_t)
|
||||
#define H5F_CLOSE_DEGREE_DEF H5F_CLOSE_DEFAULT
|
||||
|
||||
/* ======================== File Mount properties ====================*/
|
||||
/* Definition for whether absolute symlinks local to file. */
|
||||
#define H5F_MNT_SYM_LOCAL_NAME "local"
|
||||
|
@ -36,6 +36,11 @@
|
||||
#define H5F_ACC_DEBUG (H5check(),0x0008u) /*print debug info */
|
||||
#define H5F_ACC_CREAT (H5check(),0x0010u) /*create non-existing files */
|
||||
|
||||
#define H5F_OBJ_FILE (0x0001u)
|
||||
#define H5F_OBJ_DATASET (0x0002u)
|
||||
#define H5F_OBJ_GROUP (0x0004u)
|
||||
#define H5F_OBJ_DATATYPE (0x0008u)
|
||||
#define H5F_OBJ_ALL (H5F_OBJ_FILE|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE)
|
||||
|
||||
#ifdef H5_HAVE_PARALLEL
|
||||
/*
|
||||
@ -64,21 +69,39 @@ typedef enum H5T_bkg_t {
|
||||
H5T_BKG_YES = 2 /*init bkg buf with data before conversion */
|
||||
} H5T_bkg_t;
|
||||
|
||||
/* How does file close behave?
|
||||
* H5F_CLOSE_DEFAULT - Use the degree pre-defined by underlining VFL
|
||||
* H5F_CLOSE_WEAK - file closes only after all opened objects are closed
|
||||
* H5F_CLOSE_SEMI - if no opened objects, file is close; otherwise, file
|
||||
close fails
|
||||
* H5F_CLOSE_STRONG - if there are opened objects, close them first, then
|
||||
close file
|
||||
*/
|
||||
typedef enum H5F_close_degree_t {
|
||||
H5F_CLOSE_DEFAULT = 0,
|
||||
H5F_CLOSE_WEAK = 1,
|
||||
H5F_CLOSE_SEMI = 2,
|
||||
H5F_CLOSE_STRONG = 3
|
||||
} H5F_close_degree_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Functions in H5F.c */
|
||||
__DLL__ htri_t H5Fis_hdf5 (const char *filename);
|
||||
__DLL__ hid_t H5Fcreate (const char *filename, unsigned flags,
|
||||
hid_t create_plist, hid_t access_plist);
|
||||
__DLL__ hid_t H5Fopen (const char *filename, unsigned flags,
|
||||
hid_t access_plist);
|
||||
__DLL__ hid_t H5Freopen(hid_t file_id);
|
||||
__DLL__ hid_t H5Fcreate (const char *filename, unsigned flags,
|
||||
hid_t create_plist, hid_t access_plist);
|
||||
__DLL__ hid_t H5Fopen (const char *filename, unsigned flags,
|
||||
hid_t access_plist);
|
||||
__DLL__ hid_t H5Freopen(hid_t file_id);
|
||||
__DLL__ herr_t H5Fflush(hid_t object_id, H5F_scope_t scope);
|
||||
__DLL__ herr_t H5Fclose (hid_t file_id);
|
||||
__DLL__ hid_t H5Fget_create_plist (hid_t file_id);
|
||||
__DLL__ hid_t H5Fget_access_plist (hid_t file_id);
|
||||
__DLL__ hid_t H5Fget_create_plist (hid_t file_id);
|
||||
__DLL__ hid_t H5Fget_access_plist (hid_t file_id);
|
||||
__DLL__ herr_t H5Fget_obj_count(hid_t file_id, unsigned types,
|
||||
unsigned *obj_id_count);
|
||||
__DLL__ herr_t H5Fget_obj_ids(hid_t file_id, unsigned types, hid_t *obj_id_list);
|
||||
__DLL__ herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist);
|
||||
__DLL__ herr_t H5Funmount(hid_t loc, const char *name);
|
||||
|
||||
|
@ -93,6 +93,7 @@ typedef struct H5G_entry_t {
|
||||
H5G_cache_t cache; /*cached data from object header */
|
||||
H5F_t *file; /*file to which this obj hdr belongs */
|
||||
} H5G_entry_t;
|
||||
|
||||
typedef struct H5G_t H5G_t;
|
||||
|
||||
/*
|
||||
|
@ -888,6 +888,11 @@ H5I_remove(hid_t id)
|
||||
* removed from the group and its reference count is not decremented.
|
||||
* The group number is now passed to the free method.
|
||||
*
|
||||
* Raymond, 11 Dec 2001
|
||||
* If the freeing function fails, return failure instead of reference
|
||||
* count 1. This feature is needed by file close with H5F_CLOSE_SEMI
|
||||
* value.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
@ -924,7 +929,7 @@ H5I_dec_ref(hid_t id)
|
||||
H5I_remove(id);
|
||||
ret_value = 0;
|
||||
} else {
|
||||
ret_value = 1;
|
||||
ret_value = FAIL;
|
||||
}
|
||||
} else {
|
||||
ret_value = --(id_ptr->count);
|
||||
@ -1020,7 +1025,7 @@ H5I_search(H5I_type_t grp, H5I_search_func_t func, const void *key)
|
||||
for (i=0; i<grp_ptr->hash_size; i++) {
|
||||
id_ptr = grp_ptr->id_list[i];
|
||||
while (id_ptr) {
|
||||
if ((*func)(id_ptr->obj_ptr, key)) {
|
||||
if ((*func)(id_ptr->obj_ptr, id_ptr->id, key)) {
|
||||
HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
|
||||
}
|
||||
id_ptr = id_ptr->next;
|
||||
|
@ -50,7 +50,7 @@
|
||||
typedef herr_t (*H5I_free_t)(void*);
|
||||
|
||||
/* Type of the function to compare objects & keys */
|
||||
typedef int (*H5I_search_func_t)(void *obj, const void *key);
|
||||
typedef int (*H5I_search_func_t)(void *obj, hid_t id, const void *key);
|
||||
|
||||
/* Atom information structure used */
|
||||
typedef struct H5I_id_info_t {
|
||||
|
78
src/H5P.c
78
src/H5P.c
@ -3471,13 +3471,91 @@ H5Pget_gc_references(hid_t plist_id, unsigned *gc_ref/*out*/)
|
||||
|
||||
/* Get values */
|
||||
if (gc_ref)
|
||||
|
||||
if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME, gc_ref) < 0)
|
||||
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get garbage collect reference");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Pset_fclose_degree
|
||||
*
|
||||
* Purpose: Sets the degree for the file close behavior.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* November, 2001
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5Pset_fclose_degree(hid_t plist_id, H5F_close_degree_t degree)
|
||||
{
|
||||
H5P_genplist_t *plist; /* Property list pointer */
|
||||
herr_t ret_value=SUCCEED; /* return value */
|
||||
|
||||
FUNC_ENTER(H5Pset_fclose_degree, FAIL);
|
||||
|
||||
/* Check args */
|
||||
if(TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
|
||||
|
||||
/* Get the plist structure */
|
||||
if(NULL == (plist = H5I_object(plist_id)))
|
||||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
|
||||
|
||||
/* Set values */
|
||||
if(H5P_set(plist, H5F_CLOSE_DEGREE_NAME, °ree) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Pget_fclose_degree
|
||||
*
|
||||
* Purpose: Returns the current setting for the garbage collection
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* June, 1999
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t H5Pget_fclose_degree(hid_t plist_id, H5F_close_degree_t *degree)
|
||||
{
|
||||
H5P_genplist_t *plist; /* Property list pointer */
|
||||
herr_t ret_value=SUCCEED; /* return value */
|
||||
|
||||
FUNC_ENTER(H5Pget_fclose_degree, FAIL);
|
||||
|
||||
/* Check args */
|
||||
if(TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
|
||||
|
||||
/* Get the plist structure */
|
||||
if(NULL == (plist = H5I_object(plist_id)))
|
||||
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
|
||||
|
||||
if( degree && (H5P_get(plist, H5F_CLOSE_DEGREE_NAME, degree) < 0) )
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file close degree");
|
||||
|
||||
done:
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5P_set_vlen_mem_manager
|
||||
|
@ -232,6 +232,8 @@ __DLL__ herr_t H5Pget_fill_value(hid_t plist_id, hid_t type_id,
|
||||
void *value/*out*/);
|
||||
__DLL__ herr_t H5Pset_gc_references(hid_t fapl_id, unsigned gc_ref);
|
||||
__DLL__ herr_t H5Pget_gc_references(hid_t fapl_id, unsigned *gc_ref/*out*/);
|
||||
__DLL__ herr_t H5Pset_fclose_degree(hid_t fapl_id, H5F_close_degree_t degree);
|
||||
__DLL__ herr_t H5Pget_fclose_degree(hid_t fapl_id, H5F_close_degree_t *degree);
|
||||
__DLL__ herr_t H5Pset_vlen_mem_manager(hid_t plist_id,
|
||||
H5MM_allocate_t alloc_func,
|
||||
void *alloc_info, H5MM_free_t free_func,
|
||||
|
33
src/H5T.c
33
src/H5T.c
@ -1924,7 +1924,7 @@ done:
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
H5T_unlock_cb (void *_dt, const void * UNUSED key)
|
||||
H5T_unlock_cb (void *_dt, hid_t id, const void * UNUSED key)
|
||||
{
|
||||
H5T_t *dt = (H5T_t *)_dt;
|
||||
|
||||
@ -7639,6 +7639,37 @@ H5T_entof (H5T_t *dt)
|
||||
FUNC_LEAVE (ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5T_is_immutable
|
||||
*
|
||||
* Purpose: Check is a datatype is immutable.
|
||||
*
|
||||
* Return: TRUE
|
||||
*
|
||||
* FALSE
|
||||
*
|
||||
* Programmer: Raymond Lu
|
||||
* Friday, Dec 7, 2001
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
htri_t
|
||||
H5T_is_immutable(H5T_t *dt)
|
||||
{
|
||||
htri_t ret_value = FALSE;
|
||||
|
||||
FUNC_ENTER(H5T_is_immutable, FAIL);
|
||||
assert(dt);
|
||||
|
||||
if(dt->state == H5T_STATE_IMMUTABLE)
|
||||
ret_value = TRUE;
|
||||
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
|
@ -131,7 +131,7 @@ struct H5T_t {
|
||||
H5F_t *sh_file;/*file pointer if this is a shared type */
|
||||
H5T_class_t type; /*which class of type is this? */
|
||||
size_t size; /*total size of an instance of this type */
|
||||
hbool_t force_conv; /* Set if this type always needs to be converted and H5T_conv_noop cannot be called */
|
||||
hbool_t force_conv; /* Set if this type always needs to be converted and H5T_conv_noop cannot be called */
|
||||
struct H5T_t *parent;/*parent type for derived data types */
|
||||
union {
|
||||
H5T_atomic_t atomic; /* an atomic data type */
|
||||
|
@ -116,6 +116,7 @@ __DLL__ herr_t H5T_enum_insert(H5T_t *dt, const char *name, void *value);
|
||||
__DLL__ herr_t H5T_pack(H5T_t *dt);
|
||||
__DLL__ herr_t H5T_debug(const H5T_t *dt, FILE * stream);
|
||||
__DLL__ H5G_entry_t *H5T_entof(H5T_t *dt);
|
||||
__DLL__ htri_t H5T_is_immutable(H5T_t *dt);
|
||||
__DLL__ H5T_path_t *H5T_path_find(const H5T_t *src, const H5T_t *dst,
|
||||
const char *name, H5T_conv_t func);
|
||||
__DLL__ herr_t H5T_sort_value(H5T_t *dt, int *map);
|
||||
|
@ -754,6 +754,7 @@ test_types(hid_t file)
|
||||
for (i=0; i<sizeof buf; i++) buf[i] = (unsigned char)0xff ^ (unsigned char)i;
|
||||
if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf)<0)
|
||||
goto error;
|
||||
|
||||
if (H5Sclose(space)<0) goto error;
|
||||
if (H5Tclose(type)<0) goto error;
|
||||
if (H5Dclose(dset)<0) goto error;
|
||||
|
494
test/tfile.c
494
test/tfile.c
@ -50,6 +50,19 @@
|
||||
#define F3_SYM_INTERN_K F2_SYM_INTERN_K
|
||||
#define FILE3 "tfile3.h5"
|
||||
|
||||
#define OBJ_ID_COUNT_0 0
|
||||
#define OBJ_ID_COUNT_1 1
|
||||
#define OBJ_ID_COUNT_2 2
|
||||
#define OBJ_ID_COUNT_3 3
|
||||
#define OBJ_ID_COUNT_4 4
|
||||
#define OBJ_ID_COUNT_6 6
|
||||
#define OBJ_ID_COUNT_8 8
|
||||
|
||||
static void
|
||||
create_objects(hid_t, hid_t, hid_t *, hid_t *, hid_t *, hid_t *);
|
||||
static void
|
||||
test_obj_count_and_id(hid_t, hid_t, hid_t, hid_t, hid_t, hid_t);
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_file_create(): Low-level file creation I/O test routine.
|
||||
@ -343,6 +356,483 @@ test_file_open(void)
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
} /* test_file_open() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_file_close(): low-level file close test routine.
|
||||
** It mainly tests behavior with close degree.
|
||||
**
|
||||
*****************************************************************/
|
||||
static void
|
||||
test_file_close()
|
||||
{
|
||||
hid_t fid1, fid2;
|
||||
hid_t fapl_id, access_id;
|
||||
hid_t dataset_id, group_id1, group_id2, group_id3;
|
||||
H5F_close_degree_t fc_degree;
|
||||
unsigned fid_count, oid_count;
|
||||
herr_t ret;
|
||||
|
||||
/* Test behavior while opening file multiple times with different
|
||||
* file close degree value
|
||||
*/
|
||||
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
CHECK(fid1, FAIL, "H5Fcreate");
|
||||
|
||||
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
||||
CHECK(fapl_id, FAIL, "H5Pcreate");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
ret = H5Pget_fclose_degree(fapl_id, &fc_degree);
|
||||
VERIFY(fc_degree, H5F_CLOSE_STRONG, "H5Pget_fclose_degree");
|
||||
|
||||
/* should fail */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
VERIFY(fid2, FAIL, "H5Fopen");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_DEFAULT);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should succeed */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
CHECK(fid2, FAIL, "H5Fopen");
|
||||
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
/* Close second open */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
|
||||
/* Test behavior while opening file multiple times with file close
|
||||
* degree STRONG */
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
|
||||
CHECK(fid1, FAIL, "H5Fcreate");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should fail */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
VERIFY(fid2, FAIL, "H5Fopen");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should succeed */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
CHECK(fid2, FAIL, "H5Fopen");
|
||||
|
||||
/* Create a dataset and a group in each file open respectively */
|
||||
create_objects(fid1, fid2, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
/* Close second open */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
|
||||
/* Test behavior while opening file multiple times with file close
|
||||
* degree SEMI */
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
|
||||
CHECK(fid1, FAIL, "H5Fcreate");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_DEFAULT);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should fail */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
VERIFY(fid2, FAIL, "H5Fopen");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should succeed */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
CHECK(fid2, FAIL, "H5Fopen");
|
||||
|
||||
/* Create a dataset and a group in each file open respectively */
|
||||
create_objects(fid1, fid2, &dataset_id, &group_id1, &group_id2, &group_id3);
|
||||
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
/* Close second open, should fail since it is SEMI and objects are
|
||||
* still open. */
|
||||
ret = H5Fclose(fid2);
|
||||
VERIFY(ret, FAIL, "H5Fclose");
|
||||
|
||||
ret = H5Dclose(dataset_id);
|
||||
CHECK(ret, FAIL, "H5Dclose");
|
||||
|
||||
ret = H5Gclose(group_id1);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
ret = H5Gclose(group_id2);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
/* Close second open, should fail since it is SEMI and one group ID is
|
||||
* still open. */
|
||||
ret = H5Fclose(fid2);
|
||||
VERIFY(ret, FAIL, "H5Fclose");
|
||||
|
||||
ret = H5Gclose(group_id3);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
/* Close second open again. Should succeed. */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
|
||||
/* Test behavior while opening file multiple times with file close
|
||||
* degree WEAK */
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
|
||||
CHECK(fid1, FAIL, "H5Fcreate");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should fail */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
VERIFY(fid2, FAIL, "H5Fopen");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should succeed */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
CHECK(fid2, FAIL, "H5Fopen");
|
||||
|
||||
/* Create a dataset and a group in each file open respectively */
|
||||
create_objects(fid1, fid2, &dataset_id, &group_id1, &group_id2, &group_id3);
|
||||
|
||||
/* Create more new files and test object count and ID list functions */
|
||||
test_obj_count_and_id(fid1, fid2, dataset_id, group_id1,
|
||||
group_id2, group_id3);
|
||||
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
/* Close second open. File will be finally closed after all objects
|
||||
* are closed. */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
|
||||
ret = H5Dclose(dataset_id);
|
||||
CHECK(ret, FAIL, "H5Dclose");
|
||||
|
||||
ret = H5Gclose(group_id1);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
ret = H5Gclose(group_id2);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
ret = H5Gclose(group_id3);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
|
||||
|
||||
/* Test behavior while opening file multiple times with file close
|
||||
* degree DEFAULT */
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_DEFAULT);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
|
||||
CHECK(fid1, FAIL, "H5Fcreate");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should fail */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
VERIFY(fid2, FAIL, "H5Fopen");
|
||||
|
||||
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_DEFAULT);
|
||||
CHECK(ret, FAIL, "H5Pset_fclose_degree");
|
||||
|
||||
/* should succeed */
|
||||
fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, fapl_id);
|
||||
CHECK(fid2, FAIL, "H5Fopen");
|
||||
|
||||
/* Create a dataset and a group in each file open respectively */
|
||||
create_objects(fid1, fid2, &dataset_id, &group_id1, &group_id2, &group_id3);
|
||||
|
||||
access_id = H5Fget_access_plist(fid1);
|
||||
CHECK(access_id, FAIL, "H5Fget_access_plist");
|
||||
|
||||
ret= H5Pget_fclose_degree(access_id, &fc_degree);
|
||||
CHECK(ret, FAIL, "H5Pget_fclose_degree");
|
||||
|
||||
switch(fc_degree) {
|
||||
case H5F_CLOSE_STRONG:
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
/* Close second open */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
break;
|
||||
case H5F_CLOSE_SEMI:
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
ret = H5Dclose(dataset_id);
|
||||
CHECK(ret, FAIL, "H5Dclose");
|
||||
ret = H5Gclose(group_id1);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
ret = H5Gclose(group_id2);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
ret = H5Gclose(group_id3);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
/* Close second open */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
break;
|
||||
case H5F_CLOSE_WEAK:
|
||||
/* Close first open */
|
||||
ret = H5Fclose(fid1);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
/* Close second open */
|
||||
ret = H5Fclose(fid2);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
ret = H5Dclose(dataset_id);
|
||||
CHECK(ret, FAIL, "H5Dclose");
|
||||
ret = H5Gclose(group_id1);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
ret = H5Gclose(group_id2);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
ret = H5Gclose(group_id3);
|
||||
CHECK(ret, FAIL, "H5Gclose");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Close file access property list */
|
||||
ret = H5Pclose(fapl_id);
|
||||
CHECK(ret, FAIL, "H5Pclose");
|
||||
ret = H5Pclose(access_id);
|
||||
CHECK(ret, FAIL, "H5Pclose");
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** create_objects(): routine called by test_file_close to create
|
||||
** a dataset and a group in file.
|
||||
**
|
||||
****************************************************************/
|
||||
static void
|
||||
create_objects(hid_t fid1, hid_t fid2, hid_t *ret_did, hid_t *ret_gid1,
|
||||
hid_t *ret_gid2, hid_t *ret_gid3)
|
||||
{
|
||||
unsigned oid_count;
|
||||
herr_t ret;
|
||||
|
||||
/* Check reference counts of file IDs and opened object IDs.
|
||||
* The verification is hard-coded. If in any case, this testing
|
||||
* is changed, remember to check this part and update the macros.
|
||||
*/
|
||||
{
|
||||
ret = H5Fget_obj_count(fid1, H5F_OBJ_ALL, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_2, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid1, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_0, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid2, H5F_OBJ_ALL, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_2, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid2, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_0, "H5Fget_obj_count");
|
||||
}
|
||||
|
||||
/* create a dataset in the first file open */
|
||||
{
|
||||
hid_t dataset_id, dataspace_id; /* identifiers */
|
||||
hsize_t dims[F2_RANK];
|
||||
int data[F2_DIM0][F2_DIM1];
|
||||
unsigned i,j;
|
||||
|
||||
/* Create the data space for the dataset. */
|
||||
dims[0] = F2_DIM0;
|
||||
dims[1] = F2_DIM1;
|
||||
dataspace_id = H5Screate_simple(F2_RANK, dims, NULL);
|
||||
CHECK(dataspace_id, FAIL, "H5Screate_simple");
|
||||
|
||||
/* Create the dataset. */
|
||||
dataset_id = H5Dcreate(fid1, "/dset", H5T_NATIVE_INT, dataspace_id,
|
||||
H5P_DEFAULT);
|
||||
CHECK(dataset_id, FAIL, "H5Dcreate");
|
||||
|
||||
for(i=0; i<F2_DIM0; i++)
|
||||
for(j=0; j<F2_DIM1; j++)
|
||||
data[i][j]=i*10+j;
|
||||
|
||||
/* Write data to the new dataset */
|
||||
ret = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
|
||||
H5P_DEFAULT, data);
|
||||
CHECK(ret, FAIL, "H5Dwrite");
|
||||
|
||||
if(ret_did != NULL)
|
||||
*ret_did = dataset_id;
|
||||
|
||||
/* Terminate access to the data space. */
|
||||
ret = H5Sclose(dataspace_id);
|
||||
CHECK(ret, FAIL, "H5Sclose");
|
||||
}
|
||||
|
||||
/* Create a group in the second file open */
|
||||
{
|
||||
hid_t gid1, gid2, gid3;
|
||||
gid1 = H5Gcreate(fid2, "/group", 0);
|
||||
if(ret_gid1 != NULL)
|
||||
*ret_gid1 = gid1;
|
||||
|
||||
gid2 = H5Gopen(fid2, "/group");
|
||||
if(ret_gid2 != NULL)
|
||||
*ret_gid2 = gid2;
|
||||
|
||||
gid3 = H5Gopen(fid2, "/group");
|
||||
if(ret_gid3 != NULL)
|
||||
*ret_gid3 = gid3;
|
||||
}
|
||||
|
||||
/* Check reference counts of file IDs and opened object IDs.
|
||||
* The verification is hard-coded. If in any case, this testing
|
||||
* is changed, remember to check this part and update the macros.
|
||||
*/
|
||||
{
|
||||
ret = H5Fget_obj_count(fid1, H5F_OBJ_ALL, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_6, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid1, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid2, H5F_OBJ_ALL, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_6, "H5Fget_obj_count");
|
||||
|
||||
ret = H5Fget_obj_count(fid2, H5F_OBJ_DATASET|H5F_OBJ_GROUP|
|
||||
H5F_OBJ_DATATYPE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_obj_count_and_id(): test object count and ID list functions.
|
||||
**
|
||||
****************************************************************/
|
||||
static void
|
||||
test_obj_count_and_id(hid_t fid1, hid_t fid2, hid_t did, hid_t gid1,
|
||||
hid_t gid2, hid_t gid3)
|
||||
{
|
||||
hid_t fid3, fid4;
|
||||
unsigned oid_count;
|
||||
herr_t ret;
|
||||
|
||||
/* Create two new files */
|
||||
fid3 = H5Fcreate(FILE2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
CHECK(fid3, FAIL, "H5Fcreate");
|
||||
fid4 = H5Fcreate(FILE3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
CHECK(fid4, FAIL, "H5Fcreate");
|
||||
|
||||
/* test object count of all files IDs open */
|
||||
ret = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_FILE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count");
|
||||
|
||||
/* test object count of all dataset open */
|
||||
ret = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_DATASET, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_1, "H5Fget_obj_count");
|
||||
|
||||
/* test object count of all group open */
|
||||
ret = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_GROUP, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_3, "H5Fget_obj_count");
|
||||
|
||||
/* test object count of all datatype open */
|
||||
ret = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_DATATYPE, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_0, "H5Fget_obj_count");
|
||||
|
||||
/* test object count of all objects currently open */
|
||||
ret = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL, &oid_count);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_count");
|
||||
VERIFY(oid_count, OBJ_ID_COUNT_8, "H5Fget_obj_count");
|
||||
|
||||
{
|
||||
hid_t *oid_list;
|
||||
unsigned i;
|
||||
H5I_type_t id_type;
|
||||
|
||||
oid_list = (hid_t*)calloc(oid_count, sizeof(hid_t));
|
||||
if(oid_list != NULL) {
|
||||
ret = H5Fget_obj_ids(H5F_OBJ_ALL, H5F_OBJ_ALL, oid_list);
|
||||
CHECK(ret, FAIL, "H5Fget_obj_ids");
|
||||
}
|
||||
|
||||
for(i=0; i<oid_count; i++) {
|
||||
id_type = H5Iget_type(oid_list[i]);
|
||||
switch(id_type) {
|
||||
case H5I_FILE:
|
||||
if(oid_list[i]!=fid1 && oid_list[i]!=fid2 &&
|
||||
oid_list[i]!=fid3 && oid_list[i]!=fid4) {
|
||||
ret = FAIL;
|
||||
CHECK(ret, FAIL, "H5Fget_obj_ids");
|
||||
}
|
||||
break;
|
||||
case H5I_GROUP:
|
||||
if(oid_list[i]!=gid1 && oid_list[i]!=gid2 &&
|
||||
oid_list[i]!=gid3) {
|
||||
ret = FAIL;
|
||||
CHECK(ret, FAIL, "H5Fget_obj_ids");
|
||||
}
|
||||
break;
|
||||
case H5I_DATASET:
|
||||
VERIFY(oid_list[i], did, "H5Fget_obj_ids");
|
||||
break;
|
||||
default:
|
||||
ret = FAIL;
|
||||
CHECK(ret, FAIL, "H5Fget_obj_ids");
|
||||
}
|
||||
}
|
||||
|
||||
free(oid_list);
|
||||
}
|
||||
|
||||
/* close the two new files */
|
||||
ret = H5Fclose(fid3);
|
||||
CHECK(fid3, FAIL, "H5Fclose");
|
||||
ret = H5Fclose(fid4);
|
||||
CHECK(fid4, FAIL, "H5Fclose");
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_file(): Main low-level file I/O test routine.
|
||||
@ -354,8 +844,9 @@ test_file(void)
|
||||
/* Output message about test being performed */
|
||||
MESSAGE(5, ("Testing Low-Level File I/O\n"));
|
||||
|
||||
test_file_create(); /* Test file creation (also creation templates) */
|
||||
test_file_create(); /* Test file creation(also creation templates)*/
|
||||
test_file_open(); /* Test file opening */
|
||||
test_file_close(); /* Test file close behavior */
|
||||
} /* test_file() */
|
||||
|
||||
|
||||
@ -380,4 +871,3 @@ cleanup_file(void)
|
||||
remove(FILE2);
|
||||
remove(FILE3);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user