/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*********************************************************** * * Test program: tsohm * * Test Shared Object Header Messages * *************************************************************/ #include "testhdf5.h" /* Maximum number of SOHM indexes in a file. Should correspond * to H5SM_MAX_NUM_INDEXES */ /* JAMES: get these three from default fcpl */ #define MAX_INDEXES 6 /* Default SOHM values */ #define DEF_NUM_INDEXES 0 const unsigned def_type_flags[MAX_INDEXES] = {0,0,0,0,0,0}; const unsigned def_minsizes[MAX_INDEXES] = {250,250,250,250,250,250}; #define DEF_L2B 50 #define DEF_B2L 40 /* Non-default SOHM values for testing */ /* JAMES: make these defined in function */ #define TEST_NUM_INDEXES 4 const unsigned test_type_flags[MAX_INDEXES] = {H5O_MESG_FILL_FLAG, H5O_MESG_DTYPE_FLAG | H5O_MESG_ATTR_FLAG, H5O_MESG_SDSPACE_FLAG, H5O_MESG_PLINE_FLAG, 0, 0}; const unsigned test_minsizes[MAX_INDEXES] = {0, 2, 40, 100, 3, 1000}; #define TEST_L2B 65 #define TEST_B2L 64 #define FILENAME "tsohm.h5" #define NAME_BUF_SIZE 512 /* How much overhead counts as "not much" when converting B-trees, etc. */ #define OVERHEAD_ALLOWED 1.1 #define NUM_DATASETS 10 #define NUM_ATTRIBUTES 100 typedef struct dtype1_struct { int i1; char str[10]; /* JAMES */ int i2; int i3; int i4; int i5; int i6; int i7; int i8; float f1; } dtype1_struct; #define DTYPE2_SIZE 1024 const char *DSETNAME[] = { "dataset0", "dataset1", "dataset2", "dataset3", "dataset4", "dataset5", "dataset6", "dataset7", "dataset8", "dataset9", "dataset10", "dataset11", NULL }; const char *EXTRA_DSETNAME[] = { "ex_dataset0", "ex_dataset1", "ex_dataset2", "ex_dataset3", "ex_dataset4", "ex_dataset5", "ex_dataset6", "ex_dataset7", "ex_dataset8", "ex_dataset9", "ex_dataset10", "ex_dataset11", "ex_dataset12", "ex_dataset13", "ex_dataset14", "ex_dataset15", "ex_dataset16", "ex_dataset17", "ex_dataset18", "ex_dataset19", NULL }; #define SOHM_HELPER_NUM_EX_DSETS 20 typedef struct complex_t { double re; double im; } complex_t; #define ENUM_NUM_MEMBS 20 const char *ENUM_NAME[] = { "enum_member0", "enum_member1", "enum_member2", "enum_member3", "enum_member4", "enum_member5", "enum_member6", "enum_member7", "enum_member8", "enum_member9", "enum_member10", "enum_member11", "enum_member12", "enum_member13", "enum_member14", "enum_member15", "enum_member16", "enum_member17", "enum_member18", "enum_member19", NULL }; const int ENUM_VAL[] = { 0, 13, -500, 63, 64, -64, 65, 2048, 1, 2, -1, 7, 130, -5000, 630, 640, -640, 650, 20480, 10, -1001, -10 }; #define SIZE2_RANK1 10 #define SIZE2_RANK2 20 #define SIZE2_DIMS {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} #define LONG_STRING "00 index. A long string used for testing. To create new strings, set the first two characters to be some ASCII number other than 00, such as 01." /* Struct returned from size2_helper function */ typedef struct size2_helper_struct { h5_stat_size_t empty_size; h5_stat_size_t first_dset; h5_stat_size_t dsets1; h5_stat_size_t dsets2; h5_stat_size_t interleaved; h5_stat_size_t attrs1; h5_stat_size_t attrs2; } size2_helper_struct; /**************************************************************** ** ** check_fcpl_values(): Helper function for test_sohm_fcpl. ** Verifies that the *_in and *_out parameters are equal. ** ****************************************************************/ static void check_fcpl_values(hid_t fcpl_id, const unsigned nindexes_in, const unsigned *flags_in, const unsigned *minsizes_in, unsigned l2b, unsigned b2l) { unsigned num_indexes; unsigned index_flags, min_mesg_size; unsigned list_size, btree_size; unsigned x; herr_t ret; /* Verify number of indexes is set to default */ ret = H5Pget_shared_mesg_nindexes(fcpl_id, &num_indexes); CHECK_I(ret, "H5Pget_shared_mesg_nindexes"); VERIFY(num_indexes, nindexes_in, "H5Pget_shared_mesg_nindexes"); /* Verify index flags and minsizes are set */ for(x=1; x<=num_indexes; ++x) { ret = H5Pget_shared_mesg_index(fcpl_id, x, &index_flags, &min_mesg_size); CHECK_I(ret, "H5Pget_shared_mesg_index"); VERIFY(index_flags, flags_in[x-1], "H5Pget_shared_mesg_index"); VERIFY(min_mesg_size, minsizes_in[x-1], "H5Pget_shared_mesg_index"); } /* Check list-to-btree and btree-to-list values */ ret = H5Pget_shared_mesg_phase_change(fcpl_id, &list_size, &btree_size); CHECK_I(ret, "H5Pset_shared_mesg_phase_change"); VERIFY(list_size, l2b, "H5Pset_shared_mesg_phase_change"); VERIFY(btree_size, b2l, "H5Pset_shared_mesg_phase_change"); } /**************************************************************** ** ** test_sohm_fcpl(): Test File Creation Property Lists. ** ****************************************************************/ static void test_sohm_fcpl(void) { hid_t fid = -1; hid_t fcpl_id = -1; hid_t fcpl2_id = -1; unsigned x; char filename[NAME_BUF_SIZE]; herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing File Creation Properties for Shared Messages\n")); fcpl_id = H5Pcreate(H5P_FILE_CREATE); CHECK_I(fcpl_id, "H5Pcreate"); /* Verify fcpl values */ check_fcpl_values(fcpl_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L); /* Create a file with this fcpl and make sure that all the values can be * retrieved. */ h5_fixname(FILENAME, H5P_DEFAULT, filename, sizeof filename); fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); CHECK_I(fid, "H5Fcreate"); fcpl2_id = H5Fget_create_plist(fid); CHECK_I(fcpl2_id, "H5Fcreate"); /* Verify fcpl values */ check_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L); ret = H5Pclose(fcpl2_id); CHECK_I(ret, "H5Pclose"); /* Close and re-open the file. Make sure that fcpl values are still * correct. */ ret = H5Fclose(fid); CHECK_I(ret, "H5Fclose"); fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); CHECK_I(fid, "H5Fopen"); fcpl2_id = H5Fget_create_plist(fid); CHECK_I(ret, "H5Fcreate"); /* Verify fcpl values */ check_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L); /* Clean up */ ret = H5Pclose(fcpl2_id); CHECK_I(ret, "H5Pclose"); ret = H5Pclose(fcpl_id); CHECK_I(ret, "H5Pclose"); ret = H5Fclose(fid); CHECK_I(ret, "H5Fclose"); /* Start over with a non-default fcpl */ fcpl_id = H5Pcreate(H5P_FILE_CREATE); CHECK_I(fcpl_id, "H5Pcreate"); /* Set up index values */ ret = H5Pset_shared_mesg_nindexes(fcpl_id, TEST_NUM_INDEXES); CHECK_I(ret, "H5Pset_shared_mesg_nindexes"); for(x=1; x<=TEST_NUM_INDEXES; ++x) { ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x-1], test_minsizes[x-1]); CHECK_I(ret, "H5Pset_shared_mesg_index"); } ret = H5Pset_shared_mesg_phase_change(fcpl_id, TEST_L2B, TEST_B2L); CHECK_I(ret, "H5Pset_shared_mesg_phase_change"); check_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L); /* Use the fcpl to create a file and get it back again */ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); CHECK_I(fid, "H5Fcreate"); fcpl2_id = H5Fget_create_plist(fid); CHECK_I(fcpl2_id, "H5Fcreate"); /* Verify fcpl values */ check_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L); ret = H5Pclose(fcpl2_id); CHECK_I(ret, "H5Pclose"); /* Close and re-open the file. Make sure that fcpl values are still * correct. */ ret = H5Fclose(fid); CHECK_I(ret, "H5Fclose"); fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); CHECK_I(fid, "H5Fopen"); fcpl2_id = H5Fget_create_plist(fid); CHECK_I(ret, "H5Fcreate"); /* Verify fcpl values */ check_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L); /* Clean up */ ret = H5Pclose(fcpl2_id); CHECK_I(ret, "H5Pclose"); ret = H5Fclose(fid); CHECK_I(ret, "H5Fclose"); /* Test giving bogus values to H5P* functions */ H5E_BEGIN_TRY { /* Trying to set index 0 or an index higher than the current number * of indexes should fail. */ ret = H5Pset_shared_mesg_index(fcpl_id, 0, 0, 15 /* JAMES */); VERIFY(ret, -1, "H5Pset_shared_mesg_index"); ret = H5Pset_shared_mesg_index(fcpl_id, MAX_INDEXES + 1, 0, 15); VERIFY(ret, -1, "H5Pset_shared_mesg_index"); ret = H5Pset_shared_mesg_index(fcpl_id, TEST_NUM_INDEXES + 1, 0, 15); VERIFY(ret, -1, "H5Pset_shared_mesg_index"); /* Setting an unknown flag (all flags + 1) should fail */ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ALL_FLAG + 1, 15); VERIFY(ret, -1, "H5Pset_shared_mesg_index"); /* Try setting two different indexes to hold fill messages */ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_FILL_FLAG, 15 /* JAMES */); CHECK_I(ret, "H5Pset_shared_mesg_index"); ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_FILL_FLAG, 15 /* JAMES */); CHECK_I(ret, "H5Pset_shared_mesg_index"); fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); VERIFY(fid, -1, "H5Fcreate"); ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG, 15 /* JAMES */); CHECK_I(ret, "H5Pset_shared_mesg_index"); fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); VERIFY(fid, -1, "H5Fcreate"); /* Test list/btree cutoffs. We can set these to any positive value, * but if the list max is less than the btree min we'll get an error * when the file is created. */ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 12); VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change"); } H5E_END_TRY /* Actually, the list max can be exactly 1 greater than the * btree min, but no more. Also, the errors above shouldn't * have corrupted the fcpl, although we do need to reset the * second index that we changed above. */ ret = H5Pset_shared_mesg_index(fcpl_id, 2, test_type_flags[1], 15 /* JAMES */); CHECK_I(ret, "H5Pset_shared_mesg_index"); ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 11); CHECK_I(ret, "H5Pset_shared_mesg_phase_change"); fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); CHECK_I(fid, "H5Fcreate"); /* Clean up */ ret = H5Pclose(fcpl_id); CHECK_I(ret, "H5Pclose"); ret = H5Fclose(fid); CHECK_I(ret, "H5Fclose"); } /*------------------------------------------------------------------------- * Function: make_dtype_1 * * Purpose: Creates a complicated datatype for use in testing * shared object header messages. The important thing is that * the datatypes must take a lot of space to store on disk. * * Return: Success: datatype ID (should be closed by calling function) * Failure: negative * * Programmer: James Laird * Saturday, August 26, 2006 * * Modifications: * *------------------------------------------------------------------------- */ hid_t make_dtype_1() { hid_t dtype1_id = -1; hid_t str_id = -1; /* Create compound datatype. If the user asked for it, check hash value at each step */ if((dtype1_id = H5Tcreate( H5T_COMPOUND, sizeof(struct dtype1_struct)))<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i1",HOFFSET(struct dtype1_struct,i1),H5T_NATIVE_INT)<0) TEST_ERROR str_id = H5Tcopy(H5T_C_S1); if(H5Tset_size(str_id,(size_t) 10)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"vl_string",HOFFSET(dtype1_struct,str),str_id)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i2",HOFFSET(struct dtype1_struct,i2),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i3",HOFFSET(struct dtype1_struct,i3),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i4",HOFFSET(struct dtype1_struct,i4),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i5",HOFFSET(struct dtype1_struct,i5),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i6",HOFFSET(struct dtype1_struct,i6),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i7",HOFFSET(struct dtype1_struct,i7),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"i8",HOFFSET(struct dtype1_struct,i8),H5T_NATIVE_INT)<0) TEST_ERROR if(H5Tinsert(dtype1_id,"f1",HOFFSET(struct dtype1_struct,f1),H5T_NATIVE_FLOAT)<0) TEST_ERROR if(H5Tclose(str_id) < 0) TEST_ERROR return dtype1_id; error: H5E_BEGIN_TRY { H5Tclose(str_id); H5Tclose(dtype1_id); } H5E_END_TRY return -1; } /*------------------------------------------------------------------------- * Function: make_dtype_2 * * Purpose: Creates complicated datatypes for use in testing * shared object header messages. The important thing is that * the datatypes must take a lot of space to store on disk. * * If record_hash is true, uses fid to record hash values * of the intermediate datatypes in the global hash history * table. Otherwise, fid is ignored. * * Return: Success: datatype ID (should be closed by calling function) * Failure: negative * * Programmer: James Laird * Saturday, August 26, 2006 * * Modifications: * *------------------------------------------------------------------------- */ hid_t make_dtype_2() { hid_t dtype2_id = -1; hid_t enum_id= -1; hid_t int_id=-1; int x; hsize_t dims[] = {2, 1, 2, 4}; size_t size; /* Create an int with a strange precision */ if((int_id = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR if(H5Tset_precision(int_id, 24) < 0) TEST_ERROR /* Create an enumeration using that int */ if((enum_id = H5Tenum_create(int_id)) < 0) TEST_ERROR for(x=0; x= norm_oh_size) VERIFY(sohm_oh_size, 1, "H5Fclose"); if(sohm_oh_size != sohm_btree_oh_size) VERIFY(sohm_btree_oh_size, 1, "H5Fclose"); /* Both sohm files should be bigger than a normal file when empty. * It's hard to say whether a B-tree with no nodes allocated should be * smaller than a list with SOHM_HELPER_NUM_DTYPES elements. * JAMES: The sizes here shouldn't really be 1 */ if(sohm_empty_filesize <= norm_empty_filesize) VERIFY(sohm_empty_filesize, 1, "H5Fclose"); if(sohm_btree_empty_filesize <= norm_empty_filesize) VERIFY(sohm_btree_empty_filesize, 1, "H5Fclose"); /* When full, the sohm btree file should be smaller than the normal file. * The sohm list file should be at least as small, since it doesn't need the * overhead of a B-tree. */ if(sohm_btree_final_filesize >= norm_final_filesize) VERIFY(sohm_btree_final_filesize, 1, "H5Fclose"); if(sohm_final_filesize > sohm_btree_final_filesize) VERIFY(sohm_final_filesize, 1, "H5Fclose"); /* This shouldn't change even if we open and close the file */ if(sohm_btree_final_filesize2 >= norm_final_filesize2) VERIFY(sohm_btree_final_filesize2, 1, "H5Fclose"); if(sohm_final_filesize2 > sohm_btree_final_filesize2) VERIFY(sohm_final_filesize2, 1, "H5Fclose"); } /*------------------------------------------------------------------------- * Function: sohm_attr_helper * * Purpose: Given an fcpl, tests creating attributes with and without * committed datatypes. * * Programmer: James Laird * Thursday, November 30, 2006 * *------------------------------------------------------------------------- */ static void sohm_attr_helper(hid_t fcpl_id) { hid_t file_id; hid_t type_id; hid_t space_id; hid_t group_id; hid_t attr_id; hsize_t dims = 2; int wdata[2] = {7, 42}; int rdata[2]; herr_t ret; hsize_t x; /* Create a file using the fcpl */ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT); CHECK_I(file_id, "H5Fcreate"); /* Create a normal datatype and dataset */ type_id = H5Tcopy(H5T_NATIVE_INT); CHECK_I(type_id, "H5Tcopy"); space_id = H5Screate_simple(1, &dims, &dims); CHECK_I(space_id, "H5Screate_simple"); /* Create and verify an attribute on a group */ group_id = H5Gcreate(file_id, "group", 100); CHECK_I(group_id, "H5Gcreate"); attr_id = H5Acreate(group_id, "attribute", type_id, space_id, H5P_DEFAULT); CHECK_I(attr_id, "H5Acreate"); ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata); CHECK_I(ret, "H5Awrite"); /* Close the datatype and group */ ret = H5Tclose(type_id); CHECK_I(ret, "H5Tclose"); ret = H5Gclose(group_id); CHECK_I(ret, "H5Gclose"); /* Flush the file to force data to be written */ ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL); CHECK_I(ret, "H5Fflush"); /* Verify */ memset(rdata, 0, sizeof(rdata)); ret = H5Aread(attr_id, H5T_NATIVE_INT, rdata); CHECK_I(ret, "H5Aread"); for(x=0; x list_index_med.empty_size) VERIFY(norm_sizes.empty_size, 1, "h5_get_file_size"); if(list_index_med.empty_size != list_index_big.empty_size) VERIFY(list_index_med.empty_size, list_index_big.empty_size, "h5_get_file_size"); if(list_index_med.empty_size != btree_index.empty_size) VERIFY(list_index_med.empty_size, btree_index.empty_size, "h5_get_file_size"); if(list_index_med.empty_size != list_index_small.empty_size) VERIFY(list_index_med.empty_size, list_index_small.empty_size, "h5_get_file_size"); /* The files with indexes shouldn't be that much bigger than an * empty file. */ if(list_index_med.empty_size > norm_sizes.empty_size * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); /* Once one dataset has been created (with one of every kind of message), * the normal file should still be smallest. The very small list * btree_convert should be smaller than the B-tree since it has no * extra overhead. The small list should also be smaller than the B-tree. * The very large list should be much larger than anything else. */ if(norm_sizes.first_dset >= list_index_small.first_dset) VERIFY(norm_sizes.first_dset, 1, "h5_get_file_size"); if(list_index_small.first_dset >= btree_index.first_dset) VERIFY(list_index_small.first_dset, 1, "h5_get_file_size"); if(list_index_med.first_dset >= btree_index.first_dset) VERIFY(btree_index.first_dset, 1, "h5_get_file_size"); if(btree_index.first_dset >= list_index_big.first_dset) VERIFY(list_index_med.first_dset, 1, "h5_get_file_size"); /* Once a few copies of the same dataset have been created, the * very small list shouldn't have become a B-tree yet, so it should * be the smallest file. A larger list should be next, followed * by a B-tree, followed by a normal file, followed by a * list that is too large. */ if(list_index_small.dsets1 >= list_index_med.dsets1) VERIFY(btree_index.dsets1, 1, "h5_get_file_size"); if(list_index_med.dsets1 >= btree_index.dsets1) VERIFY(list_index_med.dsets1, 1, "h5_get_file_size"); if(btree_index.dsets1 >= norm_sizes.dsets1) VERIFY(btree_index.dsets1, 1, "h5_get_file_size"); if(norm_sizes.dsets1 >= list_index_big.dsets1) VERIFY(list_index_big.dsets1, 1, "h5_get_file_size"); /* The size gain should have been the same for each of the lists; * their overhead is fixed. The B-tree should have gained at least * as much, and the normal file more than that. */ if((list_index_small.dsets1 - list_index_small.first_dset) != (list_index_med.dsets1 - list_index_med.first_dset)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_med.dsets1 - list_index_med.first_dset) != (list_index_big.dsets1 - list_index_big.first_dset)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_big.dsets1 - list_index_big.first_dset) > (btree_index.dsets1 - btree_index.first_dset)) VERIFY(0, 1, "h5_get_file_size"); if((btree_index.dsets1 - btree_index.first_dset) >= (norm_sizes.dsets1 - norm_sizes.first_dset)) VERIFY(0, 1, "h5_get_file_size"); /* Once another kind of each message has been written, the very small list * should convert into a B-tree. Now the list should be smallest, then * the B-trees (although the converted B-tree file may be a little bigger), * then the normal file. The largest list may or may not be bigger than * the normal file. */ if(list_index_med.dsets2 >= btree_index.dsets2) VERIFY(list_index_med.dsets2, 1, "h5_get_file_size"); if(btree_index.dsets2 > list_index_small.dsets2) VERIFY(btree_index.dsets2, 1, "h5_get_file_size"); if(list_index_small.dsets2 >= norm_sizes.dsets2) VERIFY(btree_index.dsets2, 1, "h5_get_file_size"); /* If the small list (now a B-tree) is bigger than the existing B-tree, * it shouldn't be much bigger. * It seems that the small lists tends to be pretty big anyway. Allow * for it to have twice as much overhead. */ if(list_index_small.dsets2 > btree_index.dsets2 * OVERHEAD_ALLOWED * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); /* The lists should have grown the least since they share messages and * have no extra overhead. The normal file should have grown more than * either the lists or the B-tree. The B-tree may not have grown more * than the lists, depending on whether it needed to split nodes or not. */ if((list_index_med.dsets2 - list_index_med.dsets1) != (list_index_big.dsets2 - list_index_big.dsets1)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_big.dsets2 - list_index_big.dsets1) > (btree_index.dsets2 - btree_index.dsets1)) VERIFY(0, 1, "h5_get_file_size"); if((btree_index.dsets2 - btree_index.dsets1) >= (norm_sizes.dsets2 - norm_sizes.dsets1)) VERIFY(0, 1, "h5_get_file_size"); /* Interleaving the writes should have no effect on how the messages are * shared. No new messages should be written to the indexes, so the * sohm files will only get a little bit bigger. */ if(list_index_med.interleaved >= btree_index.interleaved) VERIFY(0, 1, "h5_get_file_size"); if(btree_index.interleaved > list_index_small.interleaved) VERIFY(0, 1, "h5_get_file_size"); if(list_index_small.interleaved >= norm_sizes.interleaved) VERIFY(0, 1, "h5_get_file_size"); /* The lists should still have grown the same amount. The converted * B-tree shouldn't have grown more than the index that was originally * a B-tree (although it might have grown less if there was extra free * space within the file). */ if((list_index_med.interleaved - list_index_med.dsets2) != (list_index_big.interleaved - list_index_big.dsets2)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_big.interleaved - list_index_big.dsets2) > (btree_index.interleaved - btree_index.dsets2)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_small.interleaved - list_index_small.dsets2) > (btree_index.interleaved - btree_index.dsets2)) VERIFY(0, 1, "h5_get_file_size"); if((btree_index.interleaved - btree_index.dsets2) >= (norm_sizes.interleaved - norm_sizes.dsets2)) VERIFY(0, 1, "h5_get_file_size"); /* After many attributes have been written, both the small and medium lists * should have become B-trees and be about the same size as the index * that started as a B-tree. * Add in OVERHEAD_ALLOWED as a fudge factor here, since the allocation * of file space can be hard to predict. */ if(btree_index.attrs1 > list_index_small.attrs1) VERIFY(0, 1, "h5_get_file_size"); if(btree_index.attrs1 > list_index_med.attrs1 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(list_index_med.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(list_index_small.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); /* Neither of the converted lists should be too much bigger than * the index that was originally a B-tree. */ if(list_index_small.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(list_index_med.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); /* The "normal" file should have had less overhead, so should gain less * size than any of the other indexes since none of these attribute * messages could be shared. The large list should have gained * less overhead than the B-tree indexes. */ if((norm_sizes.attrs1 - norm_sizes.interleaved) >= (list_index_big.attrs1 - list_index_big.interleaved)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_big.attrs1 - list_index_big.interleaved) >= (list_index_small.attrs1 - list_index_small.interleaved)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_small.attrs1 - list_index_small.interleaved) > (btree_index.attrs1 - btree_index.interleaved)) VERIFY(0, 1, "h5_get_file_size"); /* Writing another copy of each attribute shouldn't change the ordering * of sizes. The big list index is still too big to be smaller than a * normal file. The B-tree indexes should all be about the same size. */ if(btree_index.attrs2 > list_index_small.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(list_index_small.attrs2 > btree_index.attrs2 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(btree_index.attrs2 > list_index_med.attrs2 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(list_index_med.attrs2 > btree_index.attrs2 * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(list_index_med.attrs2 >= norm_sizes.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(list_index_big.attrs2 >= norm_sizes.attrs2) VERIFY(0, 1, "h5_get_file_size"); /* All of the B-tree indexes should have gained about the same amount * of space; at least as much as the list index and less than a normal * file. */ if((list_index_small.attrs2 - list_index_small.attrs1) > (btree_index.attrs2 - btree_index.attrs1)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_med.attrs2 - list_index_med.attrs1) > (btree_index.attrs2 - btree_index.attrs1)) VERIFY(0, 1, "h5_get_file_size"); if((list_index_big.attrs2 - list_index_big.attrs1) > (list_index_med.attrs2 - list_index_med.attrs1)) VERIFY(0, 1, "h5_get_file_size"); if((btree_index.attrs2 - btree_index.attrs1) >= (norm_sizes.attrs2 - norm_sizes.attrs1)) VERIFY(0, 1, "h5_get_file_size"); /* Done checking the first few files that use a single index. */ /* Start comparing other kinds of files with these "standard" * one-index files */ /* Check files with multiple indexes. */ /* These files should be larger when first created than one-index * files. */ if(mult_index_med.empty_size <= list_index_med.empty_size) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.empty_size != mult_index_med.empty_size) VERIFY(0, 1, "h5_get_file_size"); /* When the first dataset is written, they should grow quite a bit as * many different indexes must be created. */ if(mult_index_med.first_dset - mult_index_med.empty_size <= list_index_med.first_dset - list_index_med.empty_size) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.first_dset - mult_index_btree.empty_size <= btree_index.first_dset - btree_index.empty_size) VERIFY(0, 1, "h5_get_file_size"); /* Once that initial overhead is out of the way and the lists/btrees * have been created, files with more than one index should grow at * the same rate or slightly faster than files with just one index * and one heap. */ if(mult_index_med.dsets1 - mult_index_med.first_dset != list_index_med.dsets1 - list_index_med.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.dsets1 - mult_index_btree.first_dset != btree_index.dsets1 - btree_index.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_med.dsets2 - mult_index_med.dsets1 > (list_index_med.dsets2 - list_index_med.dsets1) * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_med.dsets2 - mult_index_med.dsets1 < list_index_med.dsets2 - list_index_med.dsets1) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.dsets2 - mult_index_btree.dsets1 > (btree_index.dsets2 - btree_index.dsets1) * OVERHEAD_ALLOWED) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.dsets2 - mult_index_btree.dsets1 < btree_index.dsets2 - btree_index.dsets1) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_med.interleaved - mult_index_med.dsets2 != list_index_med.interleaved - list_index_med.dsets2) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.interleaved - mult_index_btree.dsets2 != btree_index.interleaved - btree_index.dsets2) VERIFY(0, 1, "h5_get_file_size"); /* When all the attributes are added, only the index holding attributes * will become a B-tree. Skip the interleaved to attrs1 interval when * this happens because it's hard to predict exactly how much space this * will take. */ if(mult_index_med.attrs2 - mult_index_med.attrs1 != list_index_med.attrs2 - list_index_med.attrs1) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.attrs2 - mult_index_btree.attrs1 != btree_index.attrs2 - btree_index.attrs1) VERIFY(0, 1, "h5_get_file_size"); /* The final file size for both of the multiple index files should be * smaller than a normal file but bigger than any of the one-index files. */ if(mult_index_med.attrs2 >= norm_sizes.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.attrs2 >= norm_sizes.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_med.attrs2 * OVERHEAD_ALLOWED < btree_index.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(mult_index_btree.attrs2 * OVERHEAD_ALLOWED < btree_index.attrs2) VERIFY(0, 1, "h5_get_file_size"); /* Check files that don't share all messages. */ /* These files have three indexes like the files above, so they should be * the same size when created. */ if(share_some_med.empty_size != mult_index_med.empty_size) VERIFY(0, 1, "h5_get_file_size"); if(share_some_med.empty_size != share_some_btree.empty_size) VERIFY(0, 1, "h5_get_file_size"); /* When the first dataset is created, they should be not quite as big * as equivalent files that share all messages (since shared messages * have a little bit of overhead). */ if(share_some_med.first_dset >= mult_index_med.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.first_dset >= mult_index_btree.first_dset) VERIFY(0, 1, "h5_get_file_size"); /* The files that share some should have a growth rate in between * files that share all messages and normal files */ if(share_some_med.interleaved - share_some_med.first_dset <= mult_index_med.interleaved - mult_index_med.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_some_med.interleaved - share_some_med.first_dset >= norm_sizes.interleaved - norm_sizes.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.interleaved - share_some_btree.first_dset <= mult_index_btree.interleaved - mult_index_btree.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.interleaved - share_some_btree.first_dset >= norm_sizes.interleaved - norm_sizes.first_dset) VERIFY(0, 1, "h5_get_file_size"); /* Check the file that only stored gigantic messages in its second * index. Since no messages were that big, it should be identical * to the file with an empty index. */ if(share_some_btree.empty_size != share_some_toobig_index.empty_size) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.first_dset != share_some_toobig_index.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.dsets1 != share_some_toobig_index.dsets1) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.dsets2 != share_some_toobig_index.dsets2) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.interleaved != share_some_toobig_index.interleaved) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.attrs1 != share_some_toobig_index.attrs1) VERIFY(0, 1, "h5_get_file_size"); if(share_some_btree.attrs2 != share_some_toobig_index.attrs2) VERIFY(0, 1, "h5_get_file_size"); /* Check the file that shares even very tiny messages. Once messages * are written to it, it should gain a little space from sharing the * messages and lose a little space to overhead so that it's just slightly * smaller than a file that doesn't share tiny messages. * If the overhead increases or the size of messages decreases, these * numbers may be off. */ if(share_tiny_index.empty_size != type_space_index.empty_size) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.first_dset >= type_space_index.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.first_dset * OVERHEAD_ALLOWED < type_space_index.first_dset) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.dsets1 >= type_space_index.dsets1) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.dsets1 * OVERHEAD_ALLOWED < type_space_index.dsets1) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.dsets2 >= type_space_index.dsets2) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.dsets2 * OVERHEAD_ALLOWED < type_space_index.dsets2) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.interleaved >= type_space_index.interleaved) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.interleaved * OVERHEAD_ALLOWED < type_space_index.interleaved) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.attrs1 >= type_space_index.attrs1) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.attrs1 * OVERHEAD_ALLOWED < type_space_index.attrs1) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.attrs2 >= type_space_index.attrs2) VERIFY(0, 1, "h5_get_file_size"); if(share_tiny_index.attrs2 * OVERHEAD_ALLOWED < type_space_index.attrs2) VERIFY(0, 1, "h5_get_file_size"); } /**************************************************************** ** ** test_sohm(): Main Shared Object Header Message testing routine. ** ****************************************************************/ void test_sohm(void) { /* Output message about test being performed */ MESSAGE(5, ("Testing Shared Object Header Messages\n")); test_sohm_fcpl(); /* Test SOHMs and file creation plists */ test_sohm_size1(); /* Tests the sizes of files with one SOHM */ test_sohm_attrs(); /* Tests shared messages in attributes */ test_sohm_size2(0); /* Tests the sizes of files with multiple SOHMs */ test_sohm_size2(1); /* Tests the sizes of files with multiple SOHMs */ } /* test_sohm() */ /*------------------------------------------------------------------------- * Function: cleanup_sohm * * Purpose: Cleanup temporary test files * * Return: none * * Programmer: James Laird * October 9, 2006 * * Modifications: * *------------------------------------------------------------------------- */ void cleanup_sohm(void) { remove(FILENAME); }