/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*********************************************************** * * Test program: tfile * * Test the low-level file I/O features. * *************************************************************/ #include "testhdf5.h" #include "H5srcdir.h" #include "H5Iprivate.h" #include "H5Pprivate.h" #include "H5VLprivate.h" /* Virtual Object Layer */ #include "H5private.h" /* * This file needs to access private information from the H5F package. * This file also needs to access the file testing code. */ #define H5F_FRIEND /*suppress error about including H5Fpkg */ #define H5F_TESTING #include "H5Fpkg.h" /* File access */ #define H5D_FRIEND /*suppress error about including H5Dpkg */ #include "H5Dpkg.h" /* Dataset access */ #define H5S_FRIEND /*suppress error about including H5Spkg */ #include "H5Spkg.h" /* Dataspace */ #define H5T_FRIEND /*suppress error about including H5Tpkg */ #include "H5Tpkg.h" /* Datatype */ #define H5A_FRIEND /*suppress error about including H5Apkg */ #include "H5Apkg.h" /* Attributes */ #define H5O_FRIEND /*suppress error about including H5Opkg */ #include "H5Opkg.h" /* Object headers */ #define BAD_USERBLOCK_SIZE1 (hsize_t)1 #define BAD_USERBLOCK_SIZE2 (hsize_t)2 #define BAD_USERBLOCK_SIZE3 (hsize_t)3 #define BAD_USERBLOCK_SIZE4 (hsize_t)64 #define BAD_USERBLOCK_SIZE5 (hsize_t)511 #define BAD_USERBLOCK_SIZE6 (hsize_t)513 #define BAD_USERBLOCK_SIZE7 (hsize_t)6144 #define F1_USERBLOCK_SIZE (hsize_t)0 #define F1_OFFSET_SIZE sizeof(haddr_t) #define F1_LENGTH_SIZE sizeof(hsize_t) #define F1_SYM_LEAF_K 4 #define F1_SYM_INTERN_K 16 #define FILE1 "tfile1.h5" #define SFILE1 "sys_file1" #define REOPEN_FILE "tfile_reopen.h5" #define REOPEN_DSET "dset" #define F2_USERBLOCK_SIZE (hsize_t)512 #define F2_OFFSET_SIZE 8 #define F2_LENGTH_SIZE 8 #define F2_SYM_LEAF_K 8 #define F2_SYM_INTERN_K 32 #define F2_RANK 2 #define F2_DIM0 4 #define F2_DIM1 6 #define F2_DSET "dset" #define FILE2 "tfile2.h5" #define F3_USERBLOCK_SIZE (hsize_t)0 #define F3_OFFSET_SIZE F2_OFFSET_SIZE #define F3_LENGTH_SIZE F2_LENGTH_SIZE #define F3_SYM_LEAF_K F2_SYM_LEAF_K #define F3_SYM_INTERN_K F2_SYM_INTERN_K #define FILE3 "tfile3.h5" #define GRP_NAME "/group" #define DSET_NAME "dataset" #define ATTR_NAME "attr" #define TYPE_NAME "type" #define FILE4 "tfile4.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 #define GROUP1 "Group1" #define DSET1 "Dataset1" #define DSET2 "/Group1/Dataset2" #define TESTA_GROUPNAME "group" #define TESTA_DSETNAME "dataset" #define TESTA_ATTRNAME "attribute" #define TESTA_DTYPENAME "compound" #define TESTA_NAME_BUF_SIZE 64 #define TESTA_RANK 2 #define TESTA_NX 4 #define TESTA_NY 5 #define USERBLOCK_SIZE ((hsize_t)512) /* Declarations for test_filespace_*() */ #define FILENAME_LEN 1024 /* length of file name */ #define DSETNAME "dset" /* Name of dataset */ #define NELMTS(X) (sizeof(X) / sizeof(X[0])) /* # of elements */ #define READ_OLD_BUFSIZE 1024 /* Buffer for holding file data */ #define FILE5 "tfile5.h5" /* Test file */ #define TEST_THRESHOLD10 10 /* Free space section threshold */ #define FSP_SIZE_DEF 4096 /* File space page size default */ #define FSP_SIZE512 512 /* File space page size */ #define FSP_SIZE1G 1024 * 1024 * 1024 /* File space page size */ /* Declaration for test_libver_macros2() */ #define FILE6 "tfile6.h5" /* Test file */ /* Declaration for test_get_obj_ids() */ #define FILE7 "tfile7.h5" /* Test file */ #define NGROUPS 2 #define NDSETS 4 /* Declaration for test_incr_filesize() */ #define FILE8 "tfile8.h5" /* Test file */ /* Files created under 1.6 branch and 1.8 branch--used in test_filespace_compatible() */ const char *OLD_FILENAME[] = { "filespace_1_6.h5", /* 1.6 HDF5 file */ "filespace_1_8.h5" /* 1.8 HDF5 file */ }; /* Files created in 1.10.0 release --used in test_filespace_1.10.0_compatible() */ /* These files are copied from release 1.10.0 tools/h5format_convert/testfiles */ const char *OLD_1_10_0_FILENAME[] = { "h5fc_ext1_i.h5", /* 0 */ "h5fc_ext1_f.h5", /* 1 */ "h5fc_ext2_if.h5", /* 2 */ "h5fc_ext2_sf.h5", /* 3 */ "h5fc_ext3_isf.h5", /* 4 */ "h5fc_ext_none.h5" /* 5 */ }; /* Files used in test_filespace_round_compatible() */ const char *FSPACE_FILENAMES[] = { "fsm_aggr_nopersist.h5", /* H5F_FILE_SPACE_AGGR, not persisting free-space */ "fsm_aggr_persist.h5", /* H5F_FILE_SPACE_AGGR, persisting free-space */ "paged_nopersist.h5", /* H5F_FILE_SPACE_PAGE, not persisting free-space */ "paged_persist.h5", /* H5F_FILE_SPACE_PAGE, persisting free-space */ "aggr.h5", /* H5F_FILE_SPACE_AGGR */ "none.h5" /* H5F_FILE_SPACE_NONE */ }; const char *FILESPACE_NAME[] = {"tfilespace", NULL}; /* Declarations for test_libver_bounds_copy(): */ /* SRC_FILE: source file created under 1.8 branch with latest format */ /* DST_FILE: destination file for copying the dataset in SRC_FILE */ /* DSET_DS1: the dataset created in SRC_FILE to be copied to DST_FILE */ #define SRC_FILE "fill18.h5" #define DST_FILE "fill18_copy.h5" #define DSET_DS1 "DS1" /* Local test function declarations for version bounds */ static void test_libver_bounds_low_high(void); static void test_libver_bounds_super(hid_t fapl); static void test_libver_bounds_super_create(hid_t fapl, hid_t fcpl, htri_t is_swmr, htri_t non_def_fsm); static void test_libver_bounds_super_open(hid_t fapl, hid_t fcpl, htri_t is_swmr, htri_t non_def_fsm); static void test_libver_bounds_obj(hid_t fapl); static void test_libver_bounds_dataset(hid_t fapl); static void test_libver_bounds_dataspace(hid_t fapl); static void test_libver_bounds_datatype(hid_t fapl); static void test_libver_bounds_datatype_check(hid_t fapl, hid_t tid); static void test_libver_bounds_attributes(hid_t fapl); #define DSET_NULL "DSET_NULL" #define DSET "DSET" #define DSETA "DSETA" #define DSETB "DSETB" #define DSETC "DSETC" 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); static void check_file_id(hid_t, hid_t); /* Helper routine used by test_rw_noupdate() */ static int cal_chksum(const char *file, uint32_t *chksum); static void test_rw_noupdate(void); /**************************************************************** ** ** test_file_create(): Low-level file creation I/O test routine. ** ****************************************************************/ static void test_file_create(void) { hid_t fid1, fid2, fid3; /* HDF5 File IDs */ hid_t tmpl1, tmpl2; /*file creation templates */ hsize_t ublock; /*sizeof userblock */ size_t parm; /*file-creation parameters */ size_t parm2; /*file-creation parameters */ unsigned iparm; unsigned iparm2; herr_t ret; /*generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Low-Level File Creation I/O\n")); /* First ensure the file does not exist */ HDremove(FILE1); /* Try opening a non-existant file */ fid1 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT); VERIFY(fid1, FAIL, "H5Fopen"); /* Test create with various sequences of H5F_ACC_EXCL and */ /* H5F_ACC_TRUNC flags */ /* Create with H5F_ACC_EXCL */ fid1 = H5Fcreate(FILE1, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); /* * try to create the same file with H5F_ACC_TRUNC. This should fail * because fid1 is the same file and is currently open. */ fid2 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); VERIFY(fid2, FAIL, "H5Fcreate"); /* Close all files */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); ret = H5Fclose(fid2); VERIFY(ret, FAIL, "H5Fclose"); /*file should not have been open */ /* * Try again with H5F_ACC_EXCL. This should fail because the file already * exists from the previous steps. */ fid1 = H5Fcreate(FILE1, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); VERIFY(fid1, FAIL, "H5Fcreate"); /* Test create with H5F_ACC_TRUNC. This will truncate the existing file. */ fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); /* * Try to truncate first file again. This should fail because fid1 is the * same file and is currently open. */ fid2 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); VERIFY(fid2, FAIL, "H5Fcreate"); /* * Try with H5F_ACC_EXCL. This should fail too because the file already * exists. */ fid2 = H5Fcreate(FILE1, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); VERIFY(fid2, FAIL, "H5Fcreate"); /* Get the file-creation template */ tmpl1 = H5Fget_create_plist(fid1); CHECK(tmpl1, FAIL, "H5Fget_create_plist"); /* Get the file-creation parameters */ ret = H5Pget_userblock(tmpl1, &ublock); CHECK(ret, FAIL, "H5Pget_userblock"); VERIFY(ublock, F1_USERBLOCK_SIZE, "H5Pget_userblock"); ret = H5Pget_sizes(tmpl1, &parm, &parm2); CHECK(ret, FAIL, "H5Pget_sizes"); VERIFY(parm, F1_OFFSET_SIZE, "H5Pget_sizes"); VERIFY(parm2, F1_LENGTH_SIZE, "H5Pget_sizes"); ret = H5Pget_sym_k(tmpl1, &iparm, &iparm2); CHECK(ret, FAIL, "H5Pget_sym_k"); VERIFY(iparm, F1_SYM_INTERN_K, "H5Pget_sym_k"); VERIFY(iparm2, F1_SYM_LEAF_K, "H5Pget_sym_k"); /* Release file-creation template */ ret = H5Pclose(tmpl1); CHECK(ret, FAIL, "H5Pclose"); #ifdef LATER /* Double-check that the atom has been vaporized */ ret = H5Pclose(tmpl1); VERIFY(ret, FAIL, "H5Pclose"); #endif /* Create a new file with a non-standard file-creation template */ tmpl1 = H5Pcreate(H5P_FILE_CREATE); CHECK(tmpl1, FAIL, "H5Pcreate"); /* Try setting some bad userblock sizes */ H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE1); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE2); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE3); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE4); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE5); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE6); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); H5E_BEGIN_TRY { ret = H5Pset_userblock(tmpl1, BAD_USERBLOCK_SIZE7); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Pset_userblock"); /* Set the new file-creation parameters */ ret = H5Pset_userblock(tmpl1, F2_USERBLOCK_SIZE); CHECK(ret, FAIL, "H5Pset_userblock"); ret = H5Pset_sizes(tmpl1, (size_t)F2_OFFSET_SIZE, (size_t)F2_LENGTH_SIZE); CHECK(ret, FAIL, "H5Pset_sizes"); ret = H5Pset_sym_k(tmpl1, F2_SYM_INTERN_K, F2_SYM_LEAF_K); CHECK(ret, FAIL, "H5Pset_sym_k"); /* * Try to create second file, with non-standard file-creation template * params. */ fid2 = H5Fcreate(FILE2, H5F_ACC_TRUNC, tmpl1, H5P_DEFAULT); CHECK(fid2, FAIL, "H5Fcreate"); /* Release file-creation template */ ret = H5Pclose(tmpl1); CHECK(ret, FAIL, "H5Pclose"); /* Make certain we can create a dataset properly in the file with the userblock */ { hid_t dataset_id, dataspace_id; /* identifiers */ hsize_t dims[F2_RANK]; unsigned 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 = H5Dcreate2(fid2, F2_DSET, H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset_id, FAIL, "H5Dcreate2"); 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_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); CHECK(ret, FAIL, "H5Dwrite"); /* End access to the dataset and release resources used by it. */ ret = H5Dclose(dataset_id); CHECK(ret, FAIL, "H5Dclose"); /* Terminate access to the data space. */ ret = H5Sclose(dataspace_id); CHECK(ret, FAIL, "H5Sclose"); } /* Get the file-creation template */ tmpl1 = H5Fget_create_plist(fid2); CHECK(tmpl1, FAIL, "H5Fget_create_plist"); /* Get the file-creation parameters */ ret = H5Pget_userblock(tmpl1, &ublock); CHECK(ret, FAIL, "H5Pget_userblock"); VERIFY(ublock, F2_USERBLOCK_SIZE, "H5Pget_userblock"); ret = H5Pget_sizes(tmpl1, &parm, &parm2); CHECK(ret, FAIL, "H5Pget_sizes"); VERIFY(parm, F2_OFFSET_SIZE, "H5Pget_sizes"); VERIFY(parm2, F2_LENGTH_SIZE, "H5Pget_sizes"); ret = H5Pget_sym_k(tmpl1, &iparm, &iparm2); CHECK(ret, FAIL, "H5Pget_sym_k"); VERIFY(iparm, F2_SYM_INTERN_K, "H5Pget_sym_k"); VERIFY(iparm2, F2_SYM_LEAF_K, "H5Pget_sym_k"); /* Clone the file-creation template */ tmpl2 = H5Pcopy(tmpl1); CHECK(tmpl2, FAIL, "H5Pcopy"); /* Release file-creation template */ ret = H5Pclose(tmpl1); CHECK(ret, FAIL, "H5Pclose"); /* Set the new file-creation parameter */ ret = H5Pset_userblock(tmpl2, F3_USERBLOCK_SIZE); CHECK(ret, FAIL, "H5Pset_userblock"); /* * Try to create second file, with non-standard file-creation template * params */ fid3 = H5Fcreate(FILE3, H5F_ACC_TRUNC, tmpl2, H5P_DEFAULT); CHECK(fid3, FAIL, "H5Fcreate"); /* Release file-creation template */ ret = H5Pclose(tmpl2); CHECK(ret, FAIL, "H5Pclose"); /* Get the file-creation template */ tmpl1 = H5Fget_create_plist(fid3); CHECK(tmpl1, FAIL, "H5Fget_create_plist"); /* Get the file-creation parameters */ ret = H5Pget_userblock(tmpl1, &ublock); CHECK(ret, FAIL, "H5Pget_userblock"); VERIFY(ublock, F3_USERBLOCK_SIZE, "H5Pget_userblock"); ret = H5Pget_sizes(tmpl1, &parm, &parm2); CHECK(ret, FAIL, "H5Pget_sizes"); VERIFY(parm, F3_OFFSET_SIZE, "H5Pget_sizes"); VERIFY(parm2, F3_LENGTH_SIZE, "H5Pget_sizes"); ret = H5Pget_sym_k(tmpl1, &iparm, &iparm2); CHECK(ret, FAIL, "H5Pget_sym_k"); VERIFY(iparm, F3_SYM_INTERN_K, "H5Pget_sym_k"); VERIFY(iparm2, F3_SYM_LEAF_K, "H5Pget_sym_k"); /* Release file-creation template */ ret = H5Pclose(tmpl1); CHECK(ret, FAIL, "H5Pclose"); /* Close first file */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); /* Close second file */ ret = H5Fclose(fid2); CHECK(ret, FAIL, "H5Fclose"); /* Close third file */ ret = H5Fclose(fid3); CHECK(ret, FAIL, "H5Fclose"); } /* test_file_create() */ /**************************************************************** ** ** test_file_open(): Low-level file open I/O test routine. ** ****************************************************************/ static void test_file_open(void) { hid_t fid1, fid2; /*HDF5 File IDs */ hid_t did; /*dataset ID */ hid_t fapl_id; /*file access property list ID */ hid_t tmpl1; /*file creation templates */ hsize_t ublock; /*sizeof user block */ size_t parm; /*file-creation parameters */ size_t parm2; /*file-creation parameters */ unsigned iparm; unsigned iparm2; unsigned intent; herr_t ret; /*generic return value */ /* * Test single file open */ /* Output message about test being performed */ MESSAGE(5, ("Testing Low-Level File Opening I/O\n")); /* Open first file */ fid1 = H5Fopen(FILE2, H5F_ACC_RDWR, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fopen"); /* Get the intent */ ret = H5Fget_intent(fid1, &intent); CHECK(ret, FAIL, "H5Fget_intent"); VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent"); /* Get the file-creation template */ tmpl1 = H5Fget_create_plist(fid1); CHECK(tmpl1, FAIL, "H5Fget_create_plist"); /* Get the file-creation parameters */ ret = H5Pget_userblock(tmpl1, &ublock); CHECK(ret, FAIL, "H5Pget_userblock"); VERIFY(ublock, F2_USERBLOCK_SIZE, "H5Pget_userblock"); ret = H5Pget_sizes(tmpl1, &parm, &parm2); CHECK(ret, FAIL, "H5Pget_sizes"); VERIFY(parm, F2_OFFSET_SIZE, "H5Pget_sizes"); VERIFY(parm2, F2_LENGTH_SIZE, "H5Pget_sizes"); ret = H5Pget_sym_k(tmpl1, &iparm, &iparm2); CHECK(ret, FAIL, "H5Pget_sym_k"); VERIFY(iparm, F2_SYM_INTERN_K, "H5Pget_sym_k"); VERIFY(iparm2, F2_SYM_LEAF_K, "H5Pget_sym_k"); /* Release file-creation template */ ret = H5Pclose(tmpl1); CHECK(ret, FAIL, "H5Pclose"); /* Close first file */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); /* * Test two file opens: one is opened H5F_ACC_RDONLY and H5F_CLOSE_WEAK. * It's closed with an object left open. Then another is opened * H5F_ACC_RDWR, which should fail. */ /* Output message about test being performed */ MESSAGE(5, ("Testing 2 File Openings\n")); /* Create file access property list */ fapl_id = H5Pcreate(H5P_FILE_ACCESS); CHECK(fapl_id, FAIL, "H5Pcreate"); /* Set file close mode to H5F_CLOSE_WEAK */ ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK); CHECK(ret, FAIL, "H5Pset_fclose_degree"); /* Open file for first time */ fid1 = H5Fopen(FILE2, H5F_ACC_RDONLY, fapl_id); CHECK(fid1, FAIL, "H5Fopen"); /* Check the intent */ ret = H5Fget_intent(fid1, &intent); CHECK(ret, FAIL, "H5Fget_intent"); VERIFY(intent, H5F_ACC_RDONLY, "H5Fget_intent"); /* Open dataset */ did = H5Dopen2(fid1, F2_DSET, H5P_DEFAULT); CHECK(did, FAIL, "H5Dopen2"); /* Check that the intent works even if NULL is passed in */ ret = H5Fget_intent(fid1, NULL); CHECK(ret, FAIL, "H5Fget_intent"); /* Close first open */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); /* Open file for second time, which should fail. */ fid2 = H5Fopen(FILE2, H5F_ACC_RDWR, fapl_id); VERIFY(fid2, FAIL, "H5Fopen"); /* Check that the intent fails for an invalid ID */ ret = H5Fget_intent(fid1, &intent); VERIFY(ret, FAIL, "H5Fget_intent"); /* Close dataset from first open */ ret = H5Dclose(did); CHECK(ret, FAIL, "H5Dclose"); ret = H5Pclose(fapl_id); CHECK(ret, FAIL, "H5Pclose"); } /* test_file_open() */ /**************************************************************** ** ** test_file_reopen(): File reopen test routine. ** ****************************************************************/ static void test_file_reopen(void) { hid_t fid = -1; /* file ID from initial open */ hid_t rfid = -1; /* file ID from reopen */ hid_t did = -1; /* dataset ID (both opens) */ hid_t sid = -1; /* dataspace ID for dataset creation */ hsize_t dims = 6; /* dataspace size */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing File Re-opening\n")); /* Create file via first ID */ fid = H5Fcreate(REOPEN_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK_I(fid, "H5Fcreate"); /* Create a dataset in the file */ sid = H5Screate_simple(1, &dims, &dims); CHECK_I(sid, "H5Screate_simple") did = H5Dcreate2(fid, REOPEN_DSET, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK_I(did, "H5Dcreate2"); /* Close dataset and dataspace */ ret = H5Sclose(sid); CHECK(ret, FAIL, "H5Sclose"); ret = H5Dclose(did); CHECK(ret, FAIL, "H5Dclose"); /* Reopen the file with a different file ID */ rfid = H5Freopen(fid); CHECK_I(rfid, "H5Freopen"); /* Reopen the dataset through the reopen file ID */ did = H5Dopen2(rfid, REOPEN_DSET, H5P_DEFAULT); CHECK_I(did, "H5Dopen2"); /* Close and clean up */ ret = H5Dclose(did); CHECK(ret, FAIL, "H5Dclose"); ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); ret = H5Fclose(rfid); CHECK(ret, FAIL, "H5Fclose"); HDremove(REOPEN_FILE); } /* test_file_reopen() */ /**************************************************************** ** ** test_file_close(): low-level file close test routine. ** It mainly tests behavior with close degree. ** *****************************************************************/ static void test_file_close(void) { 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; 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 different file * close degree */ fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK); CHECK(ret, FAIL, "H5Pset_fclose_degree"); ret = H5Pget_fclose_degree(fapl_id, &fc_degree); VERIFY(fc_degree, H5F_CLOSE_WEAK, "H5Pget_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, should fail since it is SEMI and objects are * still open. */ ret = H5Fclose(fid1); VERIFY(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"); /* Close first open */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); 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"); /* Same check with H5Idec_ref() (should fail also) */ ret = H5Idec_ref(fid2); VERIFY(ret, FAIL, "H5Idec_ref"); 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_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); /* 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; case H5F_CLOSE_DEFAULT: default: CHECK(fc_degree, H5F_CLOSE_DEFAULT, "H5Pget_fclose_degree"); 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) { ssize_t 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. */ { oid_count = H5Fget_obj_count(fid1, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_2, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid1, H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_0, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid2, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_2, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid2, H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR); CHECK(oid_count, 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]; unsigned 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 = H5Dcreate2(fid1, "/dset", H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset_id, FAIL, "H5Dcreate2"); 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_UINT, 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 = H5Gcreate2(fid2, "/group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(gid1, FAIL, "H5Gcreate2"); if (ret_gid1 != NULL) *ret_gid1 = gid1; gid2 = H5Gopen2(fid2, "/group", H5P_DEFAULT); CHECK(gid2, FAIL, "H5Gopen2"); if (ret_gid2 != NULL) *ret_gid2 = gid2; gid3 = H5Gopen2(fid2, "/group", H5P_DEFAULT); CHECK(gid3, FAIL, "H5Gopen2"); 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. */ { oid_count = H5Fget_obj_count(fid1, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_6, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid1, H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid2, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_6, "H5Fget_obj_count"); oid_count = H5Fget_obj_count(fid2, H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count"); } } /**************************************************************** ** ** test_get_obj_ids(): Test the bug and the fix for Jira 8528. ** H5Fget_obj_ids overfilled the list of ** object IDs by one. This is an enhancement ** for test_obj_count_and_id(). ** ****************************************************************/ static void test_get_obj_ids(void) { hid_t fid, gid[NGROUPS], dset[NDSETS]; hid_t filespace; hsize_t file_dims[F2_RANK] = {F2_DIM0, F2_DIM1}; ssize_t oid_count, ret_count; hid_t * oid_list = NULL; herr_t ret; int i, m, n; ssize_t oid_list_size = NDSETS; char gname[64], dname[64]; /* Create a new file */ fid = H5Fcreate(FILE7, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid, FAIL, "H5Fcreate"); filespace = H5Screate_simple(F2_RANK, file_dims, NULL); CHECK(filespace, FAIL, "H5Screate_simple"); /* creates NGROUPS groups under the root group */ for (m = 0; m < NGROUPS; m++) { HDsprintf(gname, "group%d", m); gid[m] = H5Gcreate2(fid, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(gid[m], FAIL, "H5Gcreate2"); } /* create NDSETS datasets under the root group */ for (n = 0; n < NDSETS; n++) { HDsprintf(dname, "dataset%d", n); dset[n] = H5Dcreate2(fid, dname, H5T_NATIVE_INT, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dset[n], FAIL, "H5Dcreate2"); } /* The number of opened objects should be NGROUPS + NDSETS + 1. One is opened file. */ oid_count = H5Fget_obj_count(fid, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, (NGROUPS + NDSETS + 1), "H5Fget_obj_count"); oid_list = (hid_t *)HDcalloc((size_t)oid_list_size, sizeof(hid_t)); CHECK_PTR(oid_list, "HDcalloc"); /* Call the public function H5F_get_obj_ids to use H5F__get_objects. User reported having problem here. * that the returned size (ret_count) from H5Fget_obj_ids is one greater than the size passed in * (oid_list_size) */ ret_count = H5Fget_obj_ids(fid, H5F_OBJ_ALL, (size_t)oid_list_size, oid_list); CHECK(ret_count, FAIL, "H5Fget_obj_ids"); VERIFY(ret_count, oid_list_size, "H5Fget_obj_count"); /* Close all object IDs on the list except the file ID. The first ID is supposed to be file ID according * to the library design */ for (i = 0; i < ret_count; i++) { if (fid != oid_list[i]) { ret = H5Oclose(oid_list[i]); CHECK(ret, FAIL, "H5Oclose"); } } /* The number of opened objects should be NGROUPS + 1 + 1. The first one is opened file. The second one * is the dataset ID left open from the previous around of H5Fget_obj_ids */ oid_count = H5Fget_obj_count(fid, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, NGROUPS + 2, "H5Fget_obj_count"); /* Get the IDs of the left opend objects */ ret_count = H5Fget_obj_ids(fid, H5F_OBJ_ALL, (size_t)oid_list_size, oid_list); CHECK(ret_count, FAIL, "H5Fget_obj_ids"); VERIFY(ret_count, oid_list_size, "H5Fget_obj_count"); /* Close all object IDs on the list except the file ID. The first ID is still the file ID */ for (i = 0; i < ret_count; i++) { if (fid != oid_list[i]) { ret = H5Oclose(oid_list[i]); CHECK(ret, FAIL, "H5Oclose"); } } H5Sclose(filespace); H5Fclose(fid); HDfree(oid_list); /* Reopen the file to check whether H5Fget_obj_count and H5Fget_obj_ids still works * when the file is closed first */ fid = H5Fopen(FILE7, H5F_ACC_RDONLY, H5P_DEFAULT); CHECK(fid, FAIL, "H5Fopen"); /* Open NDSETS datasets under the root group */ for (n = 0; n < NDSETS; n++) { HDsprintf(dname, "dataset%d", n); dset[n] = H5Dopen2(fid, dname, H5P_DEFAULT); CHECK(dset[n], FAIL, "H5Dcreate2"); } /* Close the file first */ H5Fclose(fid); /* Get the number of all opened objects */ oid_count = H5Fget_obj_count((hid_t)H5F_OBJ_ALL, H5F_OBJ_ALL); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, NDSETS, "H5Fget_obj_count"); oid_list = (hid_t *)HDcalloc((size_t)oid_count, sizeof(hid_t)); CHECK_PTR(oid_list, "HDcalloc"); /* Get the list of all opened objects */ ret_count = H5Fget_obj_ids((hid_t)H5F_OBJ_ALL, H5F_OBJ_ALL, (size_t)oid_count, oid_list); CHECK(ret_count, FAIL, "H5Fget_obj_ids"); VERIFY(ret_count, NDSETS, "H5Fget_obj_count"); /* Close all open objects with H5Oclose */ for (n = 0; n < oid_count; n++) H5Oclose(oid_list[n]); HDfree(oid_list); } /**************************************************************** ** ** test_get_file_id(): Test H5Iget_file_id() ** *****************************************************************/ static void test_get_file_id(void) { hid_t fid, fid2, fid3; hid_t datatype_id, dataset_id, dataspace_id, group_id, attr_id; hid_t plist; hsize_t dims[F2_RANK]; unsigned intent; herr_t ret; /* Create a file */ fid = H5Fcreate(FILE4, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid, FAIL, "H5Fcreate"); /* Check the intent */ ret = H5Fget_intent(fid, &intent); CHECK(ret, FAIL, "H5Fget_intent"); VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent"); /* Test H5Iget_file_id() */ check_file_id(fid, fid); /* Create a group in the file. Make a duplicated file ID from the group. * And close this duplicated ID */ group_id = H5Gcreate2(fid, GRP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(group_id, FAIL, "H5Gcreate2"); /* Test H5Iget_file_id() */ check_file_id(fid, group_id); /* Close the file and get file ID from the group ID */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); /* Test H5Iget_file_id() */ check_file_id((hid_t)-1, group_id); ret = H5Gclose(group_id); CHECK(ret, FAIL, "H5Gclose"); /* Open the file again. Test H5Iget_file_id() */ fid = H5Fopen(FILE4, H5F_ACC_RDWR, H5P_DEFAULT); CHECK(fid, FAIL, "H5Fcreate"); group_id = H5Gopen2(fid, GRP_NAME, H5P_DEFAULT); CHECK(group_id, FAIL, "H5Gopen2"); /* Test H5Iget_file_id() */ check_file_id(fid, group_id); /* Open the file for second time. Test H5Iget_file_id() */ fid3 = H5Freopen(fid); CHECK(fid3, FAIL, "H5Freopen"); /* Test H5Iget_file_id() */ check_file_id(fid3, fid3); ret = H5Fclose(fid3); CHECK(ret, FAIL, "H5Fclose"); /* Create a dataset in the group. Make a duplicated file ID from the * dataset. And close this duplicated ID. */ dims[0] = F2_DIM0; dims[1] = F2_DIM1; dataspace_id = H5Screate_simple(F2_RANK, dims, NULL); CHECK(dataspace_id, FAIL, "H5Screate_simple"); dataset_id = H5Dcreate2(group_id, DSET_NAME, H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset_id, FAIL, "H5Dcreate2"); /* Test H5Iget_file_id() */ check_file_id(fid, dataset_id); /* Create an attribute for the dataset. Make a duplicated file ID from * this attribute. And close it. */ attr_id = H5Acreate2(dataset_id, ATTR_NAME, H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Acreate2"); /* Test H5Iget_file_id() */ check_file_id(fid, attr_id); /* Create a named datatype. Make a duplicated file ID from * this attribute. And close it. */ datatype_id = H5Tcopy(H5T_NATIVE_INT); CHECK(ret, FAIL, "H5Tcopy"); ret = H5Tcommit2(fid, TYPE_NAME, datatype_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Tcommit2"); /* Test H5Iget_file_id() */ check_file_id(fid, datatype_id); /* Create a property list and try to get file ID from it. * Supposed to fail. */ plist = H5Pcreate(H5P_FILE_ACCESS); CHECK(plist, FAIL, "H5Pcreate"); H5E_BEGIN_TRY { fid2 = H5Iget_file_id(plist); } H5E_END_TRY; VERIFY(fid2, FAIL, "H5Iget_file_id"); /* Close objects */ ret = H5Pclose(plist); CHECK(ret, FAIL, "H5Pclose"); ret = H5Tclose(datatype_id); CHECK(ret, FAIL, "H5Tclose"); ret = H5Aclose(attr_id); CHECK(ret, FAIL, "H5Aclose"); ret = H5Sclose(dataspace_id); CHECK(ret, FAIL, "H5Sclose"); ret = H5Dclose(dataset_id); CHECK(ret, FAIL, "H5Dclose"); ret = H5Gclose(group_id); CHECK(ret, FAIL, "H5Gclose"); ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); } /**************************************************************** ** ** check_file_id(): Internal function of test_get_file_id() ** *****************************************************************/ static void check_file_id(hid_t fid, hid_t object_id) { hid_t new_fid; herr_t ret; /* Return a duplicated file ID even not expecting user to do it. * And close this duplicated ID */ new_fid = H5Iget_file_id(object_id); if (fid >= 0) VERIFY(new_fid, fid, "H5Iget_file_id"); else CHECK(new_fid, FAIL, "H5Iget_file_id"); ret = H5Fclose(new_fid); CHECK(ret, FAIL, "H5Fclose"); } /**************************************************************** ** ** 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; ssize_t oid_count, ret_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 */ oid_count = H5Fget_obj_count((hid_t)H5F_OBJ_ALL, H5F_OBJ_FILE); CHECK(oid_count, FAIL, "H5Fget_obj_count"); VERIFY(oid_count, OBJ_ID_COUNT_4, "H5Fget_obj_count"); /* te H5F_mtab_t mtab; /* File mount table */ H5F_efc_t *efc; /* External file cache */ /* Cached values from FCPL/superblock */ uint8_t sizeof_addr; /* Size of addresses in file */ uint8_t sizeof_size; /* Size of offsets in file */ haddr_t sohm_addr; /* Relative address of shared object header message table */ unsigned sohm_vers; /* Version of shared message table on disk */ unsigned sohm_nindexes; /* Number of shared messages indexes in the table */ unsigned long feature_flags; /* VFL Driver feature Flags */ haddr_t maxaddr; /* Maximum address for file */ H5AC_t *cache; /* The object cache */ H5AC_cache_config_t mdc_initCacheCfg; /* initial configuration for the */ /* metadata cache. This structure is */ /* fixed at creation time and should */ /* not change thereafter. */ hid_t fcpl_id; /* File creation property list ID */ H5F_close_degree_t fc_degree; /* File close behavior degree */ size_t rdcc_nslots; /* Size of raw data chunk cache (slots) */ size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */ double rdcc_w0; /* Preempt read chunks first? [0.0..1.0]*/ size_t sieve_buf_size; /* Size of the data sieve buffer allocated (in bytes) */ hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Alignment */ unsigned gc_ref; /* Garbage-collect references? */ hbool_t latest_format; /* Always use the latest format? */ hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */ unsigned ncwfs; /* Num entries on cwfs list */ struct H5HG_heap_t **cwfs; /* Global heap cache */ struct H5G_t *root_grp; /* Open root group */ H5FO_t *open_objs; /* Open objects in file */ H5UC_t *grp_btree_shared; /* Ref-counted group B-tree node info */ /* File space allocation information */ H5F_file_space_type_t fs_strategy; /* File space handling strategy */ hsize_t fs_threshold; /* Free space section threshold */ hbool_t use_tmp_space; /* Whether temp. file space allocation is allowed */ haddr_t tmp_addr; /* Next address to use for temp. space in the file */ unsigned fs_aggr_merge[H5FD_MEM_NTYPES]; /* Flags for whether free space can merge with aggregator(s) */ H5F_fs_state_t fs_state[H5FD_MEM_NTYPES]; /* State of free space manager for each type */ haddr_t fs_addr[H5FD_MEM_NTYPES]; /* Address of free space manager info for each type */ H5FS_t *fs_man[H5FD_MEM_NTYPES]; /* Free space manager for each file space type */ H5FD_mem_t fs_type_map[H5FD_MEM_NTYPES]; /* Mapping of "real" file space type into tracked type */ H5F_blk_aggr_t meta_aggr; /* Metadata aggregation info */ /* (if aggregating metadata allocations) */ H5F_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */ /* (if aggregating "small data" allocations) */ /* Metadata accumulator information */ H5F_meta_accum_t accum; /* Metadata accumulator info */ }; /* * This is the top-level file descriptor. One of these structures is * allocated every time H5Fopen() is called although they may contain pointers * to shared H5F_file_t structs. */ struct H5F_t { char *open_name; /* Name used to open file */ char *actual_name; /* Actual name of the file, after resolving symlinks, etc. */ char *extpath; /* Path for searching target external link file */ H5F_file_t *shared; /* The shared file info */ unsigned nopen_objs; /* Number of open object headers*/ H5FO_t *obj_count; /* # of time each object is opened through top file structure */ hid_t file_id; /* ID of this file */ hbool_t closing; /* File is in the process of being closed */ struct H5F_t *parent; /* Parent file that this file is mounted to */ unsigned nmounts; /* Number of children mounted to this file */ }; /*****************************/ /* Package Private Variables */ /*****************************/ /* Declare a free list to manage the H5F_t struct */ H5FL_EXTERN(H5F_t); /* Declare a free list to manage the H5F_file_t struct */ H5FL_EXTERN(H5F_file_t); H5_DLLVAR const H5AC_class_t H5AC_SUPERBLOCK[1]; H5_DLLVAR const H5AC_class_t H5AC_DRVRINFO[1]; /******************************/ /* Package Private Prototypes */ /******************************/ /* General routines */ H5F_t *H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf); herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush); H5_DLL herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing); H5_DLL htri_t H5F_is_hdf5(const char *name); H5_DLL herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr); H5_DLL herr_t H5F_close(H5F_t *f); /* File mount related routines */ H5_DLL herr_t H5F_close_mounts(H5F_t *f); H5_DLL int H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void *key); H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs); /* Superblock related routines */ H5_DLL herr_t H5F__super_init(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F__super_read(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F__super_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_size, hsize_t *super_ext_size); H5_DLL herr_t H5F__super_free(H5F_super_t *sblock); /* Superblock extension related routines */ H5_DLL herr_t H5F_super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr); H5_DLL herr_t H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create); H5_DLL herr_t H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id); H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id, hbool_t was_created); /* Metadata accumulator routines */ H5_DLL herr_t H5F__accum_read(const H5F_io_info_t *fio_info, H5FD_mem_t type, haddr_t addr, size_t size, void *buf); H5_DLL herr_t H5F__accum_write(const H5F_io_info_t *fio_info, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf); H5_DLL herr_t H5F__accum_free(const H5F_io_info_t *fio_info, H5FD_mem_t type, haddr_t addr, hsize_t size); H5_DLL herr_t H5F__accum_flush(const H5F_io_info_t *fio_info); H5_DLL herr_t H5F__accum_reset(const H5F_io_info_t *fio_info, hbool_t flush); /* Shared file list related routines */ H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared); H5_DLL H5F_file_t * H5F_sfile_search(H5FD_t *lf); H5_DLL herr_t H5F_sfile_remove(H5F_file_t *shared); /* External file cache routines */ H5_DLL H5F_efc_t *H5F_efc_create(unsigned max_nfiles); H5_DLL unsigned H5F_efc_max_nfiles(H5F_efc_t *efc); H5_DLL herr_t H5F_efc_release(H5F_efc_t *efc); H5_DLL herr_t H5F_efc_destroy(H5F_efc_t *efc); H5_DLL herr_t H5F_efc_try_close(H5F_t *f); /* Functions that get/retrieve values from VFD layer */ H5_DLL herr_t H5F__set_eoa(const H5F_t *f, H5F_mem_t type, haddr_t addr); H5_DLL herr_t H5F__set_base_addr(const H5F_t *f, haddr_t addr); /* Testing functions */ #ifdef H5F_TESTING H5_DLL herr_t H5F_get_sohm_mesg_count_test(hid_t fid, unsigned type_id, size_t *mesg_count); H5_DLL herr_t H5F_check_cached_stab_test(hid_t file_id); H5_DLL herr_t H5F_get_maxaddr_test(hid_t file_id, haddr_t *maxaddr); #endif /* H5F_TESTING */ #endif /* _H5Fpkg_H */