diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2001-12-11 19:53:44 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2001-12-11 19:53:44 (GMT) |
commit | d28fd08f4a9593bd8bb51ebc17b8b6555b3885cd (patch) | |
tree | 61e5d32198fc92bdfb2b98115269991f3fadd53b | |
parent | 33ed41455eff31751d3d9d635140996ebbc61a4e (diff) | |
download | hdf5-d28fd08f4a9593bd8bb51ebc17b8b6555b3885cd.zip hdf5-d28fd08f4a9593bd8bb51ebc17b8b6555b3885cd.tar.gz hdf5-d28fd08f4a9593bd8bb51ebc17b8b6555b3885cd.tar.bz2 |
[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
-rw-r--r-- | src/H5D.c | 1 | ||||
-rw-r--r-- | src/H5F.c | 505 | ||||
-rw-r--r-- | src/H5FDcore.c | 1 | ||||
-rw-r--r-- | src/H5FDdpss.c | 1 | ||||
-rw-r--r-- | src/H5FDfamily.c | 1 | ||||
-rw-r--r-- | src/H5FDgass.c | 1 | ||||
-rw-r--r-- | src/H5FDlog.c | 1 | ||||
-rw-r--r-- | src/H5FDmpio.c | 1 | ||||
-rw-r--r-- | src/H5FDmulti.c | 1 | ||||
-rw-r--r-- | src/H5FDpublic.h | 36 | ||||
-rw-r--r-- | src/H5FDsec2.c | 1 | ||||
-rw-r--r-- | src/H5FDstdio.c | 1 | ||||
-rw-r--r-- | src/H5FDstream.c | 1 | ||||
-rw-r--r-- | src/H5Fpkg.h | 1 | ||||
-rw-r--r-- | src/H5Fprivate.h | 5 | ||||
-rw-r--r-- | src/H5Fpublic.h | 37 | ||||
-rw-r--r-- | src/H5Gprivate.h | 1 | ||||
-rw-r--r-- | src/H5I.c | 9 | ||||
-rw-r--r-- | src/H5Iprivate.h | 2 | ||||
-rw-r--r-- | src/H5P.c | 78 | ||||
-rw-r--r-- | src/H5Ppublic.h | 2 | ||||
-rw-r--r-- | src/H5T.c | 33 | ||||
-rw-r--r-- | src/H5Tpkg.h | 2 | ||||
-rw-r--r-- | src/H5Tprivate.h | 1 | ||||
-rw-r--r-- | test/dsets.c | 1 | ||||
-rw-r--r-- | test/tfile.c | 494 |
26 files changed, 1124 insertions, 94 deletions
@@ -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" @@ -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,15 +851,294 @@ 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 * * Purpose: Compares NEEDLE to a file from the HAYSTACK. @@ -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); @@ -2188,40 +2518,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 diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 206f5e6..13a4a01 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -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 */ diff --git a/src/H5FDdpss.c b/src/H5FDdpss.c index 87f86f5..9884c3b 100644 --- a/src/H5FDdpss.c +++ b/src/H5FDdpss.c @@ -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 */ diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 80feac2..16c2265 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -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 */ diff --git a/src/H5FDgass.c b/src/H5FDgass.c index 25bcdaf..12040cd 100644 --- a/src/H5FDgass.c +++ b/src/H5FDgass.c @@ -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 */ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 11162b6..b1a9848 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -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 */ diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 9209050..437d18f 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -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 */ diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index d7d67b1..b554b88 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -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 */ diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 66358be..d288307 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -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 */ - - 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 */ + 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 */ }; #ifdef __cplusplus diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index 04bcb16..df150a7 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -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 */ diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index d86dbac..d292727 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -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 */ diff --git a/src/H5FDstream.c b/src/H5FDstream.c index 7572e45..581c0b7 100644 --- a/src/H5FDstream.c +++ b/src/H5FDstream.c @@ -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 */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 0bff2a8..822896d 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -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 */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index cedfc38..ed5daf6 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -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" diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 5309b02..b7db6de 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -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); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 2bc158c..7590597 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -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; diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index abf2a4e..bb289a0 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -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 { @@ -3471,7 +3471,9 @@ 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: @@ -3480,6 +3482,82 @@ done: /*------------------------------------------------------------------------- + * 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 * * Purpose: Sets the memory allocate/free pair for VL datatypes. The diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 5f404b6..1f5bc65 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -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, @@ -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; @@ -7640,6 +7640,37 @@ H5T_entof (H5T_t *dt) } +/*------------------------------------------------------------------------- + * 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 H5T_get_ref_type diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 7082b50..f815705 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -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 */ diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 72f068a..23cd9a3 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -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); diff --git a/test/dsets.c b/test/dsets.c index 80ca27d..739af4a 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -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; diff --git a/test/tfile.c b/test/tfile.c index 308188a..98da5e7 100644 --- a/test/tfile.c +++ b/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. @@ -345,6 +358,483 @@ test_file_open(void) /**************************************************************** ** +** 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); } - |