mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
f813d1e5ce
* Correct publish path * Update clang-format to 17 (#4931) Also bump the clang-format GitHub actions to 17 * Committing clang-format changes
3778 lines
148 KiB
C
3778 lines
148 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* 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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Purpose: Test Shared Object Header Messages
|
|
*/
|
|
|
|
#include "testhdf5.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 */
|
|
|
|
/* Default SOHM values */
|
|
#define DEF_NUM_INDEXES 0
|
|
static const unsigned def_type_flags[H5O_SHMESG_MAX_NINDEXES] = {0, 0, 0, 0, 0, 0};
|
|
static const unsigned def_minsizes[H5O_SHMESG_MAX_NINDEXES] = {250, 250, 250, 250, 250, 250};
|
|
#define DEF_L2B 50
|
|
#define DEF_B2L 40
|
|
|
|
/* Non-default SOHM values for testing */
|
|
#define TEST_NUM_INDEXES 4
|
|
static const unsigned test_type_flags[H5O_SHMESG_MAX_NINDEXES] = {H5O_SHMESG_FILL_FLAG,
|
|
H5O_SHMESG_DTYPE_FLAG |
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_PLINE_FLAG,
|
|
0,
|
|
0};
|
|
static const unsigned test_minsizes[H5O_SHMESG_MAX_NINDEXES] = {0, 2, 40, 100, 3, 1000};
|
|
#define TEST_L2B 65
|
|
#define TEST_B2L 64
|
|
|
|
#define FILENAME "tsohm.h5"
|
|
#define FILENAME_SRC "tsohm_src.h5"
|
|
#define FILENAME_DST "tsohm_dst.h5"
|
|
|
|
#define NAME_BUF_SIZE 512
|
|
|
|
/* How much overhead counts as "not much" when converting B-trees, etc. */
|
|
#define OVERHEAD_ALLOWED 1.15F
|
|
|
|
#define NUM_DATASETS 10
|
|
#define NUM_ATTRIBUTES 100
|
|
|
|
typedef struct dtype1_struct {
|
|
int i1;
|
|
char str[10];
|
|
int i2;
|
|
int i3;
|
|
int i4;
|
|
int i5;
|
|
int i6;
|
|
int i7;
|
|
int i8;
|
|
float f1;
|
|
} dtype1_struct;
|
|
|
|
#define DTYPE2_SIZE 1024
|
|
static const char *DSETNAME[] = {"dataset0", "dataset1", "dataset2", "dataset3", "dataset4",
|
|
"dataset5", "dataset6", "dataset7", "dataset8", "dataset9",
|
|
"dataset10", "dataset11", NULL};
|
|
static 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
|
|
static 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};
|
|
static 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 6
|
|
#define SIZE2_RANK2 10
|
|
#define SIZE2_DIMS \
|
|
{ \
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 \
|
|
}
|
|
|
|
#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 second_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;
|
|
|
|
/* Number of distinct messages for the sohm_delete test */
|
|
#define DELETE_NUM_MESGS 7
|
|
#define HALF_DELETE_NUM_MESGS 3
|
|
#define DELETE_DIMS \
|
|
{ \
|
|
1, 1, 1, 1, 1, 1, 1 \
|
|
}
|
|
#define DELETE_MIN_MESG_SIZE 10
|
|
#define DELETE_MAX_MESG_SIZE 60
|
|
|
|
/* Number of dimensions in extend_dset test */
|
|
#define EXTEND_NDIMS 2
|
|
|
|
/* Dimensions for external_dtype test */
|
|
#define NX 10
|
|
#define NY 10
|
|
|
|
/* Helper function prototypes */
|
|
static hid_t make_dtype_1(void);
|
|
static hid_t make_dtype_2(void);
|
|
static hid_t close_reopen_file(hid_t file, const char *filename, hid_t fapl_id);
|
|
static void test_sohm_attrs(void);
|
|
#ifdef NOT_NOW
|
|
static void size2_dump_struct(const char *name, size2_helper_struct *sizes);
|
|
#endif /* NOT_NOW */
|
|
static void size2_verify(void);
|
|
static void test_sohm_delete(void);
|
|
static void test_sohm_delete_revert(void);
|
|
static void test_sohm_extlink(void);
|
|
|
|
/****************************************************************
|
|
**
|
|
** verify_fcpl_values(): Verifies that FCPL is set as expected.
|
|
**
|
|
****************************************************************/
|
|
static void
|
|
verify_fcpl_values(hid_t fcpl_id, const unsigned nindexes_expected, const unsigned *flags_expected,
|
|
const unsigned *minsizes_expected, unsigned l2b, unsigned b2l)
|
|
{
|
|
unsigned nindexes_actual;
|
|
unsigned list_size;
|
|
unsigned btree_size;
|
|
unsigned x;
|
|
herr_t ret;
|
|
|
|
/* Number of indexes */
|
|
ret = H5Pget_shared_mesg_nindexes(fcpl_id, &nindexes_actual);
|
|
CHECK_I(ret, "H5Pget_shared_mesg_nindexes");
|
|
VERIFY(nindexes_actual, nindexes_expected, "H5Pget_shared_mesg_nindexes");
|
|
|
|
/* Index flags and minsizes */
|
|
for (x = 0; x < nindexes_actual; ++x) {
|
|
unsigned flags_i;
|
|
unsigned min_mesg_size;
|
|
ret = H5Pget_shared_mesg_index(fcpl_id, x, &flags_i, &min_mesg_size);
|
|
CHECK_I(ret, "H5Pget_shared_mesg_index");
|
|
VERIFY(flags_i, flags_expected[x], "H5Pget_shared_mesg_index");
|
|
VERIFY(min_mesg_size, minsizes_expected[x], "H5Pget_shared_mesg_index");
|
|
}
|
|
|
|
/* 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");
|
|
} /* verify_fcpl_values */
|
|
|
|
/****************************************************************
|
|
**
|
|
** test_sohm_fcpl(): Test File Creation Property Lists.
|
|
**
|
|
****************************************************************/
|
|
static void
|
|
test_sohm_fcpl(void)
|
|
{
|
|
hid_t fid = H5I_INVALID_HID;
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
hid_t fcpl2_id = H5I_INVALID_HID;
|
|
unsigned x;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing File Creation Properties for Shared Messages\n"));
|
|
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
|
|
verify_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.
|
|
*/
|
|
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(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(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 = 0; x < TEST_NUM_INDEXES; ++x) {
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x], test_minsizes[x]);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
} /* end for */
|
|
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, TEST_L2B, TEST_B2L);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
verify_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(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(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");
|
|
|
|
/* Actually, the list max can be exactly 1 greater than the
|
|
* btree min, but no more.
|
|
* Reset the second index.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, test_type_flags[1], 15);
|
|
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");
|
|
ret = H5Fclose(fid);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Test edge cases:
|
|
* H5O_SHMESG_MAX_NINDEXES and H5O_SHMESG_MAX_LIST_SIZE should be valid
|
|
* values.
|
|
* Creating a file with uninitialized indexes should work. (TODO: not implemented?)
|
|
*/
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, H5O_SHMESG_MAX_NINDEXES);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE, H5O_SHMESG_MAX_LIST_SIZE);
|
|
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");
|
|
} /* test_sohm_fcpl */
|
|
|
|
/****************************************************************
|
|
**
|
|
** test_sohm_fcpl_errors(): Test bogus FCPL settings for SOHMs
|
|
**
|
|
****************************************************************/
|
|
static void
|
|
test_sohm_fcpl_errors(void)
|
|
{
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
hid_t fid = H5I_INVALID_HID;
|
|
unsigned x;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing bogus file creation properties for shared messages\n"));
|
|
|
|
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 = 0; x < TEST_NUM_INDEXES; ++x) {
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x], test_minsizes[x]);
|
|
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");
|
|
|
|
verify_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
|
|
|
|
H5E_BEGIN_TRY
|
|
{
|
|
/* Trying to create too many indexes should fail */
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, H5O_SHMESG_MAX_NINDEXES + 1);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_nindexes");
|
|
|
|
/* Trying to set index to an index higher than the current number
|
|
* of indexes should fail.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, H5O_SHMESG_MAX_NINDEXES, 0, 15);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, TEST_NUM_INDEXES, 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_SHMESG_ALL_FLAG + 1, 15);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_index");
|
|
|
|
/* Try setting two different indexes to hold fill messages. They
|
|
* should hold even very small messages for testing, even though we
|
|
* wouldn't really want to share such tiny messages in the real world.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_FILL_FLAG, 15);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_FILL_FLAG, 15);
|
|
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, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 15);
|
|
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");
|
|
/* Setting them to extremely large values should also fail */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE + 1, 0);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, H5O_SHMESG_MAX_LIST_SIZE + 10);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
|
|
ret =
|
|
H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE, H5O_SHMESG_MAX_LIST_SIZE + 1);
|
|
VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
|
|
}
|
|
H5E_END_TRY
|
|
} /* test_sohm_fcpl_errors */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hid_t
|
|
make_dtype_1(void)
|
|
{
|
|
hid_t dtype1_id = H5I_INVALID_HID;
|
|
hid_t str_id = H5I_INVALID_HID;
|
|
|
|
/* Create compound datatype. */
|
|
if ((dtype1_id = H5Tcreate(H5T_COMPOUND, sizeof(struct dtype1_struct))) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Tinsert(dtype1_id, "i1", HOFFSET(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, "string", HOFFSET(dtype1_struct, str), str_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i2", HOFFSET(dtype1_struct, i2), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i3", HOFFSET(dtype1_struct, i3), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i4", HOFFSET(dtype1_struct, i4), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i5", HOFFSET(dtype1_struct, i5), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i6", HOFFSET(dtype1_struct, i6), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i7", HOFFSET(dtype1_struct, i7), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "i8", HOFFSET(dtype1_struct, i8), H5T_NATIVE_INT) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tinsert(dtype1_id, "f1", HOFFSET(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;
|
|
} /* make_dtype1 */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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.
|
|
*
|
|
* Return: Success: datatype ID (should be closed by calling function)
|
|
* Failure: negative
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hid_t
|
|
make_dtype_2(void)
|
|
{
|
|
hid_t dtype2_id = H5I_INVALID_HID;
|
|
hid_t enum_id = H5I_INVALID_HID;
|
|
hid_t int_id = H5I_INVALID_HID;
|
|
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, (size_t)24) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create an enumeration using that int */
|
|
if ((enum_id = H5Tenum_create(int_id)) < 0)
|
|
TEST_ERROR;
|
|
|
|
for (x = 0; x < ENUM_NUM_MEMBS; x++)
|
|
if (H5Tenum_insert(enum_id, ENUM_NAME[x], &ENUM_VAL[x]) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create arrays of arrays of arrays of enums */
|
|
if ((dtype2_id = H5Tarray_create2(enum_id, 3, dims)) < 0)
|
|
TEST_ERROR;
|
|
if ((dtype2_id = H5Tarray_create2(dtype2_id, 4, dims)) < 0)
|
|
TEST_ERROR;
|
|
if ((dtype2_id = H5Tarray_create2(dtype2_id, 2, dims)) < 0)
|
|
TEST_ERROR;
|
|
if ((dtype2_id = H5Tarray_create2(dtype2_id, 1, dims)) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (H5Tclose(enum_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tclose(int_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Check the datatype size. If this is different than the #defined
|
|
* size then the fills values will have the wrong size.
|
|
*/
|
|
size = H5Tget_size(dtype2_id);
|
|
if (size != DTYPE2_SIZE)
|
|
TEST_ERROR;
|
|
|
|
return dtype2_id;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Tclose(dtype2_id);
|
|
H5Tclose(enum_id);
|
|
H5Tclose(int_id);
|
|
}
|
|
H5E_END_TRY
|
|
return -1;
|
|
} /* make_dtype2 */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: close_reopen_file
|
|
*
|
|
* Purpose: Closes a file and then reopens it. Used to ensure that
|
|
* SOHMs are written to and read from disk
|
|
*
|
|
* Return: Success: new hid_t for the file
|
|
* Failure: Negative
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hid_t
|
|
close_reopen_file(hid_t file, const char *filename, hid_t fapl_id)
|
|
{
|
|
if (H5Fclose(file) < 0)
|
|
FAIL_STACK_ERROR;
|
|
file = H5Fopen(filename, H5F_ACC_RDWR, fapl_id);
|
|
if (file < 0)
|
|
FAIL_STACK_ERROR;
|
|
return (file);
|
|
|
|
error:
|
|
return -1;
|
|
} /* close_reopen_file */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size1_helper
|
|
*
|
|
* Purpose: Creates object headers that use a large datatype message.
|
|
*
|
|
* Set test_file_closing to true to add file closing and reopening
|
|
* whenever possible (to test that SOHMs are written correctly
|
|
* on disk and not just in memory).
|
|
*
|
|
* Return: Success: file ID (may not be the same one passed in)
|
|
* Failure: H5I_INVALID_HID
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hid_t
|
|
size1_helper(hid_t file, const char *filename, hid_t fapl_id, bool test_file_closing)
|
|
{
|
|
dtype1_struct wdata;
|
|
dtype1_struct rdata;
|
|
hid_t dtype1_id = H5I_INVALID_HID;
|
|
hid_t space_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hsize_t dim1[1];
|
|
int x;
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* Macro: TSOHM_S1H_VERIFY_DATA
|
|
*
|
|
* Purpose: Encapsulate a common pattern:
|
|
* Reads the dataset and verifies that [a subset of] the data
|
|
* are as expected.
|
|
*
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
*/
|
|
#define TSOHM_S1H_VERIFY_DATA(dset_id, dtype_id) \
|
|
{ \
|
|
memset(&rdata, 0, sizeof(rdata)); \
|
|
if (0 > H5Dread((dset_id), (dtype_id), H5S_ALL, H5S_ALL, H5P_DEFAULT, &rdata)) { \
|
|
H5_FAILED(); \
|
|
AT(); \
|
|
printf("Can't read data\n"); \
|
|
goto error; \
|
|
} \
|
|
if ((rdata.i1 != wdata.i1) || (rdata.i2 != wdata.i2) || strcmp(rdata.str, wdata.str) != 0) { \
|
|
H5_FAILED(); \
|
|
AT(); \
|
|
printf("incorrect read data\n"); \
|
|
goto error; \
|
|
} \
|
|
} /* TSOHM_S1H_VERIFY_DATA() definition */
|
|
|
|
/* Closing and re-opening the file takes a long time on systems without
|
|
* local disks. Don't close and reopen if express testing is enabled.
|
|
*/
|
|
if (h5_get_testexpress() > 1)
|
|
test_file_closing = false;
|
|
|
|
/* Initialize wdata */
|
|
memset(&wdata, 0, sizeof(wdata));
|
|
wdata.i1 = 11;
|
|
strcpy(wdata.str, "string");
|
|
wdata.i2 = 22;
|
|
wdata.i3 = 33;
|
|
wdata.i4 = 44;
|
|
wdata.i5 = 55;
|
|
wdata.i6 = 66;
|
|
wdata.i7 = 77;
|
|
wdata.i8 = 88;
|
|
wdata.f1 = 0.0F;
|
|
|
|
/* Initialize rdata */
|
|
memset(&rdata, 0, sizeof(rdata));
|
|
|
|
dtype1_id = make_dtype_1();
|
|
if (dtype1_id < 0)
|
|
TEST_ERROR;
|
|
|
|
dim1[0] = 1;
|
|
space_id = H5Screate_simple(1, dim1, NULL);
|
|
if (space_id < 0)
|
|
TEST_ERROR;
|
|
|
|
dset_id = H5Dcreate2(file, DSETNAME[0], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
if (dset_id < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Test writing and reading */
|
|
if (H5Dwrite(dset_id, dtype1_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata) < 0)
|
|
FAIL_STACK_ERROR;
|
|
TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
|
|
if (H5Dclose(dset_id) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
if (test_file_closing)
|
|
if ((file = close_reopen_file(file, filename, fapl_id)) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create 3 more datasets with the same datatype/dataspace */
|
|
for (x = 1; x < 4; x++) {
|
|
dset_id = H5Dcreate2(file, DSETNAME[x], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
if (0 > dset_id)
|
|
FAIL_STACK_ERROR;
|
|
if (x == 3)
|
|
if (H5Dwrite(dset_id, dtype1_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata) < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(dset_id) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
if (test_file_closing)
|
|
if ((file = close_reopen_file(file, filename, fapl_id)) < 0)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
if (H5Tclose(dtype1_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Make sure the data has been written successfully */
|
|
dset_id = H5Dopen2(file, DSETNAME[0], H5P_DEFAULT);
|
|
if (dset_id < 0)
|
|
TEST_ERROR;
|
|
dtype1_id = H5Dget_type(dset_id);
|
|
if (dtype1_id < 0)
|
|
TEST_ERROR;
|
|
TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
|
|
|
|
if (H5Dclose(dset_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Create several copies of the dataset
|
|
* this increases the amount of space saved by sharing the datatype message
|
|
*/
|
|
for (x = 0; x < SOHM_HELPER_NUM_EX_DSETS; x++) {
|
|
dset_id =
|
|
H5Dcreate2(file, EXTRA_DSETNAME[x], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
if (dset_id < 0)
|
|
TEST_ERROR;
|
|
if (H5Dclose(dset_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
if (test_file_closing)
|
|
if ((file = close_reopen_file(file, filename, fapl_id)) < 0)
|
|
TEST_ERROR;
|
|
}
|
|
|
|
if (H5Tclose(dtype1_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Sclose(space_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
/* Ensure that we can still read data back from dataset 3 */
|
|
dset_id = H5Dopen2(file, DSETNAME[3], H5P_DEFAULT);
|
|
if (dset_id < 0)
|
|
TEST_ERROR;
|
|
dtype1_id = H5Dget_type(dset_id);
|
|
if (dtype1_id < 0)
|
|
TEST_ERROR;
|
|
TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
|
|
|
|
if (H5Dclose(dset_id) < 0)
|
|
TEST_ERROR;
|
|
if (H5Tclose(dtype1_id) < 0)
|
|
TEST_ERROR;
|
|
|
|
return file;
|
|
|
|
error:
|
|
H5E_BEGIN_TRY
|
|
{
|
|
H5Sclose(space_id);
|
|
H5Tclose(dtype1_id);
|
|
H5Dclose(dset_id);
|
|
H5Fclose(file);
|
|
}
|
|
H5E_END_TRY
|
|
|
|
return H5I_INVALID_HID;
|
|
#undef TSOHM_S1H_VERIFY_DATA /* macro is exclusive to this function */
|
|
} /* size1_helper */
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function: getsize_testsize1
|
|
*
|
|
* Purpose: Creates a test file, populates it, and returns its file size.
|
|
* Object header information from the "first" dataset in the file
|
|
* is stored in pointer `oinfo`.
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static h5_stat_size_t
|
|
getsize_testsize1(const char *filename, hid_t fcpl_id, hid_t fapl_id, bool test_file_closing,
|
|
H5O_native_info_t *ninfo)
|
|
{
|
|
hid_t fid = H5I_INVALID_HID;
|
|
herr_t ret;
|
|
|
|
fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, fapl_id);
|
|
CHECK(fid, H5I_INVALID_HID, "H5Fcreate");
|
|
|
|
/* If test_file_closing is true, you will get back a different ID,
|
|
* which will need to be closed. The helper will close your passed-in
|
|
* ID.
|
|
*/
|
|
fid = size1_helper(fid, filename, fapl_id, test_file_closing);
|
|
CHECK(fid, H5I_INVALID_HID, "size1_helper");
|
|
|
|
ret = H5Oget_native_info_by_name(fid, DSETNAME[0], ninfo, H5O_NATIVE_INFO_HDR, H5P_DEFAULT);
|
|
CHECK(ret, FAIL, "H5Oget_native_info_by_name");
|
|
|
|
ret = H5Fclose(fid);
|
|
CHECK(ret, FAIL, "H5Fclose");
|
|
|
|
return h5_get_file_size(filename, fapl_id);
|
|
} /* getsize_testsize1() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_size1
|
|
*
|
|
* Purpose: Tests shared object header messages with a large datatype
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_size1(void)
|
|
{
|
|
hid_t file = H5I_INVALID_HID;
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
|
|
unsigned use_shared = 0;
|
|
unsigned use_btree = 0;
|
|
h5_stat_size_t file_sizes[9];
|
|
unsigned size_index = 0;
|
|
hsize_t oh_sizes[3];
|
|
unsigned oh_size_index = 0;
|
|
|
|
#if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
|
|
hsize_t norm_oh_size;
|
|
#endif /* Jira HDFFV-10646 */
|
|
hsize_t sohm_oh_size;
|
|
hsize_t sohm_btree_oh_size;
|
|
h5_stat_size_t norm_empty_filesize;
|
|
h5_stat_size_t sohm_empty_filesize;
|
|
h5_stat_size_t sohm_btree_empty_filesize;
|
|
h5_stat_size_t norm_final_filesize;
|
|
h5_stat_size_t sohm_final_filesize;
|
|
h5_stat_size_t sohm_btree_final_filesize;
|
|
h5_stat_size_t norm_final_filesize2;
|
|
h5_stat_size_t sohm_final_filesize2;
|
|
h5_stat_size_t sohm_btree_final_filesize2;
|
|
|
|
H5O_native_info_t ninfo;
|
|
unsigned num_indexes = 1;
|
|
unsigned index_flags = H5O_SHMESG_DTYPE_FLAG;
|
|
unsigned min_mesg_size = 50;
|
|
unsigned list_max = 11;
|
|
unsigned btree_min = 10;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing that shared datatypes save space\n"));
|
|
|
|
/* Create a FAPL with "semi" close degree, to detect dangling IDs */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
CHECK_I(fapl_id, "H5Pcreate");
|
|
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
|
CHECK_I(ret, "H5Pset_fclose_degree");
|
|
|
|
/* ----------------------------------------
|
|
* Run operations, accumulating file sizes to compare later.
|
|
*/
|
|
|
|
for (use_shared = 0; use_shared < 2; use_shared++) {
|
|
for (use_btree = 0; use_btree < 2; use_btree++) {
|
|
bool test_open_close;
|
|
|
|
/* cannot use btree indexing without shared messages; skip case */
|
|
if (use_btree && !use_shared)
|
|
continue;
|
|
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
|
|
if (use_shared) {
|
|
/* Tests one index holding only datatype messages */
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, index_flags, min_mesg_size);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
if (use_btree) {
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
}
|
|
else {
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, list_max, btree_min);
|
|
}
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
}
|
|
else {
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
}
|
|
|
|
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
|
|
CHECK_I(file, "H5Fcreate");
|
|
ret = H5Fclose(file);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* size of empty file */
|
|
file_sizes[size_index++] = h5_get_file_size(FILENAME, fapl_id);
|
|
|
|
/* size of populated file, with different populating behaviors */
|
|
test_open_close = true;
|
|
file_sizes[size_index++] = getsize_testsize1(FILENAME, fcpl_id, fapl_id, test_open_close, &ninfo);
|
|
test_open_close = false;
|
|
file_sizes[size_index++] = getsize_testsize1(FILENAME, fcpl_id, fapl_id, test_open_close, &ninfo);
|
|
oh_sizes[oh_size_index++] = ninfo.hdr.space.total;
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* for btree/listed messages */
|
|
} /* for normal/shared messages */
|
|
|
|
ret = H5Pclose(fapl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* sanity-check state of arrays */
|
|
VERIFY(9, size_index, "size_index");
|
|
VERIFY(3, oh_size_index, "oh_size_index");
|
|
|
|
/* ----------------------------------------
|
|
* Check that all sizes make sense.
|
|
*/
|
|
|
|
/* Put result sizes into human-readable symbolic names.
|
|
* Order dependent on loop execution above.
|
|
*/
|
|
norm_empty_filesize = file_sizes[0];
|
|
norm_final_filesize = file_sizes[1];
|
|
norm_final_filesize2 = file_sizes[2];
|
|
#if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
|
|
norm_oh_size = oh_sizes[0];
|
|
#endif /* Jira HDFFV-10646 */
|
|
|
|
sohm_empty_filesize = file_sizes[3];
|
|
sohm_final_filesize = file_sizes[4];
|
|
sohm_final_filesize2 = file_sizes[5];
|
|
sohm_oh_size = oh_sizes[1];
|
|
|
|
sohm_btree_empty_filesize = file_sizes[6];
|
|
sohm_btree_final_filesize = file_sizes[7];
|
|
sohm_btree_final_filesize2 = file_sizes[8];
|
|
sohm_btree_oh_size = oh_sizes[2];
|
|
|
|
/* How the SOHM messages are stored shouldn't affect the
|
|
* size of the object header.
|
|
*/
|
|
VERIFY(sohm_btree_oh_size, sohm_oh_size, "H5Oget_info_by_name");
|
|
|
|
#if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
|
|
/* Object headers in SOHM files should be smaller than normal object
|
|
* headers.
|
|
*/
|
|
if (sohm_oh_size >= norm_oh_size)
|
|
VERIFY(norm_oh_size, 1, "H5Oget_info_by_name");
|
|
#endif /* Jira HDFFV-10646 */
|
|
|
|
/* 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.
|
|
* The sizes here shouldn't really be 1; it's just used to ensure that the
|
|
* error code triggers.
|
|
*/
|
|
if (sohm_empty_filesize <= norm_empty_filesize)
|
|
VERIFY(sohm_empty_filesize, 1, "h5_get_file_size");
|
|
|
|
if (sohm_btree_empty_filesize <= norm_empty_filesize)
|
|
VERIFY(sohm_btree_empty_filesize, 1, "h5_get_file_size");
|
|
|
|
/* 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, "h5_get_file_size");
|
|
if (sohm_final_filesize > sohm_btree_final_filesize)
|
|
VERIFY(sohm_final_filesize, 1, "h5_get_file_size");
|
|
|
|
/* Comparative sizes 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, "h5_get_file_size");
|
|
if (sohm_final_filesize2 > sohm_btree_final_filesize2)
|
|
VERIFY(sohm_final_filesize2, 1, "h5_get_file_size");
|
|
|
|
} /* test_sohm_size1 */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: test_sohm_size_consistency_open_create
|
|
*
|
|
* Purpose: Tests that header size is different depending on file open
|
|
* procedure?
|
|
* Uses "size1_helper" for file setup directed to a specific
|
|
* file handle.
|
|
*
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
#if 0 /* TODO: REVEALS BUG TO BE FIXED - SEE JIRA HDFFV-10645 */
|
|
static void
|
|
test_sohm_size_consistency_open_create(void)
|
|
{
|
|
hid_t file = H5I_INVALID_HID;
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
unsigned use_btree;
|
|
hsize_t oh_size_open;
|
|
hsize_t oh_size_create;
|
|
H5O_native_info_t oinfo;
|
|
unsigned num_indexes = 1;
|
|
unsigned index_flags = H5O_SHMESG_DTYPE_FLAG;
|
|
unsigned min_mesg_size = 50;
|
|
unsigned list_max = 11;
|
|
unsigned btree_min = 10;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, \
|
|
("Testing that header size is consistent between H5Fopen and H5Fcreate\n"));
|
|
|
|
/* Create a FAPL with "semi" close degree, to detect dangling IDs */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
CHECK_I(fapl_id, "H5Pcreate");
|
|
ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
|
|
CHECK_I(ret, "H5Pset_fclose_degree");
|
|
|
|
for (use_btree = 0; use_btree < 2; use_btree++) {
|
|
/* Create FCPL with SOHMs enabled
|
|
*/
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, index_flags, min_mesg_size);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
if (use_btree) {
|
|
MESSAGE(5, ("----testing with btree index----\n"));
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
} else {
|
|
MESSAGE(5, ("----testing with normal index----\n"));
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, list_max, btree_min);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
}
|
|
|
|
/* Create empty file */
|
|
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
|
|
CHECK_I(file, "H5Fcreate");
|
|
ret = H5Fclose(file);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Test Open/Write
|
|
* Add messages to previously-created file */
|
|
file = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_id);
|
|
CHECK_I(file, "H5Fopen");
|
|
file = size1_helper(file, FILENAME, fapl_id, false);
|
|
CHECK_I(file, "size1_helper");
|
|
|
|
/* Get the size of a dataset object header */
|
|
ret = H5Oget_native_info_by_name(file, DSETNAME[0], &oinfo, H5O_NATIVE_INFO_HDR, H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Oget_native_info_by_name");
|
|
oh_size_open = oinfo.hdr.space.total;
|
|
|
|
ret = H5Fclose(file);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Test Create/Write
|
|
* Add messages to a newly-created file */
|
|
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
|
|
CHECK_I(file, "H5Fcreate");
|
|
file = size1_helper(file, FILENAME, fapl_id, false);
|
|
CHECK_I(file, "size1_helper");
|
|
|
|
/* Get the size of a dataset object header */
|
|
ret = H5Oget_native_info_by_name(file, DSETNAME[0], &oinfo, H5O_NATIVE_INFO_HDR, H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Oget_native_info_by_name");
|
|
oh_size_create = oinfo.hdr.space.total;
|
|
|
|
ret = H5Fclose(file);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
VERIFY(oh_size_create, oh_size_open, "H5Oget_info_by_name2");
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* for normal/btree indexing */
|
|
|
|
ret = H5Pclose(fapl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* test_sohm_size_consistency_open_create */
|
|
#endif /* Jira HDFFV-10645 */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: sohm_attr_helper
|
|
*
|
|
* Purpose: Given an fcpl, tests creating attributes with and without
|
|
* committed datatypes.
|
|
* Verify that an attribute can be written and read back.
|
|
* Tests attribute on a Group.
|
|
* Tests committed and non-committed datatypes.
|
|
* Tests attribute access through `H5Aopen()`.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
sohm_attr_helper(hid_t fcpl_id)
|
|
{
|
|
hid_t file_id;
|
|
hid_t space_id;
|
|
hsize_t dims = 2;
|
|
int wdata[2] = {7, 42};
|
|
int rdata[2];
|
|
herr_t ret;
|
|
size_t x;
|
|
unsigned op_index = 0;
|
|
#define TSOHM_SAH_OP_COUNT 3
|
|
const char *groupnames[TSOHM_SAH_OP_COUNT] = {
|
|
"group_for_nothing_special",
|
|
"group_for_commited_dtype",
|
|
"group_for_commited_dtype_and_other_ID_access",
|
|
};
|
|
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
space_id = H5Screate_simple(1, &dims, &dims);
|
|
CHECK_I(space_id, "H5Screate_simple");
|
|
|
|
/* loop:
|
|
* 0 - nothing special
|
|
* 1 - committed datatype
|
|
* 2 - committed datatype, read through second ID
|
|
*/
|
|
for (op_index = 0; op_index < TSOHM_SAH_OP_COUNT; op_index++) {
|
|
hid_t type_id = H5I_INVALID_HID;
|
|
hid_t group_id = H5I_INVALID_HID;
|
|
hid_t attr_id = H5I_INVALID_HID;
|
|
hid_t attr_id2 = H5I_INVALID_HID;
|
|
hid_t attr_read_id;
|
|
|
|
/* create group in file with name unique to op_index */
|
|
group_id = H5Gcreate2(file_id, groupnames[op_index], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gcreate2");
|
|
|
|
type_id = H5Tcopy(H5T_NATIVE_INT);
|
|
CHECK_I(type_id, "H5Tcopy");
|
|
|
|
/* Commit the datatype for the latter iterations.
|
|
* Only do this ONCE.
|
|
*/
|
|
if (op_index == 1) {
|
|
ret = H5Tcommit2(file_id, "datatype", type_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Tcommit2");
|
|
}
|
|
|
|
attr_id = H5Acreate2(group_id, "attribute", type_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
|
|
if (op_index == 2) {
|
|
/* Open the attribute to get another handle */
|
|
attr_id2 = H5Aopen(group_id, "attribute", H5P_DEFAULT);
|
|
CHECK_I(attr_id2, "H5Aopen");
|
|
}
|
|
|
|
ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Tclose(type_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
|
|
/* Flush the file to force data to be written */
|
|
ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
CHECK_I(ret, "H5Fflush");
|
|
|
|
/* Verify */
|
|
attr_read_id = (op_index == 2) ? attr_id2 : attr_id;
|
|
memset(rdata, 0, sizeof(rdata));
|
|
ret = H5Aread(attr_read_id, H5T_NATIVE_INT, rdata);
|
|
CHECK_I(ret, "H5Aread");
|
|
for (x = 0; x < (size_t)dims; ++x)
|
|
VERIFY(rdata[x], wdata[x], "H5Aread");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
if (attr_id2 > -1) {
|
|
ret = H5Aclose(attr_id2);
|
|
CHECK_I(ret, "H5Aclose");
|
|
}
|
|
} /* for each attribute operation */
|
|
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
#undef TSOHM_SAH_OP_COUNT
|
|
} /* sohm_attr_helper */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_attrs
|
|
*
|
|
* Purpose: Attributes can be shared and can also contain shared
|
|
* datatype and dataspace messages. Committed datatypes
|
|
* shouldn't be shared.
|
|
*
|
|
* Test permutations of this.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_attrs(void)
|
|
{
|
|
hid_t bad_fid = H5I_INVALID_HID;
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
unsigned i = 0;
|
|
#define TSOHM_TSA_NFLAGS_1 7
|
|
unsigned flags1[TSOHM_TSA_NFLAGS_1] = {
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
};
|
|
#define TSOHM_TSA_NFLAGS_2 6
|
|
unsigned flags2[TSOHM_TSA_NFLAGS_2][2] = {
|
|
{
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
},
|
|
};
|
|
#define TSOHM_TSA_NFLAGS_3 5
|
|
unsigned flags3[TSOHM_TSA_NFLAGS_3][3] = {
|
|
{
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
},
|
|
{
|
|
H5O_SHMESG_SDSPACE_FLAG,
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
},
|
|
{
|
|
0, /* first index does not hold a shared message type? */
|
|
H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
},
|
|
{
|
|
0, /* missing SDSPACE flag */
|
|
H5O_SHMESG_DTYPE_FLAG,
|
|
H5O_SHMESG_ATTR_FLAG,
|
|
},
|
|
};
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing that shared messages work with attributes\n"));
|
|
|
|
/* No shared messages
|
|
*/
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
sohm_attr_helper(fcpl_id);
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* One shared message index
|
|
*/
|
|
for (i = 0; i < TSOHM_TSA_NFLAGS_1; i++) {
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags1[i], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
sohm_attr_helper(fcpl_id);
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
}
|
|
|
|
/* two shared message indices
|
|
*/
|
|
for (i = 0; i < TSOHM_TSA_NFLAGS_2; i++) {
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags2[i][0], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, flags2[i][1], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
sohm_attr_helper(fcpl_id);
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
}
|
|
|
|
/* duplicate flags in separate indices causes problems
|
|
*/
|
|
H5E_BEGIN_TRY
|
|
{
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ATTR_FLAG, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_ATTR_FLAG, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
bad_fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
VERIFY(bad_fid, H5I_INVALID_HID, "H5Fcreate");
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
}
|
|
H5E_END_TRY
|
|
|
|
/* three shared message indices
|
|
*/
|
|
for (i = 0; i < TSOHM_TSA_NFLAGS_3; i++) {
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags3[i][0], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, flags3[i][1], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 2, flags3[i][2], 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
sohm_attr_helper(fcpl_id);
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
}
|
|
|
|
#undef TSOHM_TSA_NFLAGS_1
|
|
#undef TSOHM_TSA_NFLAGS_2
|
|
#undef TSOHM_TSA_NFLAGS_3
|
|
|
|
} /* test_sohm_attrs */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size2_verify_plist1
|
|
*
|
|
* Purpose: Verify that the property list passed in is in fact the
|
|
* same property list used as dcpl1_id in the size2 helper
|
|
* function. This ensures that the filters can be read.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
size2_verify_plist1(hid_t plist)
|
|
{
|
|
size_t cd_nelmts;
|
|
unsigned int cd_value;
|
|
char name[NAME_BUF_SIZE];
|
|
H5Z_filter_t filter;
|
|
hid_t dtype1_id;
|
|
dtype1_struct fill1;
|
|
dtype1_struct fill1_correct;
|
|
herr_t ret;
|
|
|
|
/* Hardcoded to correspond to dcpl1_id created in size2_helper */
|
|
/* Check filters */
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 0, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 1, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 1, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 2, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 3, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_FLETCHER32, "H5Pget_filter2");
|
|
|
|
/* Check fill value */
|
|
dtype1_id = make_dtype_1();
|
|
CHECK_I(dtype1_id, "make_dtype_1");
|
|
memset(&fill1_correct, '1', sizeof(fill1_correct));
|
|
|
|
ret = H5Pget_fill_value(plist, dtype1_id, &fill1);
|
|
CHECK_I(ret, "H5Pget_fill_value");
|
|
|
|
ret = memcmp(&fill1, &fill1_correct, sizeof(fill1_correct));
|
|
VERIFY(ret, 0, "memcmp");
|
|
|
|
ret = H5Tclose(dtype1_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
} /* size2_verify_plist1 */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size2_verify_plist2
|
|
*
|
|
* Purpose: Verify that the property list passed in is in fact the
|
|
* same property list used as dcpl2_id in the size2 helper
|
|
* function. This ensures that the filters can be read.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
size2_verify_plist2(hid_t plist)
|
|
{
|
|
size_t cd_nelmts;
|
|
unsigned int cd_value;
|
|
char name[NAME_BUF_SIZE];
|
|
H5Z_filter_t filter;
|
|
hid_t dtype2_id;
|
|
char fill2[DTYPE2_SIZE];
|
|
char fill2_correct[DTYPE2_SIZE];
|
|
herr_t ret;
|
|
|
|
/* Hardcoded to correspond to dcpl1_id created in size2_helper */
|
|
/* Check filters */
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 0, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 1, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 1, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 2, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 2, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 2, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 3, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 1, "H5Pget_filter2");
|
|
|
|
cd_nelmts = 1;
|
|
filter = H5Pget_filter2(plist, 4, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
|
|
CHECK_I(filter, "H5Pget_filter2");
|
|
VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
|
|
VERIFY(cd_value, 5, "H5Pget_filter2");
|
|
|
|
/* Check fill value */
|
|
dtype2_id = make_dtype_2();
|
|
CHECK_I(dtype2_id, "make_dtype_2");
|
|
memset(&fill2_correct, '2', (size_t)DTYPE2_SIZE);
|
|
|
|
ret = H5Pget_fill_value(plist, dtype2_id, &fill2);
|
|
CHECK_I(ret, "H5Pget_fill_value");
|
|
|
|
ret = memcmp(&fill2, &fill2_correct, (size_t)DTYPE2_SIZE);
|
|
VERIFY(ret, 0, "memcmp");
|
|
|
|
ret = H5Tclose(dtype2_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
} /* size2_verify_plist2 */
|
|
|
|
#ifdef NOT_NOW
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size2_dump_struct
|
|
*
|
|
* Purpose: A debugging function to print the contents of a
|
|
* size2_helper_struct (which holds the various sizes for a
|
|
* given file during the size2_helper function).
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
size2_dump_struct(const char *name, size2_helper_struct *sizes)
|
|
{
|
|
puts(name);
|
|
printf(" empty size: %llu\n", (unsigned long long)sizes->empty_size);
|
|
printf(" first dataset: %llu \tdelta: %llu\n", (unsigned long long)sizes->first_dset,
|
|
(unsigned long long)(sizes->first_dset - sizes->empty_size));
|
|
printf("second dataset: %llu \tdelta: %llu\n", (unsigned long long)sizes->second_dset,
|
|
(unsigned long long)(sizes->second_dset - sizes->first_dset));
|
|
printf(" dsets 1: %llu \tdelta: %llu\n", (unsigned long long)sizes->dsets1,
|
|
(unsigned long long)(sizes->dsets1 - sizes->second_dset));
|
|
printf(" dsets 2: %llu \tdelta: %llu\n", (unsigned long long)sizes->dsets2,
|
|
(unsigned long long)(sizes->dsets2 - sizes->dsets1));
|
|
printf(" interleaved: %llu \tdelta: %llu\n", (unsigned long long)sizes->interleaved,
|
|
(unsigned long long)(sizes->interleaved - sizes->dsets2));
|
|
printf(" attributes: %llu \tdelta: %llu\n", (unsigned long long)sizes->attrs1,
|
|
(unsigned long long)(sizes->attrs1 - sizes->interleaved));
|
|
printf(" attributes 2: %llu \tdelta: %llu\n", (unsigned long long)sizes->attrs2,
|
|
(unsigned long long)(sizes->attrs2 - sizes->attrs1));
|
|
} /* size2_dump_struct */
|
|
#endif /* NOT_NOW */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size2_helper
|
|
*
|
|
* Purpose: A helper function for test_sohm_size2.
|
|
*
|
|
* Creates a file using the given fcpl, then creates lots
|
|
* of different kinds of messages within the file and
|
|
* returns the size of the file for comparison.
|
|
*
|
|
* If test_file_closing is not zero, closes and re-opens
|
|
* the file after every write.
|
|
*
|
|
* Doesn't close the property list. Prints an error message
|
|
* if there's a failure, but doesn't alter its return value.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
size2_helper(hid_t fcpl_id, int test_file_closing, size2_helper_struct *ret_sizes)
|
|
{
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
hid_t dtype1_id = H5I_INVALID_HID;
|
|
hid_t dtype2_id = H5I_INVALID_HID;
|
|
hid_t dspace1_id = H5I_INVALID_HID;
|
|
hid_t dspace2_id = H5I_INVALID_HID;
|
|
hid_t dcpl1_id = H5I_INVALID_HID;
|
|
hid_t dcpl2_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t attr_type_id = H5I_INVALID_HID;
|
|
hid_t attr_space_id = H5I_INVALID_HID;
|
|
hid_t attr_id = H5I_INVALID_HID;
|
|
hid_t group_id = H5I_INVALID_HID;
|
|
char attr_string1[NAME_BUF_SIZE];
|
|
char attr_string2[NAME_BUF_SIZE];
|
|
char attr_name[NAME_BUF_SIZE];
|
|
int x;
|
|
herr_t ret;
|
|
|
|
/* Constants used in this function */
|
|
const int rank1 = SIZE2_RANK1;
|
|
const int rank2 = SIZE2_RANK2;
|
|
const hsize_t dims[SIZE2_RANK2] = SIZE2_DIMS;
|
|
dtype1_struct fill1;
|
|
char fill2[DTYPE2_SIZE];
|
|
|
|
/* Closing and re-opening the file takes a long time on systems without
|
|
* local disks. Don't close and reopen if express testing is enabled.
|
|
*/
|
|
if (h5_get_testexpress() > 1)
|
|
test_file_closing = 0;
|
|
|
|
/* Create a file and get its size */
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Get the file size */
|
|
ret_sizes->empty_size = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Re-open the file and set up messages to write */
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
|
|
/* Create two large datatype messages */
|
|
dtype1_id = make_dtype_1();
|
|
CHECK_I(dtype1_id, "make_dtype_1");
|
|
dtype2_id = make_dtype_2();
|
|
CHECK_I(dtype2_id, "make_dtype_2");
|
|
|
|
/* Create some large dataspaces */
|
|
dspace1_id = H5Screate_simple(rank1, dims, dims);
|
|
CHECK_I(dspace1_id, "H5Screate_simple");
|
|
dspace2_id = H5Screate_simple(rank2, dims, dims);
|
|
CHECK_I(dspace2_id, "H5Screate_simple");
|
|
|
|
/* fill1 and fill2 are fill values for the two datatypes.
|
|
* We'll set them in the DCPL.
|
|
*/
|
|
memset(&fill1, '1', sizeof(dtype1_struct));
|
|
memset(&fill2, '2', (size_t)DTYPE2_SIZE);
|
|
|
|
dcpl1_id = H5Pcreate(H5P_DATASET_CREATE);
|
|
CHECK_I(dcpl1_id, "H5Pcreate");
|
|
H5Pset_fill_value(dcpl1_id, dtype1_id, &fill1);
|
|
|
|
dcpl2_id = H5Pcreate(H5P_DATASET_CREATE);
|
|
CHECK_I(dcpl2_id, "H5Pcreate");
|
|
H5Pset_fill_value(dcpl2_id, dtype2_id, &fill2);
|
|
|
|
/* Filter messages we'll create by setting them in a DCPL. These
|
|
* values don't need to make sense, they just need to take up space.
|
|
*/
|
|
ret = H5Pset_chunk(dcpl1_id, rank1, dims);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
ret = H5Pset_shuffle(dcpl1_id);
|
|
CHECK_I(ret, "H5Pset_shuffle");
|
|
ret = H5Pset_deflate(dcpl1_id, 1);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
ret = H5Pset_shuffle(dcpl1_id);
|
|
CHECK_I(ret, "H5Pset_shuffle");
|
|
ret = H5Pset_fletcher32(dcpl1_id);
|
|
CHECK_I(ret, "H5Pset_fletcher32");
|
|
/* Make sure that this property list is what it should be */
|
|
size2_verify_plist1(dcpl1_id);
|
|
|
|
/* Second dcpl */
|
|
ret = H5Pset_chunk(dcpl2_id, rank2, dims);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
ret = H5Pset_deflate(dcpl2_id, 1);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
ret = H5Pset_deflate(dcpl2_id, 2);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
ret = H5Pset_deflate(dcpl2_id, 2);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
ret = H5Pset_deflate(dcpl2_id, 1);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
ret = H5Pset_deflate(dcpl2_id, 5);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
/* Make sure that this property list is what it should be */
|
|
size2_verify_plist2(dcpl2_id);
|
|
|
|
/* Set up attribute data */
|
|
memset(attr_string1, 0, (size_t)NAME_BUF_SIZE);
|
|
memset(attr_string2, 0, (size_t)NAME_BUF_SIZE);
|
|
strcpy(attr_string1, LONG_STRING);
|
|
strcpy(attr_string2, LONG_STRING);
|
|
attr_string2[1] = '1'; /* The second string starts "01 index..." */
|
|
|
|
/* Set up attribute metadata */
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
CHECK_I(attr_type_id, "H5Tcopy");
|
|
ret = H5Tset_size(attr_type_id, (size_t)NAME_BUF_SIZE);
|
|
CHECK_I(ret, "H5Tset_size");
|
|
attr_space_id = H5Screate_simple(1, dims, dims);
|
|
CHECK_I(attr_space_id, "H5Screate_simple");
|
|
|
|
/* Create datasets with a big datatype, dataspace, fill value,
|
|
* and filter pipeline.
|
|
*/
|
|
for (x = 0; x < NUM_DATASETS; ++x) {
|
|
dset_id = H5Dcreate2(file_id, DSETNAME[x], dtype1_id, dspace1_id, H5P_DEFAULT, dcpl1_id, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string1);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
|
|
/* Gather extra statistics on first two datasets in file */
|
|
if (x < 2) {
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Get the file's size now */
|
|
if (x == 0)
|
|
ret_sizes->first_dset = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
else
|
|
ret_sizes->second_dset = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
} /* end if */
|
|
/* Close & reopen file if requested */
|
|
else if (test_file_closing) {
|
|
file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
} /* end if */
|
|
} /* end for */
|
|
|
|
/* Close file and get its size now */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret_sizes->dsets1 = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Create new group filled with datasets that use all different messages */
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gcreate2(file_id, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gcreate2");
|
|
|
|
/* Create NUM_DATASETS datasets in the new group */
|
|
for (x = 0; x < NUM_DATASETS; ++x) {
|
|
dset_id =
|
|
H5Dcreate2(group_id, DSETNAME[x], dtype2_id, dspace2_id, H5P_DEFAULT, dcpl2_id, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string2);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
|
|
/* Close everything & reopen file if requested */
|
|
if (test_file_closing) {
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
}
|
|
}
|
|
|
|
/* Close file and get its size now */
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret_sizes->dsets2 = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Create a new group and interleave writes of datasets types 1 and 2. */
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gcreate2(file_id, "interleaved group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gcreate2");
|
|
|
|
/* Create NUM_DATASETS datasets in the new group */
|
|
for (x = 0; x < NUM_DATASETS; x += 2) {
|
|
dset_id =
|
|
H5Dcreate2(group_id, DSETNAME[x], dtype1_id, dspace1_id, H5P_DEFAULT, dcpl1_id, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string1);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
|
|
dset_id =
|
|
H5Dcreate2(group_id, DSETNAME[x + 1], dtype2_id, dspace2_id, H5P_DEFAULT, dcpl2_id, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string2);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
|
|
/* Close everything & reopen file if requested */
|
|
if (test_file_closing) {
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
}
|
|
}
|
|
|
|
/* Close file and get its size now */
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret_sizes->interleaved = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Create lots of new attribute messages on the group
|
|
* (using different strings for the attribute)
|
|
*/
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
|
|
strcpy(attr_name, "00 index");
|
|
|
|
for (x = 0; x < NUM_ATTRIBUTES; ++x) {
|
|
/* Create a unique name and value for each attribute */
|
|
attr_string1[0] = attr_name[0] = (char)((x / 10) + '0');
|
|
attr_string1[1] = attr_name[1] = (char)((x % 10) + '0');
|
|
|
|
/* Create an attribute on the group */
|
|
attr_id = H5Acreate2(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string1);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
|
|
/* Close everything & reopen file if requested */
|
|
if (test_file_closing) {
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
}
|
|
}
|
|
|
|
/* Close file and get its size now */
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret_sizes->attrs1 = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Create all of the attributes again on the other group */
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
|
|
for (x = 0; x < NUM_ATTRIBUTES; ++x) {
|
|
/* Create the same name and value for each attribute as before */
|
|
attr_string1[0] = attr_name[0] = (char)((x / 10) + '0');
|
|
attr_string1[1] = attr_name[1] = (char)((x % 10) + '0');
|
|
|
|
/* Create an attribute on the group */
|
|
attr_id = H5Acreate2(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, attr_type_id, attr_string1);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
|
|
/* Close everything & reopen file if requested */
|
|
if (test_file_closing) {
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
|
|
CHECK_I(group_id, "H5Gopen2");
|
|
}
|
|
}
|
|
/* Close file and get its size now */
|
|
ret = H5Gclose(group_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret_sizes->attrs2 = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Close everything */
|
|
ret = H5Sclose(attr_space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Tclose(attr_type_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Tclose(dtype1_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Tclose(dtype2_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Sclose(dspace1_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Sclose(dspace2_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Pclose(dcpl1_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
ret = H5Pclose(dcpl2_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
return 0;
|
|
} /* size2_helper */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: size2_verify
|
|
*
|
|
* Purpose: A helper function to verify the file created by size2_helper.
|
|
*
|
|
* Runs various tests (not exhaustive) to ensure that the
|
|
* file FILENAME actually has the structure that size2_helper
|
|
* should have created.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
size2_verify(void)
|
|
{
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t plist_id = H5I_INVALID_HID;
|
|
hid_t space_id = H5I_INVALID_HID;
|
|
hid_t group1_id, group2_id;
|
|
hid_t attr1_id, attr2_id;
|
|
hid_t attr_type_id;
|
|
int x, y;
|
|
herr_t ret;
|
|
char attr_string[NAME_BUF_SIZE];
|
|
char attr_correct_string[NAME_BUF_SIZE];
|
|
char attr_name[NAME_BUF_SIZE];
|
|
int ndims;
|
|
hsize_t dims[SIZE2_RANK2];
|
|
hsize_t correct_dims[SIZE2_RANK2] = SIZE2_DIMS;
|
|
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fopen");
|
|
|
|
/* Verify property lists and dataspaces */
|
|
|
|
/* Get property lists from first batch of datasets */
|
|
for (x = 0; x < NUM_DATASETS; ++x) {
|
|
dset_id = H5Dopen2(file_id, DSETNAME[x], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
plist_id = H5Dget_create_plist(dset_id);
|
|
CHECK_I(plist_id, "H5Dget_create_plist");
|
|
size2_verify_plist1(plist_id);
|
|
ret = H5Pclose(plist_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
space_id = H5Dget_space(dset_id);
|
|
CHECK_I(space_id, "H5Dget_space");
|
|
ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
|
|
CHECK_I(ndims, "H5Sget_simple_extent_dims");
|
|
VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
|
|
for (y = 0; y < ndims; ++y)
|
|
VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
|
|
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
}
|
|
|
|
/* Get property lists from second batch of datasets */
|
|
group1_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
|
|
CHECK_I(group1_id, "H5Gopen2");
|
|
for (x = 0; x < NUM_DATASETS; ++x) {
|
|
dset_id = H5Dopen2(group1_id, DSETNAME[x], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
plist_id = H5Dget_create_plist(dset_id);
|
|
CHECK_I(plist_id, "H5Dget_create_plist");
|
|
size2_verify_plist2(plist_id);
|
|
ret = H5Pclose(plist_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
space_id = H5Dget_space(dset_id);
|
|
CHECK_I(space_id, "H5Dget_space");
|
|
ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
|
|
CHECK_I(ndims, "H5Sget_simple_extent_dims");
|
|
VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
|
|
for (y = 0; y < ndims; ++y)
|
|
VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
|
|
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
} /* end for */
|
|
ret = H5Gclose(group1_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
|
|
/* Get property lists from interleaved group of datasets */
|
|
group1_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
|
|
CHECK_I(group1_id, "H5Gopen2");
|
|
for (x = 0; x < NUM_DATASETS; x += 2) {
|
|
/* First "type 1" dataset */
|
|
dset_id = H5Dopen2(group1_id, DSETNAME[x], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
plist_id = H5Dget_create_plist(dset_id);
|
|
CHECK_I(plist_id, "H5Dget_create_plist");
|
|
size2_verify_plist1(plist_id);
|
|
ret = H5Pclose(plist_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
space_id = H5Dget_space(dset_id);
|
|
CHECK_I(space_id, "H5Dget_space");
|
|
ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
|
|
CHECK_I(ndims, "H5Sget_simple_extent_dims");
|
|
VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
|
|
for (y = 0; y < ndims; ++y)
|
|
VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
|
|
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
|
|
/* Second "type 2" dataset */
|
|
dset_id = H5Dopen2(group1_id, DSETNAME[x + 1], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
plist_id = H5Dget_create_plist(dset_id);
|
|
CHECK_I(plist_id, "H5Dget_create_plist");
|
|
size2_verify_plist2(plist_id);
|
|
ret = H5Pclose(plist_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
space_id = H5Dget_space(dset_id);
|
|
CHECK_I(space_id, "H5Dget_space");
|
|
ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
|
|
CHECK_I(ndims, "H5Sget_simple_extent_dims");
|
|
VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
|
|
for (y = 0; y < ndims; ++y)
|
|
VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
|
|
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
} /* end for */
|
|
ret = H5Gclose(group1_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
|
|
/* Verify attributes */
|
|
|
|
/* Create attribute data type */
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
CHECK_I(attr_type_id, "H5Tcopy");
|
|
ret = H5Tset_size(attr_type_id, (size_t)NAME_BUF_SIZE);
|
|
CHECK_I(ret, "H5Tset_size");
|
|
|
|
/* Read attributes on both groups and verify that they are correct */
|
|
group1_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
|
|
CHECK_I(group1_id, "H5Gopen2");
|
|
group2_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
|
|
CHECK_I(group2_id, "H5Gopen2");
|
|
|
|
memset(attr_string, 0, (size_t)NAME_BUF_SIZE);
|
|
memset(attr_correct_string, 0, (size_t)NAME_BUF_SIZE);
|
|
strcpy(attr_correct_string, LONG_STRING);
|
|
strcpy(attr_name, "00 index");
|
|
|
|
for (x = 0; x < NUM_ATTRIBUTES; ++x) {
|
|
/* Create the name and correct value for each attribute */
|
|
attr_correct_string[0] = attr_name[0] = (char)((x / 10) + '0');
|
|
attr_correct_string[1] = attr_name[1] = (char)((x % 10) + '0');
|
|
|
|
attr1_id = H5Aopen(group1_id, attr_name, H5P_DEFAULT);
|
|
CHECK_I(attr1_id, "H5Aopen");
|
|
attr2_id = H5Aopen(group2_id, attr_name, H5P_DEFAULT);
|
|
CHECK_I(attr2_id, "H5Aopen");
|
|
|
|
ret = H5Aread(attr1_id, attr_type_id, attr_string);
|
|
CHECK_I(ret, "H5Aread");
|
|
VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
|
|
ret = H5Aread(attr2_id, attr_type_id, attr_string);
|
|
CHECK_I(ret, "H5Aread");
|
|
VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
|
|
|
|
ret = H5Aclose(attr1_id);
|
|
CHECK_I(attr1_id, "H5Aclose");
|
|
ret = H5Aclose(attr2_id);
|
|
CHECK_I(attr2_id, "H5Aclose");
|
|
}
|
|
|
|
/* Close everything */
|
|
ret = H5Tclose(attr_type_id);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Gclose(group1_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Gclose(group2_id);
|
|
CHECK_I(ret, "H5Gclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
} /* size2_verify */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_size2
|
|
*
|
|
* Purpose: Tests shared object header messages using size2_helper to
|
|
* create different kinds of big messages.
|
|
*
|
|
* If close_reopen is set, closes and reopens the HDF5 file
|
|
* repeatedly while writing.
|
|
*
|
|
* This test works by first creating FCPLs with various
|
|
* parameters, then creating a standard file that includes
|
|
* every kind of message that can be shared using the helper
|
|
* function size2_helper. The test measures the size of the
|
|
* file at various points. Once all of the files have been
|
|
* generated, the test compares the measured sizes of the files.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_size2(int close_reopen)
|
|
{
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
/* Sizes for file with no shared messages at all */
|
|
size2_helper_struct norm_sizes;
|
|
/* Sizes for files with all messages in one index */
|
|
size2_helper_struct list_index_med, list_index_big;
|
|
size2_helper_struct btree_index, list_index_small;
|
|
/* Sizes for files with messages in three different indexes */
|
|
size2_helper_struct mult_index_med, mult_index_btree;
|
|
/* Sizes for files that don't share all kinds of messages */
|
|
size2_helper_struct share_some_med, share_some_btree;
|
|
/* Sizes for files that share different sizes of messages */
|
|
size2_helper_struct share_some_toobig_index, share_tiny_index, type_space_index;
|
|
herr_t ret;
|
|
|
|
if (close_reopen == 0)
|
|
MESSAGE(5, ("Testing that shared object header messages save space\n"));
|
|
else
|
|
MESSAGE(5, ("Testing that shared messages save space when file is closed and reopened\n"));
|
|
|
|
/* Create an fcpl with SOHMs disabled */
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &norm_sizes);
|
|
size2_verify();
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* Create an fcpl with one big index */
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Set the indexes to use a medium-sized list */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &list_index_med);
|
|
size2_verify();
|
|
|
|
/* Try making the list really big */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &list_index_big);
|
|
size2_verify();
|
|
|
|
/* Use a B-tree instead of a list */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &btree_index);
|
|
size2_verify();
|
|
|
|
/* Use such a small list that it'll become a B-tree */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &list_index_small);
|
|
size2_verify();
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* Create a new property list that puts messages in different indexes. */
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_FILL_FLAG | H5O_SHMESG_PLINE_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_SHMESG_ATTR_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Use lists that are the same size as the "medium" list on the previous
|
|
* run.
|
|
*/
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &mult_index_med);
|
|
size2_verify();
|
|
|
|
/* Use all B-trees */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &mult_index_btree);
|
|
size2_verify();
|
|
|
|
/* Edit the same property list (this should work) and don't share all messages.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_PLINE_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 100000);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG, 20);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Use "normal-sized" lists. */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &share_some_med);
|
|
size2_verify();
|
|
|
|
/* Use btrees. */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &share_some_btree);
|
|
size2_verify();
|
|
|
|
/* Change the second index to hold only gigantic messages. Result should
|
|
* be the same as the previous file.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 100000);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &share_some_toobig_index);
|
|
size2_verify();
|
|
|
|
/* Share even tiny dataspace and datatype messages. This should result in
|
|
* attribute datatypes being shared. Make this one use "really big" lists.
|
|
* It turns out that attribute dataspaces are just big enough that it saves
|
|
* some space to share them, while sharing datatypes creates as much overhead
|
|
* as one gains from sharing them.
|
|
*/
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_SDSPACE_FLAG, 1);
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &share_tiny_index);
|
|
size2_verify();
|
|
|
|
/* Create the same file but don't share the really tiny messages */
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_SDSPACE_FLAG, 100);
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
|
|
|
|
/* Get the file size & verify its contents */
|
|
size2_helper(fcpl_id, close_reopen, &type_space_index);
|
|
size2_verify();
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* Check that all sizes make sense. There is lots of room for inexact
|
|
* results here since so many different factors contribute to file size.
|
|
*/
|
|
|
|
/* Check sizes of all files created using a single index first */
|
|
|
|
/* The empty size of each file with shared messages enabled should be the
|
|
* same and should be bigger than a normal file.
|
|
*/
|
|
if (norm_sizes.empty_size > 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 > (h5_stat_size_t)((float)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 > (h5_stat_size_t)((float)list_index_small.dsets2 * OVERHEAD_ALLOWED))
|
|
VERIFY(btree_index.dsets2, list_index_small.dsets2, "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 >
|
|
(h5_stat_size_t)((float)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 > (h5_stat_size_t)((float)list_index_small.interleaved * OVERHEAD_ALLOWED))
|
|
VERIFY(btree_index.interleaved, list_index_small.interleaved, "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 > (h5_stat_size_t)((float)list_index_small.attrs1 * OVERHEAD_ALLOWED))
|
|
VERIFY(btree_index.attrs1, list_index_small.attrs1, "h5_get_file_size");
|
|
if (btree_index.attrs1 > (h5_stat_size_t)((float)list_index_med.attrs1 * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if (list_index_med.attrs1 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if (list_index_small.attrs1 > (h5_stat_size_t)((float)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 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if (list_index_med.attrs1 > (h5_stat_size_t)((float)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");
|
|
|
|
/* Give it some overhead (for commit to move messages into continuation message) */
|
|
if ((list_index_small.attrs1 - list_index_small.interleaved) >
|
|
(h5_stat_size_t)((float)(btree_index.attrs1 - btree_index.interleaved) * OVERHEAD_ALLOWED))
|
|
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 > (h5_stat_size_t)((float)list_index_small.attrs2 * OVERHEAD_ALLOWED))
|
|
VERIFY(btree_index.attrs2, list_index_small.attrs2, "h5_get_file_size");
|
|
if (list_index_small.attrs2 > (h5_stat_size_t)((float)btree_index.attrs2 * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if (btree_index.attrs2 > (h5_stat_size_t)((float)list_index_med.attrs2 * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if (list_index_med.attrs2 > (h5_stat_size_t)((float)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");
|
|
|
|
/* When the second dataset is written, they should grow less as
|
|
* some extra heap space is allocated, but no more indices.
|
|
*/
|
|
if ((mult_index_med.second_dset - mult_index_med.first_dset) >
|
|
(mult_index_med.first_dset - mult_index_med.empty_size))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((list_index_med.second_dset - list_index_med.first_dset) >
|
|
(list_index_med.first_dset - list_index_med.empty_size))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((mult_index_btree.second_dset - mult_index_btree.first_dset) >
|
|
(mult_index_btree.first_dset - mult_index_btree.empty_size))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((btree_index.second_dset - btree_index.first_dset) >
|
|
(btree_index.first_dset - btree_index.empty_size))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
|
|
/* And the size delta for the second dataset is less in files with only
|
|
* one index.
|
|
*/
|
|
if ((mult_index_med.second_dset - mult_index_med.first_dset) <=
|
|
(list_index_med.second_dset - list_index_med.first_dset))
|
|
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.second_dset) !=
|
|
(list_index_med.dsets1 - list_index_med.second_dset))
|
|
VERIFY((mult_index_med.dsets1 - mult_index_med.second_dset),
|
|
(list_index_med.dsets1 - list_index_med.second_dset), "h5_get_file_size");
|
|
if ((mult_index_btree.dsets1 - mult_index_btree.second_dset) !=
|
|
(btree_index.dsets1 - btree_index.second_dset))
|
|
VERIFY((mult_index_btree.dsets1 - mult_index_btree.second_dset),
|
|
(btree_index.dsets1 - btree_index.second_dset), "h5_get_file_size");
|
|
|
|
if ((mult_index_med.dsets2 - mult_index_med.dsets1) >
|
|
(h5_stat_size_t)((float)(list_index_med.dsets2 - list_index_med.dsets1) * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((mult_index_btree.dsets2 - mult_index_btree.dsets1) >
|
|
(h5_stat_size_t)((float)(btree_index.dsets2 - btree_index.dsets1) * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
|
|
if ((mult_index_med.interleaved - mult_index_med.dsets2) >
|
|
(h5_stat_size_t)((float)(list_index_med.interleaved - list_index_med.dsets2) * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((mult_index_btree.interleaved - mult_index_btree.dsets2) >
|
|
(h5_stat_size_t)((float)(btree_index.interleaved - btree_index.dsets2) * OVERHEAD_ALLOWED))
|
|
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) >
|
|
(h5_stat_size_t)((float)(list_index_med.attrs2 - list_index_med.attrs1) * OVERHEAD_ALLOWED))
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((mult_index_btree.attrs2 - mult_index_btree.attrs1) >
|
|
(h5_stat_size_t)((float)(btree_index.attrs2 - btree_index.attrs1) * OVERHEAD_ALLOWED))
|
|
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 ((h5_stat_size_t)((float)mult_index_med.attrs2 * OVERHEAD_ALLOWED) < btree_index.attrs2)
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
if ((h5_stat_size_t)((float)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(share_tiny_index.empty_size, type_space_index.empty_size, "h5_get_file_size");
|
|
|
|
if (share_tiny_index.first_dset >=
|
|
(h5_stat_size_t)((float)type_space_index.first_dset * OVERHEAD_ALLOWED))
|
|
VERIFY(share_tiny_index.first_dset, type_space_index.first_dset, "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.second_dset >= type_space_index.second_dset)
|
|
VERIFY(share_tiny_index.second_dset, type_space_index.second_dset, "h5_get_file_size");
|
|
if ((h5_stat_size_t)((float)share_tiny_index.second_dset * OVERHEAD_ALLOWED) <
|
|
type_space_index.second_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 ((h5_stat_size_t)((float)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 ((h5_stat_size_t)((float)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 ((h5_stat_size_t)((float)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 ((h5_stat_size_t)((float)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 ((h5_stat_size_t)((float)share_tiny_index.attrs2 * OVERHEAD_ALLOWED) < type_space_index.attrs2)
|
|
VERIFY(0, 1, "h5_get_file_size");
|
|
} /* test_sohm_size2 */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: delete_helper_write
|
|
*
|
|
* Purpose: Creates a dataset and attribute in file FILE_ID using value X
|
|
* in the DSPACE_ID and DCPL_ID arrays.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
delete_helper_write(hid_t file_id, hid_t *dspace_id, hid_t *dcpl_id, int x)
|
|
{
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t attr_id = H5I_INVALID_HID;
|
|
char wdata;
|
|
herr_t ret;
|
|
|
|
dset_id =
|
|
H5Dcreate2(file_id, DSETNAME[x], H5T_NATIVE_CHAR, dspace_id[x], H5P_DEFAULT, dcpl_id[x], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
wdata = (char)(x + 'a');
|
|
ret = H5Dwrite(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &wdata);
|
|
CHECK_I(ret, "H5Dwrite");
|
|
|
|
attr_id = H5Acreate2(dset_id, "attr_name", H5T_NATIVE_CHAR, dspace_id[x], H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Acreate2");
|
|
ret = H5Awrite(attr_id, H5T_NATIVE_CHAR, &wdata);
|
|
CHECK_I(ret, "H5Awrite");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
} /* delete_helper_write */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: delete_helper_read
|
|
*
|
|
* Purpose: Checks the value of the dataset and attribute created by
|
|
* delete_helper_write.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
delete_helper_read(hid_t file_id, hid_t *dspace_id, int x)
|
|
{
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t attr_id = H5I_INVALID_HID;
|
|
char rdata;
|
|
herr_t ret;
|
|
|
|
dset_id = H5Dopen2(file_id, DSETNAME[x], H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
rdata = '\0';
|
|
ret = H5Dread(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &rdata);
|
|
CHECK_I(ret, "H5Dread");
|
|
VERIFY(rdata, (x + 'a'), "H5Dread");
|
|
|
|
attr_id = H5Aopen(dset_id, "attr_name", H5P_DEFAULT);
|
|
CHECK_I(attr_id, "H5Aopen");
|
|
rdata = '\0';
|
|
ret = H5Aread(attr_id, H5T_NATIVE_CHAR, &rdata);
|
|
CHECK_I(ret, "H5Dread");
|
|
VERIFY(rdata, (x + 'a'), "H5Dread");
|
|
|
|
ret = H5Aclose(attr_id);
|
|
CHECK_I(ret, "H5Aclose");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
} /* delete_helper_read */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: delete_helper
|
|
*
|
|
* Purpose: Creates some shared messages, deletes them, and creates some
|
|
* more messages. The second batch of messages should use the
|
|
* space freed by the first batch, so should be about the same
|
|
* size as a file that never had the first batch of messages
|
|
* created.
|
|
*
|
|
* FCPL_ID is the file creation property list to use.
|
|
* DSPACE_ID and DCPL_ID are arrays of different dataspaces
|
|
* and property lists with filter pipelines used to create the
|
|
* messages.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
delete_helper(hid_t fcpl_id, hid_t *dspace_id, hid_t *dcpl_id)
|
|
{
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
int x;
|
|
h5_stat_size_t norm_filesize;
|
|
h5_stat_size_t deleted_filesize;
|
|
herr_t ret;
|
|
|
|
/* Get the size of a "normal" file with no deleted messages */
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
/* Create batch of messages in the file starting at message 2 */
|
|
for (x = HALF_DELETE_NUM_MESGS; x < DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_write(file_id, dspace_id, dcpl_id, x);
|
|
}
|
|
|
|
/* Check that messages can be read */
|
|
for (x = HALF_DELETE_NUM_MESGS; x < DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_read(file_id, dspace_id, x);
|
|
}
|
|
|
|
/* Close file and get filesize */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
norm_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Create a new file with messages 0 to (HALF_DELETE_NUM_MESGS - 1) */
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
for (x = 0; x < HALF_DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_write(file_id, dspace_id, dcpl_id, x);
|
|
}
|
|
|
|
/* Verify each dataset, then delete it (which should delete
|
|
* its shared messages as well
|
|
*/
|
|
for (x = 0; x < HALF_DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_read(file_id, dspace_id, x);
|
|
ret = H5Ldelete(file_id, DSETNAME[x], H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Ldelete");
|
|
}
|
|
|
|
/* The file is now empty. Write and verify the second batch of messages
|
|
* again.
|
|
*/
|
|
for (x = HALF_DELETE_NUM_MESGS; x < DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_write(file_id, dspace_id, dcpl_id, x);
|
|
}
|
|
for (x = HALF_DELETE_NUM_MESGS; x < DELETE_NUM_MESGS; ++x) {
|
|
delete_helper_read(file_id, dspace_id, x);
|
|
}
|
|
|
|
/* Close file and get filesize */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* The two filesizes should be almost the same */
|
|
if (norm_filesize > (h5_stat_size_t)((float)deleted_filesize * OVERHEAD_ALLOWED))
|
|
VERIFY(norm_filesize, deleted_filesize, "h5_get_file_size");
|
|
if (deleted_filesize > (h5_stat_size_t)((float)norm_filesize * OVERHEAD_ALLOWED))
|
|
VERIFY(deleted_filesize, norm_filesize, "h5_get_file_size");
|
|
} /* delete_helper */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_delete
|
|
*
|
|
* Purpose: Tests shared object header message deletion.
|
|
*
|
|
* Creates lots of shared messages, then ensures that they
|
|
* can be deleted without corrupting the remaining messages.
|
|
* Also checks that indexes convert from B-trees back into
|
|
* lists.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_delete(void)
|
|
{
|
|
hid_t fcpl_id;
|
|
/* We'll use dataspaces and filter pipelines for this test.
|
|
* Create a number of distinct messages of each type.
|
|
*/
|
|
hid_t dspace_id[DELETE_NUM_MESGS] = {0};
|
|
hid_t dcpl_id[DELETE_NUM_MESGS] = {0};
|
|
unsigned u;
|
|
int x;
|
|
hsize_t dims[] = DELETE_DIMS;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing deletion of SOHMs\n"));
|
|
|
|
/* Create a number of different dataspaces.
|
|
* For simplicity, each dataspace has only one element.
|
|
*/
|
|
for (u = 0; u < DELETE_NUM_MESGS; ++u) {
|
|
dspace_id[u] = H5Screate_simple((int)(u + 1), dims, dims);
|
|
CHECK_I(dspace_id[u], "H5Screate_simple");
|
|
} /* end for */
|
|
|
|
/* Create a number of different filter pipelines. */
|
|
dcpl_id[0] = H5Pcreate(H5P_DATASET_CREATE);
|
|
CHECK_I(dcpl_id[0], "H5Pcreate");
|
|
|
|
ret = H5Pset_chunk(dcpl_id[0], 1, dims);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
ret = H5Pset_shuffle(dcpl_id[0]);
|
|
CHECK_I(ret, "H5Pset_shuffle");
|
|
|
|
for (u = 1; u < DELETE_NUM_MESGS; u += 2) {
|
|
dcpl_id[u] = H5Pcopy(dcpl_id[u - 1]);
|
|
CHECK_I(dcpl_id[u], "H5Pcopy");
|
|
ret = H5Pset_chunk(dcpl_id[u], (int)(u + 1), dims);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
ret = H5Pset_deflate(dcpl_id[u], 1);
|
|
CHECK_I(ret, "H5Pset_deflate");
|
|
|
|
dcpl_id[u + 1] = H5Pcopy(dcpl_id[u]);
|
|
CHECK_I(dcpl_id[u + 1], "H5Pcopy");
|
|
ret = H5Pset_chunk(dcpl_id[u + 1], (int)(u + 2), dims);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
ret = H5Pset_shuffle(dcpl_id[u + 1]);
|
|
CHECK_I(ret, "H5Pset_shuffle");
|
|
} /* end for */
|
|
|
|
/* Create an fcpl where all messages are shared in the same index */
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Use big list indexes */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 4 * DELETE_NUM_MESGS, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Test that messages can be created and deleted properly */
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
|
|
/* Use B-tree indexes */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
|
|
/* Use small list indexes that will convert from lists to B-trees and back */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS, HALF_DELETE_NUM_MESGS - 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
|
|
/* Use two indexes */
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_ATTR_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Use big list indexes */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 5000, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
/* Use B-tree indexes */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
|
|
/* Set phase change values so that one index converts to a B-tree and one doesn't */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS + 1, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
|
|
/* Test with varying message sizes (ideally, so some messages are too
|
|
* small to be written but some are big enough that they are still written
|
|
*/
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
for (u = DELETE_MIN_MESG_SIZE; u <= DELETE_MAX_MESG_SIZE; u += 10) {
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, u);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
delete_helper(fcpl_id, dspace_id, dcpl_id);
|
|
} /* end for */
|
|
|
|
/* Cleanup */
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
for (x = DELETE_NUM_MESGS - 1; x >= 0; --x) {
|
|
ret = H5Sclose(dspace_id[x]);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Pclose(dcpl_id[x]);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* end for */
|
|
} /* test_sohm_delete */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_dset_create_and_delete_does_not_grow_file
|
|
*
|
|
* Purpose: Tests that shared object header message deletion returns
|
|
* the file to its previous state using the supplied FCPL.
|
|
*
|
|
* Creates a file according to the supplied FCPL,
|
|
* then creates datasets and deletes them.
|
|
* Done in two passes: once with one dataset, once with two.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
verify_dset_create_and_delete_does_not_grow_file(hid_t fcpl_id)
|
|
{
|
|
hid_t file_id;
|
|
hid_t dspace_id;
|
|
hid_t dset_id;
|
|
hsize_t dims[1] = {1};
|
|
h5_stat_size_t initial_filesize, deleted_filesize;
|
|
int old_nerrs; /* Number of errors when entering this routine */
|
|
herr_t ret;
|
|
|
|
/* Retrieve the current # of reported errors */
|
|
old_nerrs = GetTestNumErrs();
|
|
|
|
/* Create a dataspace for later */
|
|
dspace_id = H5Screate_simple(1, dims, dims);
|
|
CHECK_I(dspace_id, "H5Screate_simple");
|
|
|
|
/* Create a file using the FCPL supplied*/
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
/* Close the file and get its size */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
initial_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
/* Re-create the file and create a dataset in it */
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
dset_id = H5Dcreate2(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
/* Close the dataset and delete it */
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Ldelete");
|
|
|
|
/* Close the file and get its size */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
|
|
|
|
/* Repeat, creating two datasets in the file */
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
/* Create and close the first dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
|
|
/* Create and close the second. These messages should be shared */
|
|
dset_id =
|
|
H5Dcreate2(file_id, "dset2", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
|
|
/* Delete both datasets */
|
|
ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Ldelete");
|
|
ret = H5Ldelete(file_id, "dset2", H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Ldelete");
|
|
|
|
/* Close the file and get its size */
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
|
|
|
|
VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
|
|
|
|
/* Cleanup */
|
|
ret = H5Sclose(dspace_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
|
|
/* Retrieve current # of errors */
|
|
if (old_nerrs == GetTestNumErrs())
|
|
return (0);
|
|
else
|
|
return (-1);
|
|
} /* verify_dset_create_and_delete_does_not_grow_file */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_delete_revert
|
|
*
|
|
* Purpose: Verifies that creation and deletion of datasets with shared
|
|
* message headers will not increase file size.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_delete_revert(void)
|
|
{
|
|
hid_t fcpl_id;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing that file reverts to original size on SOHM deletion\n"));
|
|
|
|
/* Create an fcpl with messages in two indexes */
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG, 10);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_SDSPACE_FLAG, 10);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
/* Call the helper function to test this FCPL. */
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
/* Try using B-trees */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
/* Try sharing all messages */
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 10);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 5);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
/* Try using B-trees */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
/* There should be at least two messages in the test (datatype and
|
|
* dataspace). Use an index that will transition from a list to
|
|
* a B-tree and back.
|
|
*/
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1, 2);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
/* Try with shared messages enabled, but when messages are too big
|
|
* to be shared.
|
|
*/
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 35);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
|
|
CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* test_sohm_delete_revert */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_dset_create_and_open_through_extlink_with_sohm
|
|
*
|
|
* Purpose: Tests that a dataset created through an external link can
|
|
* be opened (that shared messages were created or not and
|
|
* were shared in the right file).
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
verify_dset_create_and_open_through_extlink_with_sohm(hid_t src_fcpl_id, hid_t dst_fcpl_id)
|
|
{
|
|
hid_t src_file_id = H5I_INVALID_HID;
|
|
hid_t dst_file_id = H5I_INVALID_HID;
|
|
hid_t space_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hsize_t dims[] = {1, 1};
|
|
herr_t ret;
|
|
|
|
/* Create files */
|
|
src_file_id = H5Fcreate(FILENAME_SRC, H5F_ACC_TRUNC, src_fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(src_file_id, "H5Fcreate");
|
|
dst_file_id = H5Fcreate(FILENAME_DST, H5F_ACC_TRUNC, dst_fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dst_file_id, "H5Fcreate");
|
|
|
|
/* Create an external link from the source file to the destination file */
|
|
ret = H5Lcreate_external(FILENAME_DST, "/", src_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(ret, "H5Lcreate_external");
|
|
|
|
/* Create a dataset through the external link */
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
CHECK_I(space_id, "H5Screate_simple");
|
|
dset_id = H5Dcreate2(src_file_id, "ext_link/dataset", H5T_NATIVE_FLOAT, space_id, H5P_DEFAULT,
|
|
H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dcreate2");
|
|
|
|
/* Close the dataset and both files to make sure everything gets flushed
|
|
* out of memory
|
|
*/
|
|
ret = H5Sclose(space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Fclose(src_file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
ret = H5Fclose(dst_file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Ensure that the dataset can be opened. If the messages were written in
|
|
* the wrong file, it'll be impossible to read the dataset's object
|
|
* header.
|
|
*/
|
|
dst_file_id = H5Fopen(FILENAME_DST, H5F_ACC_RDONLY, H5P_DEFAULT);
|
|
CHECK_I(dst_file_id, "H5Fopen");
|
|
dset_id = H5Dopen2(dst_file_id, "dataset", H5P_DEFAULT);
|
|
CHECK_I(dset_id, "H5Dopen2");
|
|
|
|
/* Cleanup */
|
|
ret = H5Dclose(dset_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Fclose(dst_file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
} /* verify_dset_create_and_open_through_extlink_with_sohm */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_extlink
|
|
*
|
|
* Purpose: Test creating SOHMs through external links (to make sure that
|
|
* they're created in the correct file).
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_extlink(void)
|
|
{
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
bool driver_is_default_compatible;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing SOHM creation through external links\n"));
|
|
|
|
ret = h5_driver_is_default_vfd_compatible(H5P_DEFAULT, &driver_is_default_compatible);
|
|
CHECK_I(ret, "h5_driver_is_default_vfd_compatible");
|
|
|
|
if (!driver_is_default_compatible) {
|
|
MESSAGE(5, ("-- SKIPPED --\n"));
|
|
return;
|
|
}
|
|
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
verify_dset_create_and_open_through_extlink_with_sohm(fcpl_id, H5P_DEFAULT);
|
|
verify_dset_create_and_open_through_extlink_with_sohm(H5P_DEFAULT, fcpl_id);
|
|
verify_dset_create_and_open_through_extlink_with_sohm(fcpl_id, fcpl_id);
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* test_sohm_extlink */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: verify_dataset_extension
|
|
*
|
|
* Purpose: Tests extending a dataset's dataspace when sharing is
|
|
* enabled.
|
|
*
|
|
* If close_reopen is true, closes and reopens the file to
|
|
* ensure that data is correctly written to disk.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
verify_dataset_extension(hid_t fcpl_id, bool close_reopen)
|
|
{
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
hid_t orig_space_id = H5I_INVALID_HID;
|
|
hid_t space1_id, space2_id, space3_id;
|
|
hid_t dcpl_id = H5I_INVALID_HID;
|
|
hid_t dset1_id, dset2_id = H5I_INVALID_HID, dset3_id = H5I_INVALID_HID;
|
|
hsize_t dims1[] = {1, 2};
|
|
hsize_t max_dims[] = {H5S_UNLIMITED, 2};
|
|
hsize_t dims2[] = {5, 2};
|
|
hsize_t out_dims[2];
|
|
hsize_t out_maxdims[2];
|
|
int x;
|
|
int old_nerrs; /* Number of errors when entering this routine */
|
|
herr_t ret;
|
|
|
|
hsize_t *space_dims[3];
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* Macro: TSOHM_VDE_VERIFY_SPACES
|
|
*
|
|
* Purpose: Encapsulate a common pattern
|
|
* Open, read-verify, and close the dataspaces for datasets 1-3
|
|
*
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
*/
|
|
#define TSOHM_VDE_VERIFY_SPACES(dims) \
|
|
do { \
|
|
/* Open dataspaces \
|
|
*/ \
|
|
space1_id = H5Dget_space(dset1_id); \
|
|
CHECK_I(space1_id, "H5Dget_space"); \
|
|
space2_id = H5Dget_space(dset2_id); \
|
|
CHECK_I(space2_id, "H5Dget_space"); \
|
|
space3_id = H5Dget_space(dset3_id); \
|
|
CHECK_I(space3_id, "H5Dget_space"); \
|
|
/* Verify dataspaces \
|
|
*/ \
|
|
ret = H5Sget_simple_extent_dims(space1_id, out_dims, out_maxdims); \
|
|
CHECK_I(ret, "H5Sget_simple_extent_dims"); \
|
|
for (x = 0; x < EXTEND_NDIMS; ++x) { \
|
|
VERIFY(out_dims[x], (dims)[0][x], "H5Sget_simple_extent_dims"); \
|
|
VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
|
|
} \
|
|
ret = H5Sget_simple_extent_dims(space2_id, out_dims, out_maxdims); \
|
|
CHECK_I(ret, "H5Sget_simple_extent_dims"); \
|
|
for (x = 0; x < EXTEND_NDIMS; ++x) { \
|
|
VERIFY(out_dims[x], (dims)[1][x], "H5Sget_simple_extent_dims"); \
|
|
VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
|
|
} \
|
|
ret = H5Sget_simple_extent_dims(space3_id, out_dims, out_maxdims); \
|
|
CHECK_I(ret, "H5Sget_simple_extent_dims"); \
|
|
for (x = 0; x < EXTEND_NDIMS; ++x) { \
|
|
VERIFY(out_dims[x], (dims)[2][x], "H5Sget_simple_extent_dims"); \
|
|
VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
|
|
} \
|
|
/* Close dataspaces \
|
|
*/ \
|
|
CHECK_I(H5Sclose(space1_id), "H5Sclose"); \
|
|
CHECK_I(H5Sclose(space2_id), "H5Sclose"); \
|
|
CHECK_I(H5Sclose(space3_id), "H5Sclose"); \
|
|
} while (0) /* define TSOHM_VDE_VERIFY_SPACES */
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* Macro: TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS()
|
|
*
|
|
* Purpose: Encapsulate a common pattern
|
|
* Wrapper to close and reopen file and datasets:
|
|
* + "dataset" (dset_id)
|
|
* + if n > 1 then include "dataset2" (dset_id2)
|
|
* + if n > 2 then include "dataset3" (dset_id3)
|
|
* + file (file_id)
|
|
*
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
*/
|
|
#define TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(n) \
|
|
do { \
|
|
CHECK_I(H5Dclose(dset1_id), "H5Dclose"); \
|
|
if ((n) > 1) \
|
|
CHECK_I(H5Dclose(dset2_id), "H5Dclose"); \
|
|
if ((n) > 2) \
|
|
CHECK_I(H5Dclose(dset3_id), "H5Dclose"); \
|
|
CHECK_I(H5Fclose(file_id), "H5Fclose"); \
|
|
\
|
|
file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT); \
|
|
CHECK_I(file_id, "H5Fopen"); \
|
|
dset1_id = H5Dopen2(file_id, "dataset", H5P_DEFAULT); \
|
|
CHECK_I(dset1_id, "H5Dopen2"); \
|
|
if ((n) > 1) { \
|
|
dset2_id = H5Dopen2(file_id, "dataset2", H5P_DEFAULT); \
|
|
CHECK_I(dset2_id, "H5Dopen2"); \
|
|
} \
|
|
if ((n) > 2) { \
|
|
dset3_id = H5Dopen2(file_id, "dataset3", H5P_DEFAULT); \
|
|
CHECK_I(dset3_id, "H5Dopen2"); \
|
|
} \
|
|
} while (0) /* define TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS */
|
|
|
|
/* Remember the current # of reported errors */
|
|
old_nerrs = GetTestNumErrs();
|
|
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
|
|
/* Create property list with chunking */
|
|
dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
|
|
CHECK_I(dcpl_id, "H5Pcreate");
|
|
ret = H5Pset_chunk(dcpl_id, 2, dims1);
|
|
CHECK_I(ret, "H5Pset_chunk");
|
|
|
|
/* Create a dataspace and a dataset*/
|
|
orig_space_id = H5Screate_simple(EXTEND_NDIMS, dims1, max_dims);
|
|
CHECK_I(orig_space_id, "H5Screate_simple");
|
|
dset1_id =
|
|
H5Dcreate2(file_id, "dataset", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset1_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
|
|
|
|
/* Create another dataset starting with the same dataspace */
|
|
dset2_id =
|
|
H5Dcreate2(file_id, "dataset2", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset2_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
|
|
|
|
/* Create a third dataset with the same dataspace */
|
|
dset3_id =
|
|
H5Dcreate2(file_id, "dataset3", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset3_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
/* Extend the first dataset */
|
|
ret = H5Dset_extent(dset1_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
space_dims[0] = dims2;
|
|
space_dims[1] = dims1;
|
|
space_dims[2] = dims1;
|
|
TSOHM_VDE_VERIFY_SPACES(space_dims);
|
|
|
|
/* Extend the second dataset */
|
|
ret = H5Dset_extent(dset2_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
space_dims[1] = dims2;
|
|
TSOHM_VDE_VERIFY_SPACES(space_dims);
|
|
|
|
/* Extend the third dataset */
|
|
ret = H5Dset_extent(dset3_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
space_dims[2] = dims2;
|
|
TSOHM_VDE_VERIFY_SPACES(space_dims);
|
|
|
|
/* Close the datasets and file */
|
|
ret = H5Dclose(dset1_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Dclose(dset2_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Dclose(dset3_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Change the order in which datasets are extended to ensure that there
|
|
* are no problems if a dataspace goes from being shared to not being
|
|
* shared or vice versa.
|
|
*/
|
|
file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
|
|
CHECK_I(file_id, "H5Fcreate");
|
|
dset1_id =
|
|
H5Dcreate2(file_id, "dataset", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset1_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
|
|
|
|
/* Extend the first dataset */
|
|
ret = H5Dset_extent(dset1_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
|
|
|
|
/* Create the second dataset. Its dataspace will be unshared and then
|
|
* become shared when extended.
|
|
*/
|
|
dset2_id =
|
|
H5Dcreate2(file_id, "dataset2", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset2_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
|
|
|
|
/* Extend the second dataset */
|
|
ret = H5Dset_extent(dset2_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
|
|
|
|
/* Create the third dataset. Its dataspace will be unshared and then
|
|
* become shared when extended.
|
|
*/
|
|
dset3_id =
|
|
H5Dcreate2(file_id, "dataset3", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
|
|
CHECK_I(dset3_id, "H5Dcreate2");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
/* Extend the third dataset */
|
|
ret = H5Dset_extent(dset3_id, dims2);
|
|
CHECK_I(ret, "H5Dset_extent");
|
|
if (close_reopen)
|
|
TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
|
|
|
|
TSOHM_VDE_VERIFY_SPACES(space_dims);
|
|
|
|
/* Close the datasets and file */
|
|
ret = H5Dclose(dset1_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Dclose(dset2_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Dclose(dset3_id);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Fclose(file_id);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Cleanup */
|
|
ret = H5Sclose(orig_space_id);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Pclose(dcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
|
|
/* Complain if this test generated errors */
|
|
if (old_nerrs == GetTestNumErrs())
|
|
return (0);
|
|
else
|
|
return (-1);
|
|
/* macros are exclusive to this function */
|
|
#undef TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS
|
|
#undef TSOHM_VDE_VERIFY_SPACES
|
|
} /* verify_dataset_extension */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_extend_dset
|
|
*
|
|
* Purpose: Test extended shared dataspaces. An extended dataset's
|
|
* dataspace will change, possibly confusing the shared message
|
|
* code.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_extend_dset(void)
|
|
{
|
|
hid_t fcpl_id = H5I_INVALID_HID;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing extending shared dataspaces\n"));
|
|
|
|
fcpl_id = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl_id, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
|
|
/* No shared messages */
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
/* Only dataspaces */
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
/* All messages */
|
|
ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
/* All messages in lists */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 100, 50);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
/* All messages in lists converted to B-trees */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
/* All messages in B-trees */
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
ret = verify_dataset_extension(fcpl_id, false);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
ret = verify_dataset_extension(fcpl_id, true);
|
|
CHECK_I(ret, "verify_dataset_extension");
|
|
|
|
ret = H5Pclose(fcpl_id);
|
|
CHECK_I(ret, "H5Pclose");
|
|
} /* test_sohm_extend_dset */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_sohm_external_dtype
|
|
*
|
|
* Purpose: When a datatype is a SOHM type in one file, test that the
|
|
* second file using the same datatype actually save it in
|
|
* the file, too.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_sohm_external_dtype(void)
|
|
{
|
|
typedef struct s1_t {
|
|
int a;
|
|
int b;
|
|
} s1_t;
|
|
s1_t *s_ptr, *orig;
|
|
hid_t fcpl, file1, file2;
|
|
hid_t dataset1, dataset2;
|
|
hid_t s1_tid, dset1_tid, dset2_tid, space;
|
|
hsize_t dims[2] = {NX, NY};
|
|
H5T_class_t dtype_class;
|
|
size_t dmsg_count;
|
|
unsigned x, i;
|
|
herr_t ret;
|
|
|
|
MESSAGE(5, ("Testing shared external datatype\n"));
|
|
|
|
fcpl = H5Pcreate(H5P_FILE_CREATE);
|
|
CHECK_I(fcpl, "H5Pcreate");
|
|
ret = H5Pset_shared_mesg_nindexes(fcpl, TEST_NUM_INDEXES);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
|
|
for (x = 0; x < TEST_NUM_INDEXES; ++x) {
|
|
ret = H5Pset_shared_mesg_index(fcpl, x, test_type_flags[x], test_minsizes[x]);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_index");
|
|
}
|
|
ret = H5Pset_shared_mesg_phase_change(fcpl, TEST_L2B, TEST_B2L);
|
|
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
|
|
|
|
space = H5Screate_simple(2, dims, NULL);
|
|
CHECK_I(space, "H5Screate_simple");
|
|
|
|
s1_tid = H5Tcreate(H5T_COMPOUND, sizeof(s1_t));
|
|
CHECK_I(s1_tid, "H5Tcreate");
|
|
ret = H5Tinsert(s1_tid, "a", HOFFSET(s1_t, a), H5T_NATIVE_INT);
|
|
CHECK_I(ret, "H5Tinsert");
|
|
ret = H5Tinsert(s1_tid, "b", HOFFSET(s1_t, b), H5T_NATIVE_INT);
|
|
CHECK_I(ret, "H5Tinsert");
|
|
|
|
/* Set up dataset in first file */
|
|
file1 = H5Fcreate(FILENAME_SRC, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT);
|
|
CHECK_I(file1, "H5Fcreate");
|
|
|
|
/* Check on datatype storage status. It should be zero now. */
|
|
ret = H5F__get_sohm_mesg_count_test(file1, H5O_DTYPE_ID, &dmsg_count);
|
|
CHECK(ret, FAIL, "H5F__get_sohm_mesg_count_test");
|
|
VERIFY(dmsg_count, 0, "H5F__get_sohm_mesg_count_test");
|
|
|
|
dataset1 = H5Dcreate2(file1, "dataset_1", s1_tid, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dataset1, "H5Dcreate2");
|
|
|
|
/* Check on datatype storage status. It should be 1 now. */
|
|
ret = H5F__get_sohm_mesg_count_test(file1, H5O_DTYPE_ID, &dmsg_count);
|
|
CHECK(ret, FAIL, "H5F__get_sohm_mesg_count_test");
|
|
VERIFY(dmsg_count, 1, "H5F__get_sohm_mesg_count_test");
|
|
|
|
dset1_tid = H5Dget_type(dataset1);
|
|
CHECK_I(dset1_tid, "H5Dget_type");
|
|
|
|
/* Allocate space and initialize data */
|
|
orig = (s1_t *)malloc(NX * NY * sizeof(s1_t));
|
|
if (orig == NULL)
|
|
CHECK_I(-1, "malloc");
|
|
for (i = 0; i < NX * NY; i++) {
|
|
s_ptr = (s1_t *)orig + i;
|
|
s_ptr->a = (int)(i * 3 + 1);
|
|
s_ptr->b = (int)(i * 3 + 2);
|
|
}
|
|
|
|
ret = H5Dwrite(dataset1, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig);
|
|
CHECK_I(ret, "H5Dwrite");
|
|
ret = H5Dclose(dataset1);
|
|
CHECK_I(ret, "H5Dclose");
|
|
|
|
/* Create dataset in second file using datatype from dataset in the first file */
|
|
file2 = H5Fcreate(FILENAME_DST, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT);
|
|
CHECK_I(file2, "H5Fcreate");
|
|
|
|
/* Check on datatype storage status. It should be zero now. */
|
|
ret = H5F__get_sohm_mesg_count_test(file2, H5O_DTYPE_ID, &dmsg_count);
|
|
CHECK(ret, FAIL, "H5F__get_sohm_mesg_count_test");
|
|
VERIFY(dmsg_count, 0, "H5F__get_sohm_mesg_count_test");
|
|
|
|
dataset2 = H5Dcreate2(file2, "dataset_2", dset1_tid, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
CHECK_I(dataset2, "H5Dcreate2");
|
|
|
|
/* Check on datatype storage status. It should be 1 now. */
|
|
ret = H5F__get_sohm_mesg_count_test(file2, H5O_DTYPE_ID, &dmsg_count);
|
|
CHECK(ret, FAIL, "H5F__get_sohm_mesg_count_test");
|
|
VERIFY(dmsg_count, 1, "H5F__get_sohm_mesg_count_test");
|
|
|
|
ret = H5Dwrite(dataset2, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig);
|
|
CHECK_I(ret, "H5Dwrite");
|
|
|
|
/* Close references to the first file */
|
|
ret = H5Dclose(dataset2);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Tclose(dset1_tid);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Fclose(file1);
|
|
CHECK_I(ret, "H5Fclose");
|
|
|
|
/* Verify that datatype details are still accessible by second file */
|
|
dataset2 = H5Dopen2(file2, "dataset_2", H5P_DEFAULT);
|
|
CHECK_I(dataset2, "H5Dopen2");
|
|
|
|
dset2_tid = H5Dget_type(dataset2);
|
|
CHECK_I(dset2_tid, "H5Dget_type");
|
|
|
|
dtype_class = H5Tget_class(dset2_tid);
|
|
VERIFY(dtype_class, H5T_COMPOUND, "H5Tget_class");
|
|
|
|
/* Cleanup */
|
|
ret = H5Tclose(dset2_tid);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Dclose(dataset2);
|
|
CHECK_I(ret, "H5Dclose");
|
|
ret = H5Sclose(space);
|
|
CHECK_I(ret, "H5Sclose");
|
|
ret = H5Tclose(s1_tid);
|
|
CHECK_I(ret, "H5Tclose");
|
|
ret = H5Pclose(fcpl);
|
|
CHECK_I(ret, "H5Pclose");
|
|
ret = H5Fclose(file2);
|
|
CHECK_I(ret, "H5Fclose");
|
|
free(orig);
|
|
} /* test_sohm_external_dtype */
|
|
|
|
/****************************************************************
|
|
**
|
|
** test_sohm(): Main Shared Object Header Message testing routine.
|
|
**
|
|
****************************************************************/
|
|
void
|
|
test_sohm(const void H5_ATTR_UNUSED *params)
|
|
{
|
|
const char *driver_name;
|
|
bool vol_is_native;
|
|
bool default_driver;
|
|
|
|
MESSAGE(5, ("Testing Shared Object Header Messages\n"));
|
|
|
|
/* Check if native VOL is being used */
|
|
CHECK(h5_using_native_vol(H5P_DEFAULT, H5I_INVALID_HID, &vol_is_native), FAIL, "h5_using_native_vol");
|
|
if (!vol_is_native) {
|
|
MESSAGE(5, (" -- SKIPPED --\n"));
|
|
return;
|
|
}
|
|
|
|
/* Get the VFD to use */
|
|
driver_name = h5_get_test_driver_name();
|
|
default_driver = h5_using_default_driver(driver_name);
|
|
|
|
test_sohm_fcpl(); /* Test SOHMs and file creation plists */
|
|
test_sohm_fcpl_errors(); /* Bogus H5P* calls for SOHMs */
|
|
|
|
/* Only run this test with sec2/default driver */
|
|
if (default_driver)
|
|
test_sohm_size1(); /* Tests the sizes of files with one SOHM */
|
|
|
|
#if 0 /* TODO: REVEALS BUG TO BE FIXED - SEE JIRA HDFFV-10645 */
|
|
test_sohm_size_consistency_open_create();
|
|
#endif /* Jira HDFFV-10645 */
|
|
test_sohm_attrs(); /* Tests shared messages in attributes */
|
|
|
|
/* Only run these tests with sec2/default driver */
|
|
if (default_driver) {
|
|
test_sohm_size2(0); /* Tests the sizes of files with multiple SOHMs */
|
|
test_sohm_size2(1); /* Tests the sizes of files with multiple
|
|
* SOHMs, closing and reopening file after
|
|
* each write. */
|
|
}
|
|
|
|
test_sohm_delete(); /* Test deleting shared messages */
|
|
test_sohm_delete_revert(); /* Test that a file with SOHMs becomes an
|
|
* empty file again when they are deleted. */
|
|
|
|
test_sohm_extlink(); /* Test SOHMs when external links are used */
|
|
|
|
test_sohm_extend_dset(); /* Test extending shared datasets */
|
|
test_sohm_external_dtype(); /* Test using datatype in another file */
|
|
} /* test_sohm */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: cleanup_sohm
|
|
*
|
|
* Purpose: Cleanup temporary test files
|
|
*
|
|
* Return: none
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
cleanup_sohm(void H5_ATTR_UNUSED *params)
|
|
{
|
|
if (GetTestCleanup()) {
|
|
HDremove(FILENAME);
|
|
HDremove(FILENAME_SRC);
|
|
HDremove(FILENAME_DST);
|
|
}
|
|
} /* cleanup_sohm */
|