1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*
15  * Purpose:     Test Shared Object Header Messages
16  */
17 
18 #include "testhdf5.h"
19 
20 /*
21  * This file needs to access private information from the H5F package.
22  * This file also needs to access the file testing code.
23  */
24 #define H5F_FRIEND   /* suppress error about including H5Fpkg      */
25 #define H5F_TESTING
26 #include "H5Fpkg.h"  /* File access */
27 
28 /* Default SOHM values */
29 #define DEF_NUM_INDEXES 0
30 const unsigned def_type_flags[H5O_SHMESG_MAX_NINDEXES] = {0,0,0,0,0,0};
31 const unsigned def_minsizes[H5O_SHMESG_MAX_NINDEXES] = {250,250,250,250,250,250};
32 #define DEF_L2B 50
33 #define DEF_B2L 40
34 
35 /* Non-default SOHM values for testing */
36 #define TEST_NUM_INDEXES 4
37 const unsigned test_type_flags[H5O_SHMESG_MAX_NINDEXES] =
38                 {H5O_SHMESG_FILL_FLAG,
39                  H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_ATTR_FLAG,
40                  H5O_SHMESG_SDSPACE_FLAG,
41                  H5O_SHMESG_PLINE_FLAG,
42                  0, 0};
43 const unsigned test_minsizes[H5O_SHMESG_MAX_NINDEXES] = {0, 2, 40, 100, 3, 1000};
44 #define TEST_L2B 65
45 #define TEST_B2L 64
46 
47 #define FILENAME   "tsohm.h5"
48 #define FILENAME_SRC   "tsohm_src.h5"
49 #define FILENAME_DST   "tsohm_dst.h5"
50 
51 #define NAME_BUF_SIZE 512
52 
53 /* How much overhead counts as "not much" when converting B-trees, etc. */
54 #define OVERHEAD_ALLOWED 1.15F
55 
56 #define NUM_DATASETS 10
57 #define NUM_ATTRIBUTES 100
58 
59 typedef struct dtype1_struct {
60     int    i1;
61     char   str[10];
62     int    i2;
63     int    i3;
64     int    i4;
65     int    i5;
66     int    i6;
67     int    i7;
68     int    i8;
69     float  f1;
70 } dtype1_struct;
71 
72 #define DTYPE2_SIZE 1024
73 const char *DSETNAME[] = {
74     "dataset0",    "dataset1",
75     "dataset2",    "dataset3",
76     "dataset4",    "dataset5",
77     "dataset6",    "dataset7",
78     "dataset8",    "dataset9",
79     "dataset10",    "dataset11",
80     NULL
81 };
82 const char *EXTRA_DSETNAME[] = {
83     "ex_dataset0",    "ex_dataset1",
84     "ex_dataset2",    "ex_dataset3",
85     "ex_dataset4",    "ex_dataset5",
86     "ex_dataset6",    "ex_dataset7",
87     "ex_dataset8",    "ex_dataset9",
88     "ex_dataset10",   "ex_dataset11",
89     "ex_dataset12",   "ex_dataset13",
90     "ex_dataset14",   "ex_dataset15",
91     "ex_dataset16",   "ex_dataset17",
92     "ex_dataset18",   "ex_dataset19",
93     NULL
94 };
95 #define SOHM_HELPER_NUM_EX_DSETS 20
96 typedef struct complex_t {
97     double                  re;
98     double                  im;
99 } complex_t;
100 #define ENUM_NUM_MEMBS 20
101 const char *ENUM_NAME[] = {
102     "enum_member0",     "enum_member1",
103     "enum_member2",     "enum_member3",
104     "enum_member4",     "enum_member5",
105     "enum_member6",     "enum_member7",
106     "enum_member8",     "enum_member9",
107     "enum_member10",    "enum_member11",
108     "enum_member12",    "enum_member13",
109     "enum_member14",    "enum_member15",
110     "enum_member16",    "enum_member17",
111     "enum_member18",    "enum_member19",
112     NULL
113 };
114 const int ENUM_VAL[] = {
115     0,     13,
116     -500,  63,
117     64,    -64,
118     65,    2048,
119     1,     2,
120     -1,    7,
121     130,    -5000,
122     630,    640,
123     -640,   650,
124     20480,  10,
125     -1001,    -10
126 };
127 #define SIZE2_RANK1 6
128 #define SIZE2_RANK2 10
129 #define SIZE2_DIMS {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
130 
131 #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."
132 
133 /* Struct returned from size2_helper function */
134 typedef struct size2_helper_struct {
135     h5_stat_size_t empty_size;
136     h5_stat_size_t first_dset;
137     h5_stat_size_t second_dset;
138     h5_stat_size_t dsets1;
139     h5_stat_size_t dsets2;
140     h5_stat_size_t interleaved;
141     h5_stat_size_t attrs1;
142     h5_stat_size_t attrs2;
143 } size2_helper_struct;
144 
145 /* Number of distinct messages for the sohm_delete test */
146 #define DELETE_NUM_MESGS 7
147 #define HALF_DELETE_NUM_MESGS 3
148 #define DELETE_DIMS {1,1,1,1,1,1,1}
149 #define DELETE_MIN_MESG_SIZE 10
150 #define DELETE_MAX_MESG_SIZE 60
151 
152 
153 /* Number of dimensions in extend_dset test */
154 #define EXTEND_NDIMS 2
155 
156 /* Dimensions for external_dtype test */
157 #define NX     10
158 #define NY     10
159 
160 /* Helper function prototypes */
161 static hid_t make_dtype_1(void);
162 static hid_t make_dtype_2(void);
163 static hid_t close_reopen_file(hid_t file, const char* filename, hid_t fapl_id);
164 static void test_sohm_attrs(void);
165 #ifdef NOT_NOW
166 static void size2_dump_struct(const char *name, size2_helper_struct *sizes);
167 #endif /* NOT_NOW */
168 static void size2_verify(void);
169 static void test_sohm_delete(void);
170 static void test_sohm_delete_revert(void);
171 static void test_sohm_extlink(void);
172 
173 
174 
175 /****************************************************************
176 **
177 **  verify_fcpl_values(): Verifies that FCPL is set as expected.
178 **
179 ****************************************************************/
180 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)181 verify_fcpl_values(hid_t fcpl_id, const unsigned nindexes_expected, const unsigned *flags_expected, const unsigned *minsizes_expected, unsigned l2b, unsigned b2l)
182 {
183     unsigned  nindexes_actual;
184     unsigned  list_size;
185     unsigned  btree_size;
186     unsigned  x;
187     herr_t    ret;
188 
189     /* Number of indexes */
190     ret = H5Pget_shared_mesg_nindexes(fcpl_id, &nindexes_actual);
191     CHECK_I(ret, "H5Pget_shared_mesg_nindexes");
192     VERIFY(nindexes_actual, nindexes_expected, "H5Pget_shared_mesg_nindexes");
193 
194     /* Index flags and minsizes */
195     for(x=0; x<nindexes_actual; ++x) {
196         unsigned flags_i;
197         unsigned min_mesg_size;
198         ret = H5Pget_shared_mesg_index(fcpl_id, x, &flags_i, &min_mesg_size);
199         CHECK_I(ret, "H5Pget_shared_mesg_index");
200         VERIFY(flags_i, flags_expected[x], "H5Pget_shared_mesg_index");
201         VERIFY(min_mesg_size, minsizes_expected[x], "H5Pget_shared_mesg_index");
202     }
203 
204     /* List-to-btree and btree-to-list values */
205     ret = H5Pget_shared_mesg_phase_change(fcpl_id, &list_size, &btree_size);
206     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
207     VERIFY(list_size, l2b, "H5Pset_shared_mesg_phase_change");
208     VERIFY(btree_size, b2l, "H5Pset_shared_mesg_phase_change");
209 } /* verify_fcpl_values */
210 
211 
212 /****************************************************************
213 **
214 **  test_sohm_fcpl(): Test File Creation Property Lists.
215 **
216 ****************************************************************/
217 static void
test_sohm_fcpl(void)218 test_sohm_fcpl(void)
219 {
220     hid_t    fid = -1;
221     hid_t    fcpl_id = -1;
222     hid_t    fcpl2_id = -1;
223     unsigned x;
224     herr_t   ret;
225 
226     MESSAGE(5, ("Testing File Creation Properties for Shared Messages\n"));
227 
228     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
229     CHECK_I(fcpl_id, "H5Pcreate");
230 
231     verify_fcpl_values(fcpl_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
232 
233     /* Create a file with this fcpl and make sure that all the values can be
234      * retrieved.
235      */
236     fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
237     CHECK_I(fid, "H5Fcreate");
238 
239     fcpl2_id = H5Fget_create_plist(fid);
240     CHECK_I(fcpl2_id, "H5Fcreate");
241 
242     verify_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
243 
244     ret = H5Pclose(fcpl2_id);
245     CHECK_I(ret, "H5Pclose");
246 
247     /* Close and re-open the file.  Make sure that fcpl values are still
248      * correct.
249      */
250     ret = H5Fclose(fid);
251     CHECK_I(ret, "H5Fclose");
252     fid = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
253     CHECK_I(fid, "H5Fopen");
254 
255     fcpl2_id = H5Fget_create_plist(fid);
256     CHECK_I(ret, "H5Fcreate");
257 
258     verify_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
259 
260     /* Clean up */
261     ret = H5Pclose(fcpl2_id);
262     CHECK_I(ret, "H5Pclose");
263     ret = H5Pclose(fcpl_id);
264     CHECK_I(ret, "H5Pclose");
265     ret = H5Fclose(fid);
266     CHECK_I(ret, "H5Fclose");
267 
268 
269     /* Start over with a non-default fcpl */
270     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
271     CHECK_I(fcpl_id, "H5Pcreate");
272 
273     /* Set up index values */
274     ret = H5Pset_shared_mesg_nindexes(fcpl_id, TEST_NUM_INDEXES);
275     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
276     for(x = 0; x < TEST_NUM_INDEXES; ++x) {
277         ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x], test_minsizes[x]);
278         CHECK_I(ret, "H5Pset_shared_mesg_index");
279     } /* end for */
280 
281     ret = H5Pset_shared_mesg_phase_change(fcpl_id, TEST_L2B, TEST_B2L);
282     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
283 
284     verify_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
285 
286     /* Use the fcpl to create a file and get it back again */
287     fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
288     CHECK_I(fid, "H5Fcreate");
289     fcpl2_id = H5Fget_create_plist(fid);
290     CHECK_I(fcpl2_id, "H5Fcreate");
291 
292     verify_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
293 
294     ret = H5Pclose(fcpl2_id);
295     CHECK_I(ret, "H5Pclose");
296 
297     /* Close and re-open the file.  Make sure that fcpl values are still
298      * correct.
299      */
300     ret = H5Fclose(fid);
301     CHECK_I(ret, "H5Fclose");
302     fid = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
303     CHECK_I(fid, "H5Fopen");
304 
305     fcpl2_id = H5Fget_create_plist(fid);
306     CHECK_I(ret, "H5Fcreate");
307 
308     verify_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
309 
310     /* Clean up */
311     ret = H5Pclose(fcpl2_id);
312     CHECK_I(ret, "H5Pclose");
313     ret = H5Fclose(fid);
314     CHECK_I(ret, "H5Fclose");
315 
316     /* Actually, the list max can be exactly 1 greater than the
317      * btree min, but no more.
318      * Reset the second index.
319      */
320     ret = H5Pset_shared_mesg_index(fcpl_id, 1, test_type_flags[1], 15);
321     CHECK_I(ret, "H5Pset_shared_mesg_index");
322     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 11);
323     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
324     fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
325     CHECK_I(fid, "H5Fcreate");
326     ret = H5Fclose(fid);
327     CHECK_I(ret, "H5Fclose");
328 
329     /* Test edge cases:
330      * H5O_SHMESG_MAX_NINDEXES and H5O_SHMESG_MAX_LIST_SIZE should be valid
331      * values.
332      * Creating a file with uninitialized indexes should work. (TODO: not implemented?)
333      */
334     ret = H5Pset_shared_mesg_nindexes(fcpl_id, H5O_SHMESG_MAX_NINDEXES);
335     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
336     ret = H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE, H5O_SHMESG_MAX_LIST_SIZE);
337     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
338     fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
339     CHECK_I(fid, "H5Fcreate");
340 
341     /* Clean up */
342     ret = H5Pclose(fcpl_id);
343     CHECK_I(ret, "H5Pclose");
344     ret = H5Fclose(fid);
345     CHECK_I(ret, "H5Fclose");
346 } /* test_sohm_fcpl */
347 
348 
349 /****************************************************************
350 **
351 **  test_sohm_fcpl_errors(): Test bogus FCPL settings for SOHMs
352 **
353 ****************************************************************/
354 static void
test_sohm_fcpl_errors(void)355 test_sohm_fcpl_errors(void)
356 {
357     hid_t    fcpl_id = -1;
358     hid_t    fid     = -1;
359     unsigned x;
360     herr_t   ret;
361 
362     MESSAGE(5, ("Testing bogus file creation properties for shared messages\n"));
363 
364     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
365     CHECK_I(fcpl_id, "H5Pcreate");
366 
367     /* Set up index values */
368     ret = H5Pset_shared_mesg_nindexes(fcpl_id, TEST_NUM_INDEXES);
369     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
370     for(x = 0; x < TEST_NUM_INDEXES; ++x) {
371         ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x], test_minsizes[x]);
372         CHECK_I(ret, "H5Pset_shared_mesg_index");
373     }
374 
375     ret = H5Pset_shared_mesg_phase_change(fcpl_id, TEST_L2B, TEST_B2L);
376     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
377 
378     verify_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
379 
380     H5E_BEGIN_TRY {
381         /* Trying to create too many indexes should fail */
382         ret = H5Pset_shared_mesg_nindexes(fcpl_id, H5O_SHMESG_MAX_NINDEXES + 1);
383         VERIFY(ret, -1, "H5Pset_shared_mesg_nindexes");
384 
385         /* Trying to set index to an index higher than the current number
386          * of indexes should fail.
387          */
388         ret = H5Pset_shared_mesg_index(fcpl_id, H5O_SHMESG_MAX_NINDEXES, 0, 15);
389         VERIFY(ret, -1, "H5Pset_shared_mesg_index");
390         ret = H5Pset_shared_mesg_index(fcpl_id, TEST_NUM_INDEXES, 0, 15);
391         VERIFY(ret, -1, "H5Pset_shared_mesg_index");
392 
393         /* Setting an unknown flag (all flags + 1) should fail */
394         ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_ALL_FLAG + 1, 15);
395         VERIFY(ret, -1, "H5Pset_shared_mesg_index");
396 
397         /* Try setting two different indexes to hold fill messages.  They
398          * should hold even very small messages for testing, even though we
399          * wouldn't really want to share such tiny messages in the real world.
400          */
401         ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_FILL_FLAG, 15);
402         CHECK_I(ret, "H5Pset_shared_mesg_index");
403         ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_FILL_FLAG, 15);
404         CHECK_I(ret, "H5Pset_shared_mesg_index");
405         fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
406         VERIFY(fid, -1, "H5Fcreate");
407         ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 15);
408         CHECK_I(ret, "H5Pset_shared_mesg_index");
409         fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
410         VERIFY(fid, -1, "H5Fcreate");
411 
412         /* Test list/btree cutoffs.  We can set these to any positive value,
413          * but if the list max is less than the btree min we'll get an error
414          * when the file is created.
415          */
416         ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 12);
417         VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
418         /* Setting them to extremely large values should also fail */
419         ret = H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE + 1, 0);
420         VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
421         ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, H5O_SHMESG_MAX_LIST_SIZE + 10);
422         VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
423         ret = H5Pset_shared_mesg_phase_change(fcpl_id, H5O_SHMESG_MAX_LIST_SIZE, H5O_SHMESG_MAX_LIST_SIZE+1);
424         VERIFY(ret, -1, "H5Pset_shared_mesg_phase_change");
425     } H5E_END_TRY
426 } /* test_sohm_fcpl_errors */
427 
428 
429 /*-------------------------------------------------------------------------
430  * Function:    make_dtype_1
431  *
432  * Purpose:     Creates a complicated datatype for use in testing
433  *              shared object header messages. The important thing is that
434  *              the datatypes must take a lot of space to store on disk.
435  *
436  * Return:      Success:        datatype ID (should be closed by calling function)
437  *              Failure:        negative
438  *
439  * Programmer:  James Laird
440  *              Saturday, August 26, 2006
441  *
442  *-------------------------------------------------------------------------
443  */
444 static hid_t
make_dtype_1(void)445 make_dtype_1(void)
446 {
447     hid_t dtype1_id = -1;
448     hid_t str_id = -1;
449 
450     /* Create compound datatype. */
451     if((dtype1_id = H5Tcreate(H5T_COMPOUND, sizeof(struct dtype1_struct))) < 0) TEST_ERROR
452 
453     if(H5Tinsert(dtype1_id, "i1", HOFFSET(dtype1_struct, i1), H5T_NATIVE_INT) < 0) TEST_ERROR
454 
455     str_id = H5Tcopy(H5T_C_S1);
456     if(H5Tset_size(str_id, (size_t)10) < 0) TEST_ERROR
457 
458     if(H5Tinsert(dtype1_id, "string", HOFFSET(dtype1_struct, str), str_id) < 0) TEST_ERROR
459     if(H5Tinsert(dtype1_id, "i2", HOFFSET(dtype1_struct, i2), H5T_NATIVE_INT) < 0) TEST_ERROR
460     if(H5Tinsert(dtype1_id, "i3", HOFFSET(dtype1_struct, i3), H5T_NATIVE_INT) < 0) TEST_ERROR
461     if(H5Tinsert(dtype1_id, "i4", HOFFSET(dtype1_struct, i4), H5T_NATIVE_INT) < 0) TEST_ERROR
462     if(H5Tinsert(dtype1_id, "i5", HOFFSET(dtype1_struct, i5), H5T_NATIVE_INT) < 0) TEST_ERROR
463     if(H5Tinsert(dtype1_id, "i6", HOFFSET(dtype1_struct, i6), H5T_NATIVE_INT) < 0) TEST_ERROR
464     if(H5Tinsert(dtype1_id, "i7", HOFFSET(dtype1_struct, i7), H5T_NATIVE_INT) < 0) TEST_ERROR
465     if(H5Tinsert(dtype1_id, "i8", HOFFSET(dtype1_struct, i8), H5T_NATIVE_INT) < 0) TEST_ERROR
466     if(H5Tinsert(dtype1_id, "f1", HOFFSET(dtype1_struct, f1), H5T_NATIVE_FLOAT) < 0) TEST_ERROR
467 
468     if(H5Tclose(str_id) < 0) TEST_ERROR
469 
470     return dtype1_id;
471 
472 error:
473     H5E_BEGIN_TRY {
474       H5Tclose(str_id);
475       H5Tclose(dtype1_id);
476     } H5E_END_TRY
477     return -1;
478 } /* make_dtype1 */
479 
480 
481 /*-------------------------------------------------------------------------
482  * Function:    make_dtype_2
483  *
484  * Purpose:     Creates complicated datatypes for use in testing
485  *              shared object header messages. The important thing is that
486  *              the datatypes must take a lot of space to store on disk.
487  *
488  * Return:      Success:        datatype ID (should be closed by calling function)
489  *              Failure:        negative
490  *
491  * Programmer:  James Laird
492  *              Saturday, August 26, 2006
493  *
494  * Modifications:
495  *
496  *-------------------------------------------------------------------------
497  */
498 static hid_t
make_dtype_2(void)499 make_dtype_2(void)
500 {
501     hid_t dtype2_id = -1;
502     hid_t enum_id= -1;
503     hid_t int_id=-1;
504     int x;
505     hsize_t dims[] = {2, 1, 2, 4};
506     size_t size;
507 
508     /* Create an int with a strange precision */
509     if((int_id = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR
510     if(H5Tset_precision(int_id, (size_t)24) < 0) TEST_ERROR
511 
512     /* Create an enumeration using that int */
513     if((enum_id = H5Tenum_create(int_id)) < 0) TEST_ERROR
514 
515     for(x = 0; x < ENUM_NUM_MEMBS; x++)
516       if(H5Tenum_insert(enum_id, ENUM_NAME[x], &ENUM_VAL[x]) < 0) TEST_ERROR
517 
518     /* Create arrays of arrays of arrays of enums */
519     if((dtype2_id = H5Tarray_create2(enum_id, 3, dims)) < 0) TEST_ERROR
520     if((dtype2_id = H5Tarray_create2(dtype2_id, 4, dims)) < 0) TEST_ERROR
521     if((dtype2_id = H5Tarray_create2(dtype2_id, 2, dims)) < 0) TEST_ERROR
522     if((dtype2_id = H5Tarray_create2(dtype2_id, 1, dims)) < 0) TEST_ERROR
523 
524     if(H5Tclose(enum_id) < 0) TEST_ERROR
525     if(H5Tclose(int_id) < 0) TEST_ERROR
526 
527     /* Check the datatype size.  If this is different than the #defined
528      * size then the fills values will have the wrong size.
529      */
530     size = H5Tget_size(dtype2_id);
531     if(size != DTYPE2_SIZE) TEST_ERROR
532 
533     return dtype2_id;
534 
535 error:
536     H5E_BEGIN_TRY {
537       H5Tclose(dtype2_id);
538       H5Tclose(enum_id);
539       H5Tclose(int_id);
540     } H5E_END_TRY
541     return -1;
542 } /* make_dtype2 */
543 
544 
545 /*-------------------------------------------------------------------------
546  * Function:    close_reopen_file
547  *
548  * Purpose:     Closes a file and then reopens it.  Used to ensure that
549  *              SOHMs are written to and read from disk
550  *
551  * Return:      Success:        new hid_t for the file
552  *              Failure:        Negative
553  *
554  * Programmer:  James Laird
555  *              Wednesday, October 4, 2006
556  *
557  * Modifications:
558  *
559  *-------------------------------------------------------------------------
560  */
561 static hid_t
close_reopen_file(hid_t file,const char * filename,hid_t fapl_id)562 close_reopen_file(hid_t file, const char* filename, hid_t fapl_id)
563 {
564     if (H5Fclose(file) < 0)
565         FAIL_STACK_ERROR
566     file = H5Fopen(filename, H5F_ACC_RDWR, fapl_id);
567     if (file < 0)
568         FAIL_STACK_ERROR
569     return(file);
570 
571 error:
572     return -1;
573 } /* close_reopen_file */
574 
575 
576 /*-------------------------------------------------------------------------
577  * Function:    size1_helper
578  *
579  * Purpose:     Creates object headers that use a large datatype message.
580  *
581  *              Set test_file_closing to TRUE to add file closing and reopening
582  *              whenever possible (to test that SOHMs are written correctly
583  *              on disk and not just in memory).
584  *
585  * Return:      Success:    file ID (may not be the same one passed in)
586  *              Failure:    H5I_INVALID_HID
587  *
588  * Programmer:  James Laird
589  *              Monday, April 10, 2006
590  *
591  *-------------------------------------------------------------------------
592  */
593 static hid_t
size1_helper(hid_t file,const char * filename,hid_t fapl_id,hbool_t test_file_closing)594 size1_helper(hid_t file, const char *filename, hid_t fapl_id, hbool_t test_file_closing)
595 {
596     dtype1_struct wdata;
597     dtype1_struct rdata;
598     hid_t       dtype1_id = H5I_INVALID_HID;
599     hid_t       space_id = H5I_INVALID_HID;
600     hid_t       dset_id = H5I_INVALID_HID;
601     hsize_t     dim1[1];
602     int         x;
603 
604 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
605  * Macro:      TSOHM_S1H_VERIFY_DATA
606  *
607  * Purpose:    Encapsulate a common pattern:
608  *             Reads the dataset and verifies that [a subset of] the data
609  *             are as expected.
610  *
611  * Programmer: Jacob Smith
612  *             2018 November 1
613  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
614  */
615 #define TSOHM_S1H_VERIFY_DATA(dset_id, dtype_id) \
616 {                                                \
617     HDmemset(&rdata, 0, sizeof(rdata));          \
618     if (0 > H5Dread((dset_id), (dtype_id), H5S_ALL, H5S_ALL, H5P_DEFAULT, &rdata)) { \
619         H5_FAILED(); AT();                       \
620         HDprintf("Can't read data\n");             \
621         goto error;                              \
622     }                                            \
623     if ((rdata.i1 != wdata.i1) || (rdata.i2 != wdata.i2) || HDstrcmp(rdata.str, wdata.str)) { \
624         H5_FAILED(); AT();                       \
625         HDprintf("incorrect read data\n");         \
626         goto error;                              \
627     }                                            \
628 } /* TSOHM_S1H_VERIFY_DATA() definition */
629 
630     /* Closing and re-opening the file takes a long time on systems without
631      * local disks.  Don't close and reopen if express testing is enabled.
632      */
633     if(GetTestExpress() > 1)
634       test_file_closing = FALSE;
635 
636     /* Intialize wdata */
637     HDmemset(&wdata, 0, sizeof(wdata));
638     wdata.i1 = 11;
639     HDstrcpy(wdata.str, "string");
640     wdata.i2 = 22;
641     wdata.i3 = 33;
642     wdata.i4 = 44;
643     wdata.i5 = 55;
644     wdata.i6 = 66;
645     wdata.i7 = 77;
646     wdata.i8 = 88;
647     wdata.f1 = 0.0F;
648 
649     /* Intialize rdata */
650     HDmemset(&rdata, 0, sizeof(rdata));
651 
652     dtype1_id = make_dtype_1();
653     if(dtype1_id < 0) TEST_ERROR
654 
655     dim1[0] = 1;
656     space_id = H5Screate_simple(1, dim1, NULL);
657     if(space_id < 0) TEST_ERROR
658 
659     dset_id = H5Dcreate2(file, DSETNAME[0], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
660     if(dset_id < 0) FAIL_STACK_ERROR
661 
662     /* Test writing and reading */
663     if(H5Dwrite(dset_id, dtype1_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata) < 0) FAIL_STACK_ERROR
664     TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
665     if(H5Dclose(dset_id) < 0) FAIL_STACK_ERROR
666 
667     if(test_file_closing)
668         if((file = close_reopen_file(file, filename, fapl_id)) < 0) TEST_ERROR
669 
670     /* Create 3 more datasets with the same datatype/dataspace */
671     for (x = 1; x < 4; x++) {
672         dset_id = H5Dcreate2(file, DSETNAME[x], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
673         if (0 > dset_id) FAIL_STACK_ERROR
674         if (x == 3)
675             if(H5Dwrite(dset_id, dtype1_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata) < 0) TEST_ERROR
676         if (H5Dclose(dset_id) < 0) FAIL_STACK_ERROR
677 
678         if (test_file_closing)
679             if((file = close_reopen_file(file, filename, fapl_id)) < 0) TEST_ERROR
680     }
681 
682     if(H5Tclose(dtype1_id) < 0) TEST_ERROR
683 
684     /* Make sure the data has been written successfully */
685     dset_id = H5Dopen2(file, DSETNAME[0], H5P_DEFAULT);
686     if(dset_id < 0) TEST_ERROR
687     dtype1_id = H5Dget_type(dset_id);
688     if(dtype1_id < 0) TEST_ERROR
689     TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
690 
691     if(H5Dclose(dset_id) < 0) TEST_ERROR
692 
693     /* Create several copies of the dataset
694      * this increases the amount of space saved by sharing the datatype message
695      */
696     for(x = 0; x < SOHM_HELPER_NUM_EX_DSETS; x++) {
697         dset_id = H5Dcreate2(file, EXTRA_DSETNAME[x], dtype1_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
698         if(dset_id < 0) TEST_ERROR
699         if(H5Dclose(dset_id) < 0) TEST_ERROR
700 
701         if(test_file_closing)
702             if((file = close_reopen_file(file, filename, fapl_id)) < 0) TEST_ERROR
703     }
704 
705     if(H5Tclose(dtype1_id) < 0) TEST_ERROR
706     if(H5Sclose(space_id) < 0) TEST_ERROR
707 
708     /* Ensure that we can still read data back from dataset 3 */
709     dset_id = H5Dopen2(file, DSETNAME[3], H5P_DEFAULT);
710     if(dset_id < 0) TEST_ERROR
711     dtype1_id = H5Dget_type(dset_id);
712     if(dtype1_id < 0) TEST_ERROR
713     TSOHM_S1H_VERIFY_DATA(dset_id, dtype1_id)
714 
715     if(H5Dclose(dset_id) < 0) TEST_ERROR
716     if(H5Tclose(dtype1_id) < 0) TEST_ERROR
717 
718     return file;
719 
720  error:
721     H5E_BEGIN_TRY {
722         H5Sclose(space_id);
723         H5Tclose(dtype1_id);
724         H5Dclose(dset_id);
725         H5Fclose(file);
726     } H5E_END_TRY
727 
728     return H5I_INVALID_HID;
729 #undef TSOHM_S1H_VERIFY_DATA /* macro is exclusive to this function */
730 } /* size1_helper */
731 
732 
733 /*----------------------------------------------------------------------------
734  * Function: getsize_testsize1
735  *
736  * Purpose: Creates a test file, populates it, and returns its file size.
737  *          Oject header information from the "first" dataset in the file
738  *          is stored in pointer `oinfo`.
739  *
740  * Programmer: Jacob Smith
741  *             2018 November 1
742  *----------------------------------------------------------------------------
743  */
744 static h5_stat_size_t
getsize_testsize1(const char * filename,hid_t fcpl_id,hid_t fapl_id,hbool_t test_file_closing,H5O_info_t * oinfo)745 getsize_testsize1(const char *filename, hid_t fcpl_id, hid_t fapl_id,
746     hbool_t test_file_closing, H5O_info_t *oinfo)
747 {
748     hid_t fid = H5I_INVALID_HID;
749     herr_t ret;
750 
751     fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, fapl_id);
752     CHECK(fid, H5I_INVALID_HID, "H5Fcreate");
753 
754     /* If test_file_closing is TRUE, you will get back a different ID,
755      * which will need to be closed. The helper will close your passed-in
756      * ID.
757      */
758     fid = size1_helper(fid, filename, fapl_id, test_file_closing);
759     CHECK(fid, H5I_INVALID_HID, "size1_helper");
760 
761     ret = H5Oget_info_by_name2(fid, DSETNAME[0], oinfo, H5O_INFO_HDR, H5P_DEFAULT);
762     CHECK(ret, FAIL, "H5Oget_info_by_name");
763 
764     ret = H5Fclose(fid);
765     CHECK(ret, FAIL, "H5Fclose");
766 
767     return h5_get_file_size(filename, fapl_id);
768 } /* getsize_testsize1() */
769 
770 
771 /*-------------------------------------------------------------------------
772  * Function:    test_sohm_size1
773  *
774  * Purpose:     Tests shared object header messages with a large datatype
775  *
776  * Programmer:  James Laird
777  *              Monday, April 10, 2006
778  *
779  *-------------------------------------------------------------------------
780  */
781 static void
test_sohm_size1(void)782 test_sohm_size1(void)
783 {
784     hid_t       file = -1;
785     hid_t       fcpl_id = -1;
786     hid_t       fapl_id = -1;
787 
788     unsigned       use_shared = 0;
789     unsigned       use_btree = 0;
790     h5_stat_size_t file_sizes[9];
791     unsigned       size_index = 0;
792     hsize_t        oh_sizes[3];
793     unsigned       oh_size_index = 0;
794 
795 #if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
796     hsize_t        norm_oh_size;
797 #endif /* Jira HDFFV-10646 */
798     hsize_t        sohm_oh_size;
799     hsize_t        sohm_btree_oh_size;
800     h5_stat_size_t norm_empty_filesize;
801     h5_stat_size_t sohm_empty_filesize;
802     h5_stat_size_t sohm_btree_empty_filesize;
803     h5_stat_size_t norm_final_filesize;
804     h5_stat_size_t sohm_final_filesize;
805     h5_stat_size_t sohm_btree_final_filesize;
806     h5_stat_size_t norm_final_filesize2;
807     h5_stat_size_t sohm_final_filesize2;
808     h5_stat_size_t sohm_btree_final_filesize2;
809 
810     H5O_info_t  oinfo;
811     unsigned    num_indexes = 1;
812     unsigned    index_flags = H5O_SHMESG_DTYPE_FLAG;
813     unsigned    min_mesg_size = 50;
814     unsigned    list_max = 11;
815     unsigned    btree_min = 10;
816     herr_t      ret;
817 
818     MESSAGE(5, ("Testing that shared datatypes save space\n"));
819 
820     /* Create a FAPL with "semi" close degree, to detect dangling IDs */
821     fapl_id = H5Pcreate(H5P_FILE_ACCESS);
822     CHECK_I(fapl_id, "H5Pcreate");
823     ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
824     CHECK_I(ret, "H5Pset_fclose_degree");
825 
826     /* ----------------------------------------
827      * Run operations, accumulating file sizes to compare later.
828      */
829 
830     for (use_shared = 0; use_shared < 2; use_shared++) {
831         for (use_btree = 0; use_btree < 2; use_btree++) {
832             hbool_t test_open_close;
833 
834             /* cannot use btree indexing without shared messages; skip case */
835             if (use_btree && !use_shared)
836                 continue;
837 
838             fcpl_id = H5Pcreate(H5P_FILE_CREATE);
839             CHECK_I(fcpl_id, "H5Pcreate");
840 
841             if (use_shared) {
842                 /* Tests one index holding only datatype messages */
843                 ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
844                 CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
845                 ret = H5Pset_shared_mesg_index(fcpl_id, 0, index_flags, min_mesg_size);
846                 CHECK_I(ret, "H5Pset_shared_mesg_index");
847 
848                 if (use_btree) {
849                     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
850                 } else {
851                     ret = H5Pset_shared_mesg_phase_change(fcpl_id, list_max, btree_min);
852                 }
853                 CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
854             } else {
855                 ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
856                 CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
857             }
858 
859             file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
860             CHECK_I(file, "H5Fcreate");
861             ret = H5Fclose(file);
862             CHECK_I(ret, "H5Fclose");
863 
864             /* size of empty file */
865             file_sizes[size_index++] = h5_get_file_size(FILENAME, fapl_id);
866 
867             /* size of populated file, with different populating behaviors */
868             test_open_close = TRUE;
869             file_sizes[size_index++] = getsize_testsize1(FILENAME, fcpl_id, fapl_id, test_open_close, &oinfo);
870             test_open_close = FALSE;
871             file_sizes[size_index++] = getsize_testsize1(FILENAME, fcpl_id, fapl_id, test_open_close, &oinfo);
872             oh_sizes[oh_size_index++] = oinfo.hdr.space.total;
873 
874             ret = H5Pclose(fcpl_id);
875             CHECK_I(ret, "H5Pclose");
876         } /* for btree/listed messages */
877     } /* for normal/shared messages */
878 
879     ret = H5Pclose(fapl_id);
880     CHECK_I(ret, "H5Pclose");
881 
882     /* sanity-check state of arrays */
883     VERIFY(9, size_index, "size_index");
884     VERIFY(3, oh_size_index, "oh_size_index");
885 
886     /* ----------------------------------------
887      * Check that all sizes make sense.
888      */
889 
890     /* Put result sizes into human-readable symbolic names.
891      * Order dependent on loop execution above.
892      */
893     norm_empty_filesize = file_sizes[0];
894     norm_final_filesize = file_sizes[1];
895     norm_final_filesize2 = file_sizes[2];
896 #if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
897     norm_oh_size = oh_sizes[0];
898 #endif /* Jira HDFFV-10646 */
899 
900     sohm_empty_filesize = file_sizes[3];
901     sohm_final_filesize = file_sizes[4];
902     sohm_final_filesize2 = file_sizes[5];
903     sohm_oh_size = oh_sizes[1];
904 
905     sohm_btree_empty_filesize = file_sizes[6];
906     sohm_btree_final_filesize = file_sizes[7];
907     sohm_btree_final_filesize2 = file_sizes[8];
908     sohm_btree_oh_size = oh_sizes[2];
909 
910     /* How the SOHM messages are stored shouldn't affect the
911      * size of the object header.
912      */
913     VERIFY(sohm_btree_oh_size, sohm_oh_size, "H5Oget_info_by_name");
914 
915 #if 0 /* TBD: lying comment or bug. See Jira HDFFV-10646 */
916     /* Object headers in SOHM files should be smaller than normal object
917      * headers.
918      */
919     if (sohm_oh_size >= norm_oh_size)
920         VERIFY(norm_oh_size, 1, "H5Oget_info_by_name");
921 #endif /* Jira HDFFV-10646 */
922 
923     /* Both sohm files should be bigger than a normal file when empty.
924      * It's hard to say whether a B-tree with no nodes allocated should be
925      * smaller than a list with SOHM_HELPER_NUM_DTYPES elements.
926      * The sizes here shouldn't really be 1; it's just used to ensure that the
927      * error code triggers.
928      */
929     if(sohm_empty_filesize <= norm_empty_filesize)
930         VERIFY(sohm_empty_filesize, 1, "h5_get_file_size");
931 
932     if(sohm_btree_empty_filesize <= norm_empty_filesize)
933         VERIFY(sohm_btree_empty_filesize, 1, "h5_get_file_size");
934 
935     /* When full, the sohm btree file should be smaller than the normal file.
936      * The sohm list file should be at least as small, since it doesn't need
937      * the overhead of a B-tree.
938      */
939     if(sohm_btree_final_filesize >= norm_final_filesize)
940         VERIFY(sohm_btree_final_filesize, 1, "h5_get_file_size");
941     if(sohm_final_filesize > sohm_btree_final_filesize)
942         VERIFY(sohm_final_filesize, 1, "h5_get_file_size");
943 
944     /* Comparative sizes shouldn't change even if we open and close the file
945      */
946     if(sohm_btree_final_filesize2 >= norm_final_filesize2)
947         VERIFY(sohm_btree_final_filesize2, 1, "h5_get_file_size");
948     if(sohm_final_filesize2 > sohm_btree_final_filesize2)
949         VERIFY(sohm_final_filesize2, 1, "h5_get_file_size");
950 
951 } /* test_sohm_size1 */
952 
953 
954 /*---------------------------------------------------------------------------
955  * Function:    test_sohm_size_consistency_open_create
956  *
957  * Purpose:     Tests that header size is different depending on file open
958  *              procedure?
959  *              Uses "size1_helper" for file setup directed to a specific
960  *              file handle.
961  *
962  * Programmer:  Jacob Smith
963  *              2018 November 1
964  *
965  *---------------------------------------------------------------------------
966  */
967 #if 0 /* TODO: REVEALS BUG TO BE FIXED - SEE JIRA HDFFV-10645 */
968 static void
969 test_sohm_size_consistency_open_create(void)
970 {
971     hid_t       file = -1;
972     hid_t       fcpl_id = -1;
973     hid_t       fapl_id = -1;
974     unsigned    use_btree;
975     hsize_t     oh_size_open;
976     hsize_t     oh_size_create;
977     H5O_info_t  oinfo;
978     unsigned    num_indexes = 1;
979     unsigned    index_flags = H5O_SHMESG_DTYPE_FLAG;
980     unsigned    min_mesg_size = 50;
981     unsigned    list_max = 11;
982     unsigned    btree_min = 10;
983     herr_t      ret;
984 
985     MESSAGE(5, \
986     ("Testing that header size is consistent between H5Fopen and H5Fcreate\n"));
987 
988     /* Create a FAPL with "semi" close degree, to detect dangling IDs */
989     fapl_id = H5Pcreate(H5P_FILE_ACCESS);
990     CHECK_I(fapl_id, "H5Pcreate");
991     ret = H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI);
992     CHECK_I(ret, "H5Pset_fclose_degree");
993 
994     for (use_btree = 0; use_btree < 2; use_btree++) {
995         /* Create FCPL with SOHMs enabled
996          */
997         fcpl_id = H5Pcreate(H5P_FILE_CREATE);
998         CHECK_I(fcpl_id, "H5Pcreate");
999         ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
1000         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1001         ret = H5Pset_shared_mesg_index(fcpl_id, 0, index_flags, min_mesg_size);
1002         CHECK_I(ret, "H5Pset_shared_mesg_index");
1003         if (use_btree) {
1004             MESSAGE(5, ("----testing with btree index----\n"));
1005             ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
1006             CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
1007         } else {
1008             MESSAGE(5, ("----testing with normal index----\n"));
1009             ret = H5Pset_shared_mesg_phase_change(fcpl_id, list_max, btree_min);
1010             CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
1011         }
1012 
1013         /* Create empty file */
1014         file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
1015         CHECK_I(file, "H5Fcreate");
1016         ret = H5Fclose(file);
1017         CHECK_I(ret, "H5Fclose");
1018 
1019         /* Test Open/Write
1020          * Add messages to previously-created file */
1021         file = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_id);
1022         CHECK_I(file, "H5Fopen");
1023         file = size1_helper(file, FILENAME, fapl_id, FALSE);
1024         CHECK_I(file, "size1_helper");
1025 
1026         /* Get the size of a dataset object header */
1027         ret = H5Oget_info_by_name2(file, DSETNAME[0], &oinfo, H5O_INFO_HDR, H5P_DEFAULT);
1028         CHECK_I(ret, "H5Oget_info_by_name");
1029         oh_size_open = oinfo.hdr.space.total;
1030 
1031         ret = H5Fclose(file);
1032         CHECK_I(ret, "H5Fclose");
1033 
1034         /* Test Create/Write
1035          * Add messages to a newly-created file */
1036         file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, fapl_id);
1037         CHECK_I(file, "H5Fcreate");
1038         file = size1_helper(file, FILENAME, fapl_id, FALSE);
1039         CHECK_I(file, "size1_helper");
1040 
1041         /* Get the size of a dataset object header */
1042         ret = H5Oget_info_by_name2(file, DSETNAME[0], &oinfo, H5O_INFO_HDR, H5P_DEFAULT);
1043         CHECK_I(ret, "H5Oget_info_by_name");
1044         oh_size_create = oinfo.hdr.space.total;
1045 
1046         ret = H5Fclose(file);
1047         CHECK_I(ret, "H5Fclose");
1048 
1049         VERIFY(oh_size_create, oh_size_open, "H5Oget_info_by_name2");
1050 
1051         ret = H5Pclose(fcpl_id);
1052         CHECK_I(ret, "H5Pclose");
1053     } /* for normal/btree indexing */
1054 
1055     ret = H5Pclose(fapl_id);
1056     CHECK_I(ret, "H5Pclose");
1057 } /* test_sohm_size_consistency_open_create */
1058 #endif /* Jira HDFFV-10645 */
1059 
1060 
1061 /*-------------------------------------------------------------------------
1062  * Function:    sohm_attr_helper
1063  *
1064  * Purpose:     Given an fcpl, tests creating attributes with and without
1065  *              committed datatypes.
1066  *              Verify that an attribute can be written and read back.
1067  *              Tests attribute on a Group.
1068  *              Tests committed and non-committed datatypes.
1069  *              Tests attribute access through `H5Aopen()`.
1070  *
1071  * Programmer:  James Laird
1072  *              Thursday, November 30, 2006
1073  *
1074  *-------------------------------------------------------------------------
1075  */
1076 static void
sohm_attr_helper(hid_t fcpl_id)1077 sohm_attr_helper(hid_t fcpl_id)
1078 {
1079     hid_t file_id;
1080     hid_t space_id;
1081     hsize_t dims = 2;
1082     int wdata[2] = {7, 42};
1083     int rdata[2];
1084     herr_t ret;
1085     size_t x;
1086     unsigned op_index=0;
1087 #define TSOHM_SAH_OP_COUNT 3
1088     const char *groupnames[TSOHM_SAH_OP_COUNT] = {
1089         "group_for_nothing_special",
1090         "group_for_commited_dtype",
1091         "group_for_commited_dtype_and_other_ID_access",
1092     };
1093 
1094     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
1095     CHECK_I(file_id, "H5Fcreate");
1096 
1097     space_id = H5Screate_simple(1, &dims, &dims);
1098     CHECK_I(space_id, "H5Screate_simple");
1099 
1100     /* loop:
1101      * 0 - nothing special
1102      * 1 - committed datatype
1103      * 2 - committed datatype, read through second ID
1104      */
1105     for (op_index = 0; op_index < TSOHM_SAH_OP_COUNT; op_index++) {
1106         hid_t type_id  = -1;
1107         hid_t group_id = -1;
1108         hid_t attr_id  = -1;
1109         hid_t attr_id2 = -1;
1110         hid_t attr_read_id;
1111 
1112         /* create group in file with name unique to op_index */
1113         group_id = H5Gcreate2(file_id, groupnames[op_index], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1114         CHECK_I(group_id, "H5Gcreate2");
1115 
1116         type_id = H5Tcopy(H5T_NATIVE_INT);
1117         CHECK_I(type_id, "H5Tcopy");
1118 
1119         /* Commit the datatype for the latter iterations.
1120          * Only do this ONCE.
1121          */
1122         if (op_index == 1) {
1123             ret = H5Tcommit2(file_id, "datatype", type_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1124             CHECK_I(ret, "H5Tcommit2");
1125         }
1126 
1127         attr_id = H5Acreate2(group_id, "attribute", type_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
1128         CHECK_I(attr_id, "H5Acreate2");
1129 
1130         if (op_index == 2) {
1131             /* Open the attribute to get another handle */
1132             attr_id2 = H5Aopen(group_id, "attribute", H5P_DEFAULT);
1133             CHECK_I(attr_id2, "H5Aopen");
1134         }
1135 
1136         ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata);
1137         CHECK_I(ret, "H5Awrite");
1138 
1139         ret = H5Gclose(group_id);
1140         CHECK_I(ret, "H5Gclose");
1141         ret = H5Tclose(type_id);
1142         CHECK_I(ret, "H5Tclose");
1143 
1144         /* Flush the file to force data to be written */
1145         ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
1146         CHECK_I(ret, "H5Fflush");
1147 
1148         /* Verify */
1149         attr_read_id = (op_index == 2) ? attr_id2 : attr_id;
1150         HDmemset(rdata, 0, sizeof(rdata));
1151         ret = H5Aread(attr_read_id, H5T_NATIVE_INT, rdata);
1152         CHECK_I(ret, "H5Aread");
1153         for(x = 0; x < (size_t)dims; ++x)
1154             VERIFY(rdata[x], wdata[x], "H5Aread");
1155 
1156         ret = H5Aclose(attr_id);
1157         CHECK_I(ret, "H5Aclose");
1158         if (attr_id2 > -1 ) {
1159             ret = H5Aclose(attr_id2);
1160             CHECK_I(ret, "H5Aclose");
1161         }
1162     } /* for each attribute operation */
1163 
1164     ret = H5Sclose(space_id);
1165     CHECK_I(ret, "H5Sclose");
1166     ret = H5Fclose(file_id);
1167     CHECK_I(ret, "H5Fclose");
1168 #undef TSOHM_SAH_OP_COUNT
1169 } /* sohm_attr_helper */
1170 
1171 
1172 /*-------------------------------------------------------------------------
1173  * Function:    test_sohm_attrs
1174  *
1175  * Purpose:     Attributes can be shared and can also contain shared
1176  *              datatype and dataspace messages.  Committed datatypes
1177  *              shouldn't be shared.
1178  *
1179  *              Test permutations of this.
1180  *
1181  * Programmer:  James Laird
1182  *              Thursday, November 30, 2006
1183  *
1184  *-------------------------------------------------------------------------
1185  */
1186 static void
test_sohm_attrs(void)1187 test_sohm_attrs(void)
1188 {
1189     hid_t bad_fid = H5I_INVALID_HID;
1190     hid_t fcpl_id = H5I_INVALID_HID;
1191     unsigned i = 0;
1192 #define TSOHM_TSA_NFLAGS_1 7
1193     unsigned flags1[TSOHM_TSA_NFLAGS_1] = {
1194         H5O_SHMESG_ATTR_FLAG,
1195         H5O_SHMESG_SDSPACE_FLAG,
1196         H5O_SHMESG_DTYPE_FLAG,
1197         H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
1198         H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
1199         H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
1200         H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
1201     };
1202 #define TSOHM_TSA_NFLAGS_2 6
1203     unsigned flags2[TSOHM_TSA_NFLAGS_2][2] = {
1204         {   H5O_SHMESG_ATTR_FLAG,
1205             H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
1206         },
1207         {   H5O_SHMESG_SDSPACE_FLAG,
1208             H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
1209         },
1210         {   H5O_SHMESG_DTYPE_FLAG,
1211             H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
1212         },
1213         {   H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
1214             H5O_SHMESG_ATTR_FLAG,
1215         },
1216         {   H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_DTYPE_FLAG,
1217             H5O_SHMESG_SDSPACE_FLAG,
1218         },
1219         {   H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG,
1220             H5O_SHMESG_DTYPE_FLAG,
1221         },
1222     };
1223 #define TSOHM_TSA_NFLAGS_3 5
1224     unsigned flags3[TSOHM_TSA_NFLAGS_3][3] = {
1225         {   H5O_SHMESG_ATTR_FLAG,
1226             H5O_SHMESG_SDSPACE_FLAG,
1227             H5O_SHMESG_DTYPE_FLAG,
1228         },
1229         {   H5O_SHMESG_DTYPE_FLAG,
1230             H5O_SHMESG_ATTR_FLAG,
1231             H5O_SHMESG_SDSPACE_FLAG,
1232         },
1233         {   H5O_SHMESG_SDSPACE_FLAG,
1234             H5O_SHMESG_DTYPE_FLAG,
1235             H5O_SHMESG_ATTR_FLAG,
1236         },
1237         {   0, /* first index does not hold a shared message type? */
1238             H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG,
1239             H5O_SHMESG_ATTR_FLAG,
1240         },
1241         {   0, /* missing SDSPACE flag */
1242             H5O_SHMESG_DTYPE_FLAG,
1243             H5O_SHMESG_ATTR_FLAG,
1244         },
1245     };
1246     herr_t ret;
1247 
1248     MESSAGE(5, ("Testing that shared messages work with attributes\n"));
1249 
1250     /* No shared messages
1251      */
1252     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
1253     CHECK_I(fcpl_id, "H5Pcreate");
1254     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
1255     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1256 
1257     sohm_attr_helper(fcpl_id);
1258 
1259     ret = H5Pclose(fcpl_id);
1260     CHECK_I(ret, "H5Pclose");
1261 
1262     /* One shared message index
1263      */
1264     for (i=0; i < TSOHM_TSA_NFLAGS_1; i++) {
1265         fcpl_id = H5Pcreate(H5P_FILE_CREATE);
1266         CHECK_I(fcpl_id, "H5Pcreate");
1267         ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
1268         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1269         ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags1[i], 2);
1270         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1271 
1272         sohm_attr_helper(fcpl_id);
1273 
1274         ret = H5Pclose(fcpl_id);
1275         CHECK_I(ret, "H5Pclose");
1276     }
1277 
1278     /* two shared message indices
1279      */
1280     for (i=0; i < TSOHM_TSA_NFLAGS_2; i++) {
1281         fcpl_id = H5Pcreate(H5P_FILE_CREATE);
1282         CHECK_I(fcpl_id, "H5Pcreate");
1283         ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
1284         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1285         ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags2[i][0], 2);
1286         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1287         ret = H5Pset_shared_mesg_index(fcpl_id, 1, flags2[i][1], 2);
1288         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1289 
1290         sohm_attr_helper(fcpl_id);
1291 
1292         ret = H5Pclose(fcpl_id);
1293         CHECK_I(ret, "H5Pclose");
1294     }
1295 
1296     /* duplicate flags in separate indices causes problems
1297      */
1298     H5E_BEGIN_TRY {
1299         fcpl_id = H5Pcreate(H5P_FILE_CREATE);
1300         CHECK_I(fcpl_id, "H5Pcreate");
1301         ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
1302         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1303         ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ATTR_FLAG, 2);
1304         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1305         ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_ATTR_FLAG, 2);
1306         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1307 
1308         bad_fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
1309         VERIFY(bad_fid, H5I_INVALID_HID, "H5Fcreate");
1310 
1311         ret = H5Pclose(fcpl_id);
1312         CHECK_I(ret, "H5Pclose");
1313     } H5E_END_TRY;
1314 
1315     /* three shared message indices
1316      */
1317     for (i=0; i < TSOHM_TSA_NFLAGS_3; i++) {
1318         fcpl_id = H5Pcreate(H5P_FILE_CREATE);
1319         CHECK_I(fcpl_id, "H5Pcreate");
1320         ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
1321         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1322         ret = H5Pset_shared_mesg_index(fcpl_id, 0, flags3[i][0], 2);
1323         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1324         ret = H5Pset_shared_mesg_index(fcpl_id, 1, flags3[i][1], 2);
1325         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1326         ret = H5Pset_shared_mesg_index(fcpl_id, 2, flags3[i][2], 2);
1327         CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
1328 
1329         sohm_attr_helper(fcpl_id);
1330 
1331         ret = H5Pclose(fcpl_id);
1332         CHECK_I(ret, "H5Pclose");
1333     }
1334 
1335 #undef TSOHM_TSA_NFLAGS_1
1336 #undef TSOHM_TSA_NFLAGS_2
1337 #undef TSOHM_TSA_NFLAGS_3
1338 
1339 } /* test_sohm_attrs */
1340 
1341 
1342 /*-------------------------------------------------------------------------
1343  * Function:    size2_verify_plist1
1344  *
1345  * Purpose:     Verify that the property list passed in is in fact the
1346  *              same property list used as dcpl1_id in the size2 helper
1347  *              function.  This ensures that the filters can be read.
1348  *
1349  * Programmer:  James Laird
1350  *              Wednesday, November 22, 2006
1351  *
1352  *-------------------------------------------------------------------------
1353  */
1354 static void
size2_verify_plist1(hid_t plist)1355 size2_verify_plist1(hid_t plist)
1356 {
1357     size_t cd_nelmts;
1358     unsigned int cd_value;
1359     char name[NAME_BUF_SIZE];
1360     H5Z_filter_t filter;
1361     hid_t dtype1_id;
1362     dtype1_struct fill1;
1363     dtype1_struct fill1_correct;
1364     herr_t ret;
1365 
1366     /* Hardcoded to correspond to dcpl1_id created in size2_helper */
1367     /* Check filters */
1368     cd_nelmts = 1;
1369     filter = H5Pget_filter2(plist, 0, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1370     CHECK_I(filter, "H5Pget_filter2");
1371     VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter2");
1372 
1373     cd_nelmts = 1;
1374     filter = H5Pget_filter2(plist, 1, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1375     CHECK_I(filter, "H5Pget_filter2");
1376     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1377     VERIFY(cd_value, 1, "H5Pget_filter2");
1378 
1379     cd_nelmts = 1;
1380     filter = H5Pget_filter2(plist, 2, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1381     CHECK_I(filter, "H5Pget_filter2");
1382     VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter2");
1383 
1384     cd_nelmts = 1;
1385     filter = H5Pget_filter2(plist, 3, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1386     CHECK_I(filter, "H5Pget_filter2");
1387     VERIFY(filter, H5Z_FILTER_FLETCHER32, "H5Pget_filter2");
1388 
1389 
1390     /* Check fill value */
1391     dtype1_id=make_dtype_1();
1392     CHECK_I(dtype1_id, "make_dtype_1");
1393     HDmemset(&fill1_correct, '1', sizeof(fill1_correct));
1394 
1395     ret = H5Pget_fill_value(plist, dtype1_id, &fill1);
1396     CHECK_I(ret, "H5Pget_fill_value");
1397 
1398     ret = HDmemcmp(&fill1, &fill1_correct, sizeof(fill1_correct));
1399     VERIFY(ret, 0, "memcmp");
1400 
1401     ret = H5Tclose(dtype1_id);
1402     CHECK_I(ret, "H5Tclose");
1403 } /* size2_verify_plist1 */
1404 
1405 
1406 /*-------------------------------------------------------------------------
1407  * Function:    size2_verify_plist2
1408  *
1409  * Purpose:     Verify that the property list passed in is in fact the
1410  *              same property list used as dcpl2_id in the size2 helper
1411  *              function.  This ensures that the filters can be read.
1412  *
1413  * Programmer:  James Laird
1414  *              Wednesday, November 22, 2006
1415  *
1416  *-------------------------------------------------------------------------
1417  */
1418 static void
size2_verify_plist2(hid_t plist)1419 size2_verify_plist2(hid_t plist)
1420 {
1421     size_t cd_nelmts;
1422     unsigned int cd_value;
1423     char name[NAME_BUF_SIZE];
1424     H5Z_filter_t filter;
1425     hid_t dtype2_id;
1426     char fill2[DTYPE2_SIZE];
1427     char fill2_correct[DTYPE2_SIZE];
1428     herr_t ret;
1429 
1430     /* Hardcoded to correspond to dcpl1_id created in size2_helper */
1431     /* Check filters */
1432     cd_nelmts = 1;
1433     filter = H5Pget_filter2(plist, 0, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1434     CHECK_I(filter, "H5Pget_filter2");
1435     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1436     VERIFY(cd_value, 1, "H5Pget_filter2");
1437 
1438     cd_nelmts = 1;
1439     filter = H5Pget_filter2(plist, 1, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1440     CHECK_I(filter, "H5Pget_filter2");
1441     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1442     VERIFY(cd_value, 2, "H5Pget_filter2");
1443 
1444     cd_nelmts = 1;
1445     filter = H5Pget_filter2(plist, 2, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1446     CHECK_I(filter, "H5Pget_filter2");
1447     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1448     VERIFY(cd_value, 2, "H5Pget_filter2");
1449 
1450     cd_nelmts = 1;
1451     filter = H5Pget_filter2(plist, 3, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1452     CHECK_I(filter, "H5Pget_filter2");
1453     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1454     VERIFY(cd_value, 1, "H5Pget_filter2");
1455 
1456     cd_nelmts = 1;
1457     filter = H5Pget_filter2(plist, 4, NULL, &cd_nelmts, &cd_value, (size_t)NAME_BUF_SIZE, name, NULL);
1458     CHECK_I(filter, "H5Pget_filter2");
1459     VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter2");
1460     VERIFY(cd_value, 5, "H5Pget_filter2");
1461 
1462 
1463     /* Check fill value */
1464     dtype2_id = make_dtype_2();
1465     CHECK_I(dtype2_id, "make_dtype_2");
1466     HDmemset(&fill2_correct, '2', (size_t)DTYPE2_SIZE);
1467 
1468     ret = H5Pget_fill_value(plist, dtype2_id, &fill2);
1469     CHECK_I(ret, "H5Pget_fill_value");
1470 
1471     ret = HDmemcmp(&fill2, &fill2_correct, (size_t)DTYPE2_SIZE);
1472     VERIFY(ret, 0, "memcmp");
1473 
1474     ret = H5Tclose(dtype2_id);
1475     CHECK_I(ret, "H5Tclose");
1476 } /* size2_verify_plist2 */
1477 
1478 #ifdef NOT_NOW
1479 
1480 /*-------------------------------------------------------------------------
1481  * Function:    size2_dump_struct
1482  *
1483  * Purpose:     A debugging function to print the contents of a
1484  *              size2_helper_struct (which holds the various sizes for a
1485  *              given file during the size2_helper function).
1486  *
1487  * Programmer:  James Laird
1488  *              Friday, January 26, 2007
1489  *
1490  * Modifications:
1491  *
1492  *-------------------------------------------------------------------------
1493  */
1494 static void
size2_dump_struct(const char * name,size2_helper_struct * sizes)1495 size2_dump_struct(const char *name, size2_helper_struct *sizes)
1496 {
1497   HDputs(name);
1498   HDprintf("    empty size: %llu\n", (unsigned long long)sizes->empty_size);
1499   HDprintf(" first dataset: %llu \tdelta: %llu\n", (unsigned long long)sizes->first_dset, (unsigned long long)(sizes->first_dset - sizes->empty_size));
1500   HDprintf("second dataset: %llu \tdelta: %llu\n", (unsigned long long)sizes->second_dset, (unsigned long long)(sizes->second_dset - sizes->first_dset));
1501   HDprintf("       dsets 1: %llu \tdelta: %llu\n", (unsigned long long)sizes->dsets1, (unsigned long long)(sizes->dsets1 - sizes->second_dset));
1502   HDprintf("       dsets 2: %llu \tdelta: %llu\n", (unsigned long long)sizes->dsets2, (unsigned long long)(sizes->dsets2 - sizes->dsets1));
1503   HDprintf("   interleaved: %llu \tdelta: %llu\n", (unsigned long long)sizes->interleaved, (unsigned long long)(sizes->interleaved - sizes->dsets2));
1504   HDprintf("    attributes: %llu \tdelta: %llu\n", (unsigned long long)sizes->attrs1, (unsigned long long)(sizes->attrs1 - sizes->interleaved));
1505   HDprintf("  attributes 2: %llu \tdelta: %llu\n", (unsigned long long)sizes->attrs2, (unsigned long long)(sizes->attrs2 - sizes->attrs1));
1506 } /* size2_dump_struct */
1507 #endif /* NOT_NOW */
1508 
1509 
1510 /*-------------------------------------------------------------------------
1511  * Function:    size2_helper
1512  *
1513  * Purpose:     A helper functon for test_sohm_size2.
1514  *
1515  *              Creates a file using the given fcpl, then creates lots
1516  *              of different kinds of messages within the file and
1517  *              returns the size of the file for comparison.
1518  *
1519  *              If test_file_closing is not zero, closes and re-opens
1520  *              the file after every write.
1521  *
1522  *              Doesn't close the property list.  Prints an error message
1523  *              if there's a failure, but doesn't alter its return value.
1524  *
1525  * Programmer:  James Laird
1526  *              Friday, November 17, 2006
1527  *
1528  * Modifications:
1529  *
1530  *-------------------------------------------------------------------------
1531  */
1532 static int
size2_helper(hid_t fcpl_id,int test_file_closing,size2_helper_struct * ret_sizes)1533 size2_helper(hid_t fcpl_id, int test_file_closing, size2_helper_struct *ret_sizes)
1534 {
1535     hid_t file_id = -1;
1536     hid_t dtype1_id = -1;
1537     hid_t dtype2_id = -1;
1538     hid_t dspace1_id = -1;
1539     hid_t dspace2_id = -1;
1540     hid_t dcpl1_id = -1;
1541     hid_t dcpl2_id = -1;
1542     hid_t dset_id = -1;
1543     hid_t attr_type_id = -1;
1544     hid_t attr_space_id = -1;
1545     hid_t attr_id = -1;
1546     hid_t group_id = -1;
1547     char attr_string1[NAME_BUF_SIZE];
1548     char attr_string2[NAME_BUF_SIZE];
1549     char attr_name[NAME_BUF_SIZE];
1550     int x;
1551     herr_t ret;
1552 
1553     /* Constants used in this function */
1554     const int rank1 = SIZE2_RANK1;
1555     const int rank2 = SIZE2_RANK2;
1556     const hsize_t dims[SIZE2_RANK2] = SIZE2_DIMS;
1557     dtype1_struct fill1;
1558     char fill2[DTYPE2_SIZE];
1559 
1560     /* Closing and re-opening the file takes a long time on systems without
1561      * local disks.  Don't close and reopen if express testing is enabled.
1562      */
1563     if(GetTestExpress() > 1)
1564         test_file_closing = 0;
1565 
1566     /* Create a file and get its size */
1567     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
1568     CHECK_I(file_id, "H5Fcreate");
1569 
1570     ret = H5Fclose(file_id);
1571     CHECK_I(ret, "H5Fclose");
1572 
1573     /* Get the file size */
1574     ret_sizes->empty_size = h5_get_file_size(FILENAME, H5P_DEFAULT);
1575 
1576     /* Re-open the file and set up messages to write */
1577     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1578     CHECK_I(file_id, "H5Fopen");
1579 
1580     /* Create two large datatype messages */
1581     dtype1_id = make_dtype_1();
1582     CHECK_I(dtype1_id, "make_dtype_1");
1583     dtype2_id = make_dtype_2();
1584     CHECK_I(dtype2_id, "make_dtype_2");
1585 
1586     /* Create some large dataspaces */
1587     dspace1_id = H5Screate_simple(rank1, dims, dims);
1588     CHECK_I(dspace1_id, "H5Screate_simple");
1589     dspace2_id = H5Screate_simple(rank2, dims, dims);
1590     CHECK_I(dspace2_id, "H5Screate_simple");
1591 
1592     /* fill1 and fill2 are fill values for the two datatypes.
1593      * We'll set them in the DCPL.
1594      */
1595     HDmemset(&fill1, '1', sizeof(dtype1_struct));
1596     HDmemset(&fill2, '2', (size_t)DTYPE2_SIZE);
1597 
1598     dcpl1_id = H5Pcreate(H5P_DATASET_CREATE);
1599     CHECK_I(dcpl1_id, "H5Pcreate");
1600     H5Pset_fill_value(dcpl1_id, dtype1_id, &fill1);
1601 
1602     dcpl2_id = H5Pcreate(H5P_DATASET_CREATE);
1603     CHECK_I(dcpl2_id, "H5Pcreate");
1604     H5Pset_fill_value(dcpl2_id, dtype2_id, &fill2);
1605 
1606     /* Filter messages we'll create by setting them in a DCPL. These
1607      * values don't need to make sense, they just need to take up space.
1608      */
1609     ret = H5Pset_chunk(dcpl1_id, rank1, dims);
1610     CHECK_I(ret, "H5Pset_chunk");
1611     ret = H5Pset_shuffle(dcpl1_id);
1612     CHECK_I(ret, "H5Pset_shuffle");
1613     ret = H5Pset_deflate(dcpl1_id, 1);
1614     CHECK_I(ret, "H5Pset_deflate");
1615     ret = H5Pset_shuffle(dcpl1_id);
1616     CHECK_I(ret, "H5Pset_shuffle");
1617     ret = H5Pset_fletcher32(dcpl1_id);
1618     CHECK_I(ret, "H5Pset_fletcher32");
1619     /* Make sure that this property list is what it should be */
1620     size2_verify_plist1(dcpl1_id);
1621 
1622     /* Second dcpl */
1623     ret = H5Pset_chunk(dcpl2_id, rank2, dims);
1624     CHECK_I(ret, "H5Pset_chunk");
1625     ret = H5Pset_deflate(dcpl2_id, 1);
1626     CHECK_I(ret, "H5Pset_deflate");
1627     ret = H5Pset_deflate(dcpl2_id, 2);
1628     CHECK_I(ret, "H5Pset_deflate");
1629     ret = H5Pset_deflate(dcpl2_id, 2);
1630     CHECK_I(ret, "H5Pset_deflate");
1631     ret = H5Pset_deflate(dcpl2_id, 1);
1632     CHECK_I(ret, "H5Pset_deflate");
1633     ret = H5Pset_deflate(dcpl2_id, 5);
1634     CHECK_I(ret, "H5Pset_deflate");
1635     /* Make sure that this property list is what it should be */
1636     size2_verify_plist2(dcpl2_id);
1637 
1638     /* Set up attribute data */
1639     HDmemset(attr_string1, 0, (size_t)NAME_BUF_SIZE);
1640     HDmemset(attr_string2, 0, (size_t)NAME_BUF_SIZE);
1641     HDstrcpy(attr_string1, LONG_STRING);
1642     HDstrcpy(attr_string2, LONG_STRING);
1643     attr_string2[1] = '1';        /* The second string starts "01 index..." */
1644 
1645     /* Set up attribute metadata */
1646     attr_type_id = H5Tcopy(H5T_C_S1);
1647     CHECK_I(attr_type_id, "H5Tcopy");
1648     ret = H5Tset_size(attr_type_id, (size_t)NAME_BUF_SIZE);
1649     CHECK_I(ret, "H5Tset_size");
1650     attr_space_id = H5Screate_simple(1, dims, dims);
1651     CHECK_I(attr_space_id, "H5Screate_simple");
1652 
1653     /* Create datasets with a big datatype, dataspace, fill value,
1654      * and filter pipeline.
1655      */
1656     for(x = 0; x < NUM_DATASETS; ++x) {
1657         dset_id = H5Dcreate2(file_id, DSETNAME[x], dtype1_id, dspace1_id, H5P_DEFAULT, dcpl1_id, H5P_DEFAULT);
1658         CHECK_I(dset_id, "H5Dcreate2");
1659 
1660         attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1661         CHECK_I(attr_id, "H5Acreate2");
1662         ret = H5Awrite(attr_id, attr_type_id, attr_string1);
1663         CHECK_I(ret, "H5Awrite");
1664 
1665         ret = H5Aclose(attr_id);
1666         CHECK_I(ret, "H5Aclose");
1667         ret = H5Dclose(dset_id);
1668         CHECK_I(ret, "H5Dclose");
1669 
1670         /* Gather extra statistics on first two datasets in file */
1671         if(x < 2) {
1672             ret = H5Fclose(file_id);
1673             CHECK_I(ret, "H5Fclose");
1674 
1675             /* Get the file's size now */
1676             if(x == 0)
1677                 ret_sizes->first_dset = h5_get_file_size(FILENAME, H5P_DEFAULT);
1678             else
1679                 ret_sizes->second_dset = h5_get_file_size(FILENAME, H5P_DEFAULT);
1680 
1681             file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1682             CHECK_I(file_id, "H5Fopen");
1683         } /* end if */
1684         /* Close & reopen file if requested */
1685         else if(test_file_closing) {
1686             file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
1687             CHECK_I(file_id, "H5Fopen");
1688         } /* end if */
1689     } /* end for */
1690 
1691     /* Close file and get its size now */
1692     ret = H5Fclose(file_id);
1693     CHECK_I(ret, "H5Fclose");
1694     ret_sizes->dsets1 = h5_get_file_size(FILENAME, H5P_DEFAULT);
1695 
1696 
1697     /* Create new group filled with datasets that use all different messages */
1698     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1699     CHECK_I(file_id, "H5Fopen");
1700     group_id = H5Gcreate2(file_id, "group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1701     CHECK_I(group_id, "H5Gcreate2");
1702 
1703     /* Create NUM_DATASETS datasets in the new group */
1704     for(x=0; x<NUM_DATASETS; ++x) {
1705         dset_id = H5Dcreate2(group_id, DSETNAME[x], dtype2_id, dspace2_id, H5P_DEFAULT, dcpl2_id, H5P_DEFAULT);
1706         CHECK_I(dset_id, "H5Dcreate2");
1707 
1708         attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1709         CHECK_I(attr_id, "H5Acreate2");
1710         ret = H5Awrite(attr_id, attr_type_id, attr_string2);
1711         CHECK_I(ret, "H5Awrite");
1712 
1713         ret = H5Dclose(dset_id);
1714         CHECK_I(ret, "H5Dclose");
1715         ret = H5Aclose(attr_id);
1716         CHECK_I(ret, "H5Aclose");
1717 
1718         /* Close everything & reopen file if requested */
1719         if(test_file_closing) {
1720             ret = H5Gclose(group_id);
1721             CHECK_I(ret, "H5Gclose");
1722             file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
1723             CHECK_I(file_id, "H5Fopen");
1724             group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
1725             CHECK_I(group_id, "H5Gopen2");
1726         }
1727     }
1728 
1729     /* Close file and get its size now */
1730     ret = H5Gclose(group_id);
1731     CHECK_I(ret, "H5Gclose");
1732     ret = H5Fclose(file_id);
1733     CHECK_I(ret, "H5Fclose");
1734     ret_sizes->dsets2 = h5_get_file_size(FILENAME, H5P_DEFAULT);
1735 
1736 
1737     /* Create a new group and interleave writes of datasets types 1 and 2. */
1738     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1739     CHECK_I(file_id, "H5Fopen");
1740     group_id = H5Gcreate2(file_id, "interleaved group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1741     CHECK_I(group_id, "H5Gcreate2");
1742 
1743     /* Create NUM_DATASETS datasets in the new group */
1744     for(x=0; x<NUM_DATASETS; x+=2)
1745     {
1746         dset_id = H5Dcreate2(group_id, DSETNAME[x], dtype1_id, dspace1_id, H5P_DEFAULT, dcpl1_id, H5P_DEFAULT);
1747         CHECK_I(dset_id, "H5Dcreate2");
1748 
1749         attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1750         CHECK_I(attr_id, "H5Acreate2");
1751         ret = H5Awrite(attr_id, attr_type_id, attr_string1);
1752         CHECK_I(ret, "H5Awrite");
1753 
1754         ret = H5Dclose(dset_id);
1755         CHECK_I(ret, "H5Dclose");
1756         ret = H5Aclose(attr_id);
1757         CHECK_I(ret, "H5Aclose");
1758 
1759         dset_id = H5Dcreate2(group_id, DSETNAME[x+1], dtype2_id, dspace2_id, H5P_DEFAULT, dcpl2_id, H5P_DEFAULT);
1760         CHECK_I(dset_id, "H5Dcreate2");
1761 
1762         attr_id = H5Acreate2(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1763         CHECK_I(attr_id, "H5Acreate2");
1764         ret = H5Awrite(attr_id, attr_type_id, attr_string2);
1765         CHECK_I(ret, "H5Awrite");
1766 
1767         ret = H5Dclose(dset_id);
1768         CHECK_I(ret, "H5Dclose");
1769         ret = H5Aclose(attr_id);
1770         CHECK_I(ret, "H5Aclose");
1771 
1772         /* Close everything & reopen file if requested */
1773         if(test_file_closing) {
1774             ret = H5Gclose(group_id);
1775             CHECK_I(ret, "H5Gclose");
1776             file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
1777             CHECK_I(file_id, "H5Fopen");
1778             group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
1779             CHECK_I(group_id, "H5Gopen2");
1780         }
1781     }
1782 
1783     /* Close file and get its size now */
1784     ret = H5Gclose(group_id);
1785     CHECK_I(ret, "H5Gclose");
1786     ret = H5Fclose(file_id);
1787     CHECK_I(ret, "H5Fclose");
1788     ret_sizes->interleaved = h5_get_file_size(FILENAME, H5P_DEFAULT);
1789 
1790     /* Create lots of new attribute messages on the group
1791      * (using different strings for the attribute)
1792      */
1793     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1794     CHECK_I(file_id, "H5Fopen");
1795     group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
1796     CHECK_I(group_id, "H5Gopen2");
1797 
1798     HDstrcpy(attr_name, "00 index");
1799 
1800     for(x = 0; x < NUM_ATTRIBUTES; ++x) {
1801         /* Create a unique name and value for each attribute */
1802         attr_string1[0] = attr_name[0] = (char)((x / 10) + '0');
1803         attr_string1[1] = attr_name[1] = (char)((x % 10) + '0');
1804 
1805         /* Create an attribute on the group */
1806         attr_id = H5Acreate2(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1807         CHECK_I(attr_id, "H5Acreate2");
1808         ret = H5Awrite(attr_id, attr_type_id, attr_string1);
1809         CHECK_I(ret, "H5Awrite");
1810 
1811         ret = H5Aclose(attr_id);
1812         CHECK_I(ret, "H5Aclose");
1813 
1814         /* Close everything & reopen file if requested */
1815         if(test_file_closing) {
1816             ret = H5Gclose(group_id);
1817             CHECK_I(ret, "H5Gclose");
1818             file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
1819             CHECK_I(file_id, "H5Fopen");
1820             group_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
1821             CHECK_I(group_id, "H5Gopen2");
1822         }
1823     }
1824 
1825     /* Close file and get its size now */
1826     ret = H5Gclose(group_id);
1827     CHECK_I(ret, "H5Gclose");
1828     ret = H5Fclose(file_id);
1829     CHECK_I(ret, "H5Fclose");
1830     ret_sizes->attrs1 = h5_get_file_size(FILENAME, H5P_DEFAULT);
1831 
1832 
1833     /* Create all of the attributes again on the other group */
1834     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
1835     CHECK_I(file_id, "H5Fopen");
1836     group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
1837     CHECK_I(group_id, "H5Gopen2");
1838 
1839     for(x=0; x<NUM_ATTRIBUTES; ++x)
1840     {
1841         /* Create the same name and value for each attribute as before */
1842         attr_string1[0] = attr_name[0] = (char)((x / 10) + '0');
1843         attr_string1[1] = attr_name[1] = (char)((x % 10) + '0');
1844 
1845         /* Create an attribute on the group */
1846         attr_id = H5Acreate2(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT, H5P_DEFAULT);
1847         CHECK_I(attr_id, "H5Acreate2");
1848         ret = H5Awrite(attr_id, attr_type_id, attr_string1);
1849         CHECK_I(ret, "H5Awrite");
1850 
1851         ret = H5Aclose(attr_id);
1852         CHECK_I(ret, "H5Aclose");
1853 
1854         /* Close everything & reopen file if requested */
1855         if(test_file_closing) {
1856             ret = H5Gclose(group_id);
1857             CHECK_I(ret, "H5Gclose");
1858             file_id = close_reopen_file(file_id, FILENAME, H5P_DEFAULT);
1859             CHECK_I(file_id, "H5Fopen");
1860             group_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
1861             CHECK_I(group_id, "H5Gopen2");
1862         }
1863     }
1864     /* Close file and get its size now */
1865     ret = H5Gclose(group_id);
1866     CHECK_I(ret, "H5Gclose");
1867     ret = H5Fclose(file_id);
1868     CHECK_I(ret, "H5Fclose");
1869     ret_sizes->attrs2 = h5_get_file_size(FILENAME, H5P_DEFAULT);
1870 
1871 
1872     /* Close everything */
1873     ret = H5Sclose(attr_space_id);
1874     CHECK_I(ret, "H5Sclose");
1875     ret = H5Tclose(attr_type_id);
1876     CHECK_I(ret, "H5Sclose");
1877     ret = H5Tclose(dtype1_id);
1878     CHECK_I(ret, "H5Tclose");
1879     ret = H5Tclose(dtype2_id);
1880     CHECK_I(ret, "H5Tclose");
1881     ret = H5Sclose(dspace1_id);
1882     CHECK_I(ret, "H5Sclose");
1883     ret = H5Sclose(dspace2_id);
1884     CHECK_I(ret, "H5Sclose");
1885     ret = H5Pclose(dcpl1_id);
1886     CHECK_I(ret, "H5Pclose");
1887     ret = H5Pclose(dcpl2_id);
1888     CHECK_I(ret, "H5Pclose");
1889 
1890     return 0;
1891 } /* size2_helper */
1892 
1893 
1894 /*-------------------------------------------------------------------------
1895  * Function:    size2_verify
1896  *
1897  * Purpose:     A helper functon to verify the file created by size2_helper.
1898  *
1899  *              Runs various tests (not exhaustive) to ensure that the
1900  *              file FILENAME actually has the structure that size2_helper
1901  *              should have created.
1902  *
1903  * Programmer:  James Laird
1904  *              Friday, November 17, 2006
1905  *
1906  *-------------------------------------------------------------------------
1907  */
1908 static void
size2_verify(void)1909 size2_verify(void)
1910 {
1911     hid_t file_id = -1;
1912     hid_t dset_id=-1;
1913     hid_t plist_id=-1;
1914     hid_t space_id=-1;
1915     hid_t group1_id, group2_id;
1916     hid_t attr1_id, attr2_id;
1917     hid_t attr_type_id;
1918     int x, y;
1919     herr_t ret;
1920     char attr_string[NAME_BUF_SIZE];
1921     char attr_correct_string[NAME_BUF_SIZE];
1922     char attr_name[NAME_BUF_SIZE];
1923     int ndims;
1924     hsize_t dims[SIZE2_RANK2];
1925     hsize_t correct_dims[SIZE2_RANK2] = SIZE2_DIMS;
1926 
1927     file_id = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
1928     CHECK_I(file_id, "H5Fopen");
1929 
1930 
1931     /* Verify property lists and dataspaces */
1932 
1933     /* Get property lists from first batch of datasets */
1934     for(x = 0; x < NUM_DATASETS; ++x) {
1935         dset_id = H5Dopen2(file_id, DSETNAME[x], H5P_DEFAULT);
1936         CHECK_I(dset_id, "H5Dopen2");
1937         plist_id = H5Dget_create_plist(dset_id);
1938         CHECK_I(plist_id, "H5Dget_create_plist");
1939         size2_verify_plist1(plist_id);
1940         ret = H5Pclose(plist_id);
1941         CHECK_I(ret, "H5Pclose");
1942 
1943         space_id = H5Dget_space(dset_id);
1944         CHECK_I(space_id, "H5Dget_space");
1945         ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
1946         CHECK_I(ndims, "H5Sget_simple_extent_dims");
1947         VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
1948         for(y = 0; y < ndims; ++y)
1949             VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
1950 
1951         ret = H5Sclose(space_id);
1952         CHECK_I(ret, "H5Sclose");
1953 
1954         ret = H5Dclose(dset_id);
1955         CHECK_I(ret, "H5Dclose");
1956     }
1957 
1958     /* Get property lists from second batch of datasets */
1959     group1_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
1960     CHECK_I(group1_id, "H5Gopen2");
1961     for(x = 0; x < NUM_DATASETS; ++x) {
1962         dset_id = H5Dopen2(group1_id, DSETNAME[x], H5P_DEFAULT);
1963         CHECK_I(dset_id, "H5Dopen2");
1964         plist_id = H5Dget_create_plist(dset_id);
1965         CHECK_I(plist_id, "H5Dget_create_plist");
1966         size2_verify_plist2(plist_id);
1967         ret = H5Pclose(plist_id);
1968         CHECK_I(ret, "H5Pclose");
1969 
1970         space_id = H5Dget_space(dset_id);
1971         CHECK_I(space_id, "H5Dget_space");
1972         ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
1973         CHECK_I(ndims, "H5Sget_simple_extent_dims");
1974         VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
1975         for(y = 0; y < ndims; ++y)
1976             VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
1977 
1978         ret = H5Sclose(space_id);
1979         CHECK_I(ret, "H5Sclose");
1980 
1981         ret = H5Dclose(dset_id);
1982         CHECK_I(ret, "H5Dclose");
1983     } /* end for */
1984     ret = H5Gclose(group1_id);
1985     CHECK_I(ret, "H5Gclose");
1986 
1987     /* Get property lists from interleaved group of datasets */
1988     group1_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
1989     CHECK_I(group1_id, "H5Gopen2");
1990     for(x = 0; x < NUM_DATASETS; x += 2) {
1991         /* First "type 1" dataset */
1992         dset_id = H5Dopen2(group1_id, DSETNAME[x], H5P_DEFAULT);
1993         CHECK_I(dset_id, "H5Dopen2");
1994         plist_id = H5Dget_create_plist(dset_id);
1995         CHECK_I(plist_id, "H5Dget_create_plist");
1996         size2_verify_plist1(plist_id);
1997         ret = H5Pclose(plist_id);
1998         CHECK_I(ret, "H5Pclose");
1999 
2000         space_id = H5Dget_space(dset_id);
2001         CHECK_I(space_id, "H5Dget_space");
2002         ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
2003         CHECK_I(ndims, "H5Sget_simple_extent_dims");
2004         VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
2005         for(y = 0; y < ndims; ++y)
2006             VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
2007 
2008         ret = H5Sclose(space_id);
2009         CHECK_I(ret, "H5Sclose");
2010 
2011         ret = H5Dclose(dset_id);
2012         CHECK_I(ret, "H5Dclose");
2013 
2014         /* Second "type 2" dataset */
2015         dset_id = H5Dopen2(group1_id, DSETNAME[x + 1], H5P_DEFAULT);
2016         CHECK_I(dset_id, "H5Dopen2");
2017         plist_id = H5Dget_create_plist(dset_id);
2018         CHECK_I(plist_id, "H5Dget_create_plist");
2019         size2_verify_plist2(plist_id);
2020         ret = H5Pclose(plist_id);
2021         CHECK_I(ret, "H5Pclose");
2022 
2023         space_id = H5Dget_space(dset_id);
2024         CHECK_I(space_id, "H5Dget_space");
2025         ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
2026         CHECK_I(ndims, "H5Sget_simple_extent_dims");
2027         VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
2028         for(y = 0; y < ndims; ++y)
2029             VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
2030 
2031         ret = H5Sclose(space_id);
2032         CHECK_I(ret, "H5Sclose");
2033 
2034         ret = H5Dclose(dset_id);
2035         CHECK_I(ret, "H5Dclose");
2036     } /* end for */
2037     ret = H5Gclose(group1_id);
2038     CHECK_I(ret, "H5Gclose");
2039 
2040 
2041     /* Verify attributes */
2042 
2043     /* Create attribute data type */
2044     attr_type_id = H5Tcopy(H5T_C_S1);
2045     CHECK_I(attr_type_id, "H5Tcopy");
2046     ret = H5Tset_size(attr_type_id, (size_t)NAME_BUF_SIZE);
2047     CHECK_I(ret, "H5Tset_size");
2048 
2049     /* Read attributes on both groups and verify that they are correct */
2050     group1_id = H5Gopen2(file_id, "group", H5P_DEFAULT);
2051     CHECK_I(group1_id, "H5Gopen2");
2052     group2_id = H5Gopen2(file_id, "interleaved group", H5P_DEFAULT);
2053     CHECK_I(group2_id, "H5Gopen2");
2054 
2055     HDmemset(attr_string, 0, (size_t)NAME_BUF_SIZE);
2056     HDmemset(attr_correct_string, 0, (size_t)NAME_BUF_SIZE);
2057     HDstrcpy(attr_correct_string, LONG_STRING);
2058     HDstrcpy(attr_name, "00 index");
2059 
2060     for(x = 0; x < NUM_ATTRIBUTES; ++x) {
2061         /* Create the name and correct value for each attribute */
2062         attr_correct_string[0] = attr_name[0] = (char)((x / 10) + '0');
2063         attr_correct_string[1] = attr_name[1] = (char)((x % 10) + '0');
2064 
2065         attr1_id = H5Aopen(group1_id, attr_name, H5P_DEFAULT);
2066         CHECK_I(attr1_id, "H5Aopen");
2067         attr2_id = H5Aopen(group2_id, attr_name, H5P_DEFAULT);
2068         CHECK_I(attr2_id, "H5Aopen");
2069 
2070         ret = H5Aread(attr1_id, attr_type_id, attr_string);
2071         CHECK_I(ret, "H5Aread");
2072         VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
2073         ret = H5Aread(attr2_id, attr_type_id, attr_string);
2074         CHECK_I(ret, "H5Aread");
2075         VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
2076 
2077         ret = H5Aclose(attr1_id);
2078         CHECK_I(attr1_id, "H5Aclose");
2079         ret = H5Aclose(attr2_id);
2080         CHECK_I(attr2_id, "H5Aclose");
2081     }
2082 
2083     /* Close everything */
2084     ret = H5Tclose(attr_type_id);
2085     CHECK_I(ret, "H5Tclose");
2086     ret = H5Gclose(group1_id);
2087     CHECK_I(ret, "H5Gclose");
2088     ret = H5Gclose(group2_id);
2089     CHECK_I(ret, "H5Gclose");
2090     ret = H5Fclose(file_id);
2091     CHECK_I(ret, "H5Fclose");
2092 } /* size2_verify */
2093 
2094 
2095 /*-------------------------------------------------------------------------
2096  * Function:    test_sohm_size2
2097  *
2098  * Purpose:     Tests shared object header messages using size2_helper to
2099  *              create different kinds of big messages.
2100  *
2101  *              If close_reopen is set, closes and reopens the HDF5 file
2102  *              repeatedly while writing.
2103  *
2104  *              This test works by first creating FCPLs with various
2105  *              parameters, then creating a standard file that includes
2106  *              every kind of message that can be shared using the helper
2107  *              function size2_helper.  The test measures the size of the
2108  *              file at various points.  Once all of the files have been
2109  *              generated, the test compares the measured sizes of the files.
2110  *
2111  *
2112  * Programmer:  James Laird
2113  *              Friday, November 17, 2006
2114  *
2115  *-------------------------------------------------------------------------
2116  */
2117 static void
test_sohm_size2(int close_reopen)2118 test_sohm_size2(int close_reopen)
2119 {
2120     hid_t       fcpl_id = -1;
2121     /* Sizes for file with no shared messages at all */
2122     size2_helper_struct norm_sizes;
2123     /* Sizes for files with all messages in one index */
2124     size2_helper_struct list_index_med, list_index_big;
2125     size2_helper_struct btree_index, list_index_small;
2126     /* Sizes for files with messages in three different indexes */
2127     size2_helper_struct mult_index_med, mult_index_btree;
2128     /* Sizes for files that don't share all kinds of messages */
2129     size2_helper_struct share_some_med, share_some_btree;
2130     /* Sizes for files that share different sizes of messages */
2131     size2_helper_struct share_some_toobig_index, share_tiny_index, type_space_index;
2132     herr_t      ret;
2133 
2134     if(close_reopen == 0)
2135         MESSAGE(5, ("Testing that shared object header messages save space\n"))
2136     else
2137         MESSAGE(5, ("Testing that shared messages save space when file is closed and reopened\n"))
2138 
2139     /* Create an fcpl with SOHMs disabled */
2140     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
2141     CHECK_I(fcpl_id, "H5Pcreate");
2142 
2143     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
2144     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
2145 
2146     /* Get the file size & verify its contents */
2147     size2_helper(fcpl_id, close_reopen, &norm_sizes);
2148     size2_verify();
2149 
2150     ret = H5Pclose(fcpl_id);
2151     CHECK_I(ret, "H5Pclose");
2152 
2153 
2154     /* Create an fcpl with one big index */
2155     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
2156     CHECK_I(fcpl_id, "H5Pcreate");
2157 
2158     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
2159     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
2160     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 20);
2161     CHECK_I(ret, "H5Pset_shared_mesg_index");
2162 
2163     /* Set the indexes to use a medium-sized list */
2164     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
2165     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2166 
2167     /* Get the file size & verify its contents */
2168     size2_helper(fcpl_id, close_reopen, &list_index_med);
2169     size2_verify();
2170 
2171 
2172     /* Try making the list really big */
2173     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
2174     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2175 
2176     /* Get the file size & verify its contents */
2177     size2_helper(fcpl_id, close_reopen, &list_index_big);
2178     size2_verify();
2179 
2180 
2181     /* Use a B-tree instead of a list */
2182     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
2183     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2184 
2185     /* Get the file size & verify its contents */
2186     size2_helper(fcpl_id, close_reopen, &btree_index);
2187     size2_verify();
2188 
2189 
2190     /* Use such a small list that it'll become a B-tree */
2191     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 0);
2192     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2193 
2194     /* Get the file size & verify its contents */
2195     size2_helper(fcpl_id, close_reopen, &list_index_small);
2196     size2_verify();
2197 
2198     ret = H5Pclose(fcpl_id);
2199     CHECK_I(ret, "H5Pclose");
2200 
2201 
2202     /* Create a new property list that puts messages in different indexes. */
2203     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
2204     CHECK_I(fcpl_id, "H5Pcreate");
2205 
2206     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
2207     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
2208     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG, 20);
2209     CHECK_I(ret, "H5Pset_shared_mesg_index");
2210     ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_FILL_FLAG | H5O_SHMESG_PLINE_FLAG, 20);
2211     CHECK_I(ret, "H5Pset_shared_mesg_index");
2212     ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_SHMESG_ATTR_FLAG, 20);
2213     CHECK_I(ret, "H5Pset_shared_mesg_index");
2214 
2215     /* Use lists that are the same size as the "medium" list on the previous
2216      * run.
2217      */
2218     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
2219     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2220 
2221     /* Get the file size & verify its contents */
2222     size2_helper(fcpl_id, close_reopen, &mult_index_med);
2223     size2_verify();
2224 
2225 
2226     /* Use all B-trees */
2227     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
2228     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2229 
2230     /* Get the file size & verify its contents */
2231     size2_helper(fcpl_id, close_reopen, &mult_index_btree);
2232     size2_verify();
2233 
2234 
2235     /* Edit the same property list (this should work) and don't share all messages.
2236      */
2237     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_PLINE_FLAG, 20);
2238     CHECK_I(ret, "H5Pset_shared_mesg_index");
2239     ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 100000);
2240     CHECK_I(ret, "H5Pset_shared_mesg_index");
2241     ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_SHMESG_ATTR_FLAG | H5O_SHMESG_SDSPACE_FLAG, 20);
2242     CHECK_I(ret, "H5Pset_shared_mesg_index");
2243 
2244     /* Use "normal-sized" lists. */
2245     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
2246     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2247 
2248     /* Get the file size & verify its contents */
2249     size2_helper(fcpl_id, close_reopen, &share_some_med);
2250     size2_verify();
2251 
2252     /* Use btrees. */
2253     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
2254     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2255 
2256     /* Get the file size & verify its contents */
2257     size2_helper(fcpl_id, close_reopen, &share_some_btree);
2258     size2_verify();
2259 
2260 
2261     /* Change the second index to hold only gigantic messages.  Result should
2262      * be the same as the previous file.
2263      */
2264     ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG, 100000);
2265     CHECK_I(ret, "H5Pset_shared_mesg_index");
2266 
2267     /* Get the file size & verify its contents */
2268     size2_helper(fcpl_id, close_reopen, &share_some_toobig_index);
2269     size2_verify();
2270 
2271 
2272     /* Share even tiny dataspace and datatype messages.  This should result in
2273      * attribute datatypes being shared.  Make this one use "really big" lists.
2274      * It turns out that attribute dataspaces are just big enough that it saves
2275      * some space to share them, while sharing datatypes creates as much overhead
2276      * as one gains from sharing them.
2277      */
2278     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
2279     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_SDSPACE_FLAG, 1);
2280     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
2281 
2282     /* Get the file size & verify its contents */
2283     size2_helper(fcpl_id, close_reopen, &share_tiny_index);
2284     size2_verify();
2285 
2286     /* Create the same file but don't share the really tiny messages */
2287     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_SDSPACE_FLAG, 100);
2288     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
2289 
2290     /* Get the file size & verify its contents */
2291     size2_helper(fcpl_id, close_reopen, &type_space_index);
2292     size2_verify();
2293 
2294     ret = H5Pclose(fcpl_id);
2295     CHECK_I(ret, "H5Pclose");
2296 
2297 
2298 
2299     /* Check that all sizes make sense.  There is lots of room for inexact
2300      * results here since so many different factors contribute to file size.
2301      */
2302 
2303 
2304     /* Check sizes of all files created using a single index first */
2305 
2306     /* The empty size of each file with shared messages enabled should be the
2307      * same and should be bigger than a normal file.
2308      */
2309     if(norm_sizes.empty_size > list_index_med.empty_size)
2310         VERIFY(norm_sizes.empty_size, 1, "h5_get_file_size");
2311     if(list_index_med.empty_size != list_index_big.empty_size)
2312         VERIFY(list_index_med.empty_size, list_index_big.empty_size, "h5_get_file_size");
2313     if(list_index_med.empty_size != btree_index.empty_size)
2314         VERIFY(list_index_med.empty_size, btree_index.empty_size, "h5_get_file_size");
2315     if(list_index_med.empty_size != list_index_small.empty_size)
2316         VERIFY(list_index_med.empty_size, list_index_small.empty_size, "h5_get_file_size");
2317     /* The files with indexes shouldn't be that much bigger than an
2318      * empty file.
2319      */
2320     if(list_index_med.empty_size > (h5_stat_size_t)((float)norm_sizes.empty_size * OVERHEAD_ALLOWED))
2321         VERIFY(0, 1, "h5_get_file_size");
2322 
2323 
2324     /* Once one dataset has been created (with one of every kind of message),
2325      * the normal file should still be smallest.  The very small list
2326      * btree_convert should be smaller than the B-tree since it has no
2327      * extra overhead.  The small list should also be smaller than the B-tree.
2328      * The very large list should be much larger than anything else.
2329      */
2330     if(norm_sizes.first_dset >= list_index_small.first_dset)
2331         VERIFY(norm_sizes.first_dset, 1, "h5_get_file_size");
2332     if(list_index_small.first_dset >= btree_index.first_dset)
2333         VERIFY(list_index_small.first_dset, 1, "h5_get_file_size");
2334     if(list_index_med.first_dset >= btree_index.first_dset)
2335         VERIFY(btree_index.first_dset, 1, "h5_get_file_size");
2336     if(btree_index.first_dset >= list_index_big.first_dset)
2337         VERIFY(list_index_med.first_dset, 1, "h5_get_file_size");
2338 
2339 
2340     /* Once a few copies of the same dataset have been created, the
2341      * very small list shouldn't have become a B-tree yet, so it should
2342      * be the smallest file.  A larger list should be next, followed
2343      * by a B-tree, followed by a normal file, followed by a
2344      * list that is too large.
2345      */
2346     if(list_index_small.dsets1 >= list_index_med.dsets1)
2347         VERIFY(btree_index.dsets1, 1, "h5_get_file_size");
2348     if(list_index_med.dsets1 >= btree_index.dsets1)
2349         VERIFY(list_index_med.dsets1, 1, "h5_get_file_size");
2350     if(btree_index.dsets1 >= norm_sizes.dsets1)
2351         VERIFY(btree_index.dsets1, 1, "h5_get_file_size");
2352     if(norm_sizes.dsets1 >= list_index_big.dsets1)
2353         VERIFY(list_index_big.dsets1, 1, "h5_get_file_size");
2354 
2355     /* The size gain should have been the same for each of the lists;
2356      * their overhead is fixed.  The B-tree should have gained at least
2357      * as much, and the normal file more than that.
2358      */
2359     if((list_index_small.dsets1 - list_index_small.first_dset) !=
2360             (list_index_med.dsets1 - list_index_med.first_dset))
2361         VERIFY(0, 1, "h5_get_file_size");
2362     if((list_index_med.dsets1 - list_index_med.first_dset) !=
2363             (list_index_big.dsets1 - list_index_big.first_dset))
2364         VERIFY(0, 1, "h5_get_file_size");
2365     if((list_index_big.dsets1 - list_index_big.first_dset) >
2366             (btree_index.dsets1 - btree_index.first_dset))
2367         VERIFY(0, 1, "h5_get_file_size");
2368     if((btree_index.dsets1 - btree_index.first_dset) >=
2369             (norm_sizes.dsets1 - norm_sizes.first_dset))
2370         VERIFY(0, 1, "h5_get_file_size");
2371 
2372 
2373     /* Once another kind of each message has been written, the very small list
2374      * should convert into a B-tree.  Now the list should be smallest, then
2375      * the B-trees (although the converted B-tree file may be a little bigger),
2376      * then the normal file.  The largest list may or may not be bigger than
2377      * the normal file.
2378      */
2379     if(list_index_med.dsets2 >= btree_index.dsets2)
2380         VERIFY(list_index_med.dsets2, 1, "h5_get_file_size");
2381     if(btree_index.dsets2 > (h5_stat_size_t)((float)list_index_small.dsets2 * OVERHEAD_ALLOWED))
2382         VERIFY(btree_index.dsets2, list_index_small.dsets2, "h5_get_file_size");
2383     if(list_index_small.dsets2 >= norm_sizes.dsets2)
2384         VERIFY(btree_index.dsets2, 1, "h5_get_file_size");
2385     /* If the small list (now a B-tree) is bigger than the existing B-tree,
2386      * it shouldn't be much bigger.
2387      * It seems that the small lists tends to be pretty big anyway.  Allow
2388      * for it to have twice as much overhead.
2389      */
2390     if(list_index_small.dsets2 > (h5_stat_size_t)((float)btree_index.dsets2 * OVERHEAD_ALLOWED * OVERHEAD_ALLOWED))
2391         VERIFY(0, 1, "h5_get_file_size");
2392     /* The lists should have grown the least since they share messages and
2393      * have no extra overhead.  The normal file should have grown more than
2394      * either the lists or the B-tree.  The B-tree may not have grown more
2395      * than the lists, depending on whether it needed to split nodes or not.
2396      */
2397     if((list_index_med.dsets2 - list_index_med.dsets1) !=
2398             (list_index_big.dsets2 - list_index_big.dsets1))
2399         VERIFY(0, 1, "h5_get_file_size");
2400     if((list_index_big.dsets2 - list_index_big.dsets1) >
2401             (btree_index.dsets2 - btree_index.dsets1))
2402         VERIFY(0, 1, "h5_get_file_size");
2403     if((btree_index.dsets2 - btree_index.dsets1) >=
2404             (norm_sizes.dsets2 - norm_sizes.dsets1))
2405         VERIFY(0, 1, "h5_get_file_size");
2406 
2407 
2408     /* Interleaving the writes should have no effect on how the messages are
2409      * shared.  No new messages should be written to the indexes, so the
2410      * sohm files will only get a little bit bigger.
2411      */
2412     if(list_index_med.interleaved >= btree_index.interleaved)
2413         VERIFY(0, 1, "h5_get_file_size");
2414     if(btree_index.interleaved > (h5_stat_size_t)((float)list_index_small.interleaved * OVERHEAD_ALLOWED))
2415         VERIFY(btree_index.interleaved, list_index_small.interleaved, "h5_get_file_size");
2416     if(list_index_small.interleaved >= norm_sizes.interleaved)
2417         VERIFY(0, 1, "h5_get_file_size");
2418     /* The lists should still have grown the same amount.  The converted
2419      * B-tree shouldn't have grown more than the index that was originally
2420      * a B-tree (although it might have grown less if there was extra free
2421      * space within the file).
2422      */
2423     if((list_index_med.interleaved - list_index_med.dsets2) !=
2424             (list_index_big.interleaved - list_index_big.dsets2))
2425         VERIFY(0, 1, "h5_get_file_size");
2426     if((list_index_big.interleaved - list_index_big.dsets2) >
2427             (btree_index.interleaved - btree_index.dsets2))
2428         VERIFY(0, 1, "h5_get_file_size");
2429     if((list_index_small.interleaved - list_index_small.dsets2) >
2430             (btree_index.interleaved - btree_index.dsets2))
2431         VERIFY(0, 1, "h5_get_file_size");
2432     if((btree_index.interleaved - btree_index.dsets2) >=
2433             (norm_sizes.interleaved - norm_sizes.dsets2))
2434         VERIFY(0, 1, "h5_get_file_size");
2435 
2436     /* After many attributes have been written, both the small and medium lists
2437      * should have become B-trees and be about the same size as the index
2438      * that started as a B-tree.
2439      * Add in OVERHEAD_ALLOWED as a fudge factor here, since the allocation
2440      * of file space can be hard to predict.
2441      */
2442     if(btree_index.attrs1 > (h5_stat_size_t)((float)list_index_small.attrs1 * OVERHEAD_ALLOWED))
2443         VERIFY(btree_index.attrs1, list_index_small.attrs1, "h5_get_file_size");
2444     if(btree_index.attrs1 > (h5_stat_size_t)((float)list_index_med.attrs1 * OVERHEAD_ALLOWED))
2445         VERIFY(0, 1, "h5_get_file_size");
2446     if(list_index_med.attrs1 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
2447         VERIFY(0, 1, "h5_get_file_size");
2448     if(list_index_small.attrs1 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
2449         VERIFY(0, 1, "h5_get_file_size");
2450     /* Neither of the converted lists should be too much bigger than
2451      * the index that was originally a B-tree.
2452      */
2453     if(list_index_small.attrs1 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
2454         VERIFY(0, 1, "h5_get_file_size");
2455     if(list_index_med.attrs1 > (h5_stat_size_t)((float)btree_index.attrs1 * OVERHEAD_ALLOWED))
2456         VERIFY(0, 1, "h5_get_file_size");
2457     /* The "normal" file should have had less overhead, so should gain less
2458      * size than any of the other indexes since none of these attribute
2459      * messages could be shared.  The large list should have gained
2460      * less overhead than the B-tree indexes.
2461      */
2462     if((norm_sizes.attrs1 - norm_sizes.interleaved) >=
2463             (list_index_big.attrs1 - list_index_big.interleaved))
2464         VERIFY(0, 1, "h5_get_file_size");
2465     if((list_index_big.attrs1 - list_index_big.interleaved) >=
2466             (list_index_small.attrs1 - list_index_small.interleaved))
2467         VERIFY(0, 1, "h5_get_file_size");
2468 
2469     /* Give it some overhead (for checkin to move messages into continuation message) */
2470     if((list_index_small.attrs1 - list_index_small.interleaved) >
2471             (h5_stat_size_t)((float)(btree_index.attrs1 - btree_index.interleaved) * OVERHEAD_ALLOWED))
2472         VERIFY(0, 1, "h5_get_file_size");
2473 
2474 
2475     /* Writing another copy of each attribute shouldn't change the ordering
2476      * of sizes.  The big list index is still too big to be smaller than a
2477      * normal file.  The B-tree indexes should all be about the same size.
2478      */
2479     if(btree_index.attrs2 > (h5_stat_size_t)((float)list_index_small.attrs2 * OVERHEAD_ALLOWED))
2480         VERIFY(btree_index.attrs2, list_index_small.attrs2, "h5_get_file_size");
2481     if(list_index_small.attrs2 > (h5_stat_size_t)((float)btree_index.attrs2 * OVERHEAD_ALLOWED))
2482         VERIFY(0, 1, "h5_get_file_size");
2483     if(btree_index.attrs2 > (h5_stat_size_t)((float)list_index_med.attrs2 * OVERHEAD_ALLOWED))
2484         VERIFY(0, 1, "h5_get_file_size");
2485     if(list_index_med.attrs2 > (h5_stat_size_t)((float)btree_index.attrs2 * OVERHEAD_ALLOWED))
2486         VERIFY(0, 1, "h5_get_file_size");
2487     if(list_index_med.attrs2 >= norm_sizes.attrs2)
2488         VERIFY(0, 1, "h5_get_file_size");
2489     if(list_index_big.attrs2 >= norm_sizes.attrs2)
2490         VERIFY(0, 1, "h5_get_file_size");
2491     /* All of the B-tree indexes should have gained about the same amount
2492      * of space; at least as much as the list index and less than a normal
2493      * file.
2494      */
2495     if((list_index_small.attrs2 - list_index_small.attrs1) >
2496             (btree_index.attrs2 - btree_index.attrs1))
2497         VERIFY(0, 1, "h5_get_file_size");
2498     if((list_index_med.attrs2 - list_index_med.attrs1) >
2499             (btree_index.attrs2 - btree_index.attrs1))
2500         VERIFY(0, 1, "h5_get_file_size");
2501     if((list_index_big.attrs2 - list_index_big.attrs1) >
2502             (list_index_med.attrs2 - list_index_med.attrs1))
2503         VERIFY(0, 1, "h5_get_file_size");
2504     if((btree_index.attrs2 - btree_index.attrs1) >=
2505             (norm_sizes.attrs2 - norm_sizes.attrs1))
2506         VERIFY(0, 1, "h5_get_file_size");
2507 
2508     /* Done checking the first few files that use a single index. */
2509 
2510 
2511     /* Start comparing other kinds of files with these "standard"
2512      * one-index files
2513      */
2514 
2515     /* Check files with multiple indexes. */
2516     /* These files should be larger when first created than one-index
2517      * files.
2518      */
2519     if(mult_index_med.empty_size <= list_index_med.empty_size)
2520         VERIFY(0, 1, "h5_get_file_size");
2521     if(mult_index_btree.empty_size != mult_index_med.empty_size)
2522         VERIFY(0, 1, "h5_get_file_size");
2523 
2524     /* When the first dataset is written, they should grow quite a bit as
2525      * many different indexes must be created.
2526      */
2527     if((mult_index_med.first_dset - mult_index_med.empty_size) <=
2528             (list_index_med.first_dset - list_index_med.empty_size))
2529         VERIFY(0, 1, "h5_get_file_size");
2530     if((mult_index_btree.first_dset - mult_index_btree.empty_size) <=
2531             (btree_index.first_dset - btree_index.empty_size))
2532         VERIFY(0, 1, "h5_get_file_size");
2533 
2534     /* When the second dataset is written, they should grow less as
2535      * some extra heap space is allocated, but no more indices.
2536      */
2537     if((mult_index_med.second_dset - mult_index_med.first_dset) >
2538             (mult_index_med.first_dset - mult_index_med.empty_size))
2539         VERIFY(0, 1, "h5_get_file_size");
2540     if((list_index_med.second_dset - list_index_med.first_dset) >
2541             (list_index_med.first_dset - list_index_med.empty_size))
2542         VERIFY(0, 1, "h5_get_file_size");
2543     if((mult_index_btree.second_dset - mult_index_btree.first_dset) >
2544             (mult_index_btree.first_dset - mult_index_btree.empty_size))
2545         VERIFY(0, 1, "h5_get_file_size");
2546     if((btree_index.second_dset - btree_index.first_dset) >
2547             (btree_index.first_dset - btree_index.empty_size))
2548         VERIFY(0, 1, "h5_get_file_size");
2549 
2550     /* And the size delta for the second dataset is less in files with only
2551      *  one index.
2552      */
2553     if((mult_index_med.second_dset - mult_index_med.first_dset) <=
2554             (list_index_med.second_dset - list_index_med.first_dset))
2555         VERIFY(0, 1, "h5_get_file_size");
2556     if((mult_index_btree.first_dset - mult_index_btree.empty_size) <=
2557             (btree_index.first_dset - btree_index.empty_size))
2558         VERIFY(0, 1, "h5_get_file_size");
2559 
2560     /* Once that initial overhead is out of the way and the lists/btrees
2561      * have been created, files with more than one index should grow at
2562      * the same rate or slightly faster than files with just one index
2563      * and one heap.
2564      */
2565      if((mult_index_med.dsets1 - mult_index_med.second_dset) !=
2566             (list_index_med.dsets1 - list_index_med.second_dset))
2567         VERIFY((mult_index_med.dsets1 - mult_index_med.second_dset), (list_index_med.dsets1 - list_index_med.second_dset), "h5_get_file_size");
2568      if((mult_index_btree.dsets1 - mult_index_btree.second_dset) !=
2569             (btree_index.dsets1 - btree_index.second_dset))
2570         VERIFY((mult_index_btree.dsets1 - mult_index_btree.second_dset), (btree_index.dsets1 - btree_index.second_dset), "h5_get_file_size");
2571 
2572      if((mult_index_med.dsets2 - mult_index_med.dsets1) >
2573             (h5_stat_size_t)((float)(list_index_med.dsets2 - list_index_med.dsets1) * OVERHEAD_ALLOWED))
2574         VERIFY(0, 1, "h5_get_file_size");
2575      if((mult_index_btree.dsets2 - mult_index_btree.dsets1) >
2576             (h5_stat_size_t)((float)(btree_index.dsets2 - btree_index.dsets1) * OVERHEAD_ALLOWED))
2577         VERIFY(0, 1, "h5_get_file_size");
2578 
2579      if((mult_index_med.interleaved - mult_index_med.dsets2) >
2580             (h5_stat_size_t)((float)(list_index_med.interleaved - list_index_med.dsets2) * OVERHEAD_ALLOWED))
2581         VERIFY(0, 1, "h5_get_file_size");
2582      if((mult_index_btree.interleaved - mult_index_btree.dsets2) >
2583             (h5_stat_size_t)((float)(btree_index.interleaved - btree_index.dsets2) * OVERHEAD_ALLOWED))
2584         VERIFY(0, 1, "h5_get_file_size");
2585 
2586     /* When all the attributes are added, only the index holding attributes
2587      * will become a B-tree.  Skip the interleaved to attrs1 interval when
2588      * this happens because it's hard to predict exactly how much space this
2589      * will take.
2590      */
2591      if((mult_index_med.attrs2 - mult_index_med.attrs1) >
2592             (h5_stat_size_t)((float)(list_index_med.attrs2 - list_index_med.attrs1) * OVERHEAD_ALLOWED))
2593         VERIFY(0, 1, "h5_get_file_size");
2594      if((mult_index_btree.attrs2 - mult_index_btree.attrs1) >
2595             (h5_stat_size_t)((float)(btree_index.attrs2 - btree_index.attrs1) * OVERHEAD_ALLOWED))
2596         VERIFY(0, 1, "h5_get_file_size");
2597 
2598     /* The final file size for both of the multiple index files should be
2599      * smaller than a normal file but bigger than any of the one-index files.
2600      */
2601      if(mult_index_med.attrs2 >= norm_sizes.attrs2)
2602         VERIFY(0, 1, "h5_get_file_size");
2603      if(mult_index_btree.attrs2 >= norm_sizes.attrs2)
2604         VERIFY(0, 1, "h5_get_file_size");
2605      if((h5_stat_size_t)((float)mult_index_med.attrs2 * OVERHEAD_ALLOWED) < btree_index.attrs2)
2606         VERIFY(0, 1, "h5_get_file_size");
2607      if((h5_stat_size_t)((float)mult_index_btree.attrs2 * OVERHEAD_ALLOWED) < btree_index.attrs2)
2608         VERIFY(0, 1, "h5_get_file_size");
2609 
2610 
2611     /* Check files that don't share all messages. */
2612     /* These files have three indexes like the files above, so they should be
2613      * the same size when created.
2614      */
2615     if(share_some_med.empty_size != mult_index_med.empty_size)
2616         VERIFY(0, 1, "h5_get_file_size");
2617     if(share_some_med.empty_size != share_some_btree.empty_size)
2618         VERIFY(0, 1, "h5_get_file_size");
2619 
2620     /* When the first dataset is created, they should be not quite as big
2621      * as equivalent files that share all messages (since shared messages
2622      * have a little bit of overhead).
2623      */
2624     if(share_some_med.first_dset >= mult_index_med.first_dset)
2625         VERIFY(0, 1, "h5_get_file_size");
2626     if(share_some_btree.first_dset >= mult_index_btree.first_dset)
2627         VERIFY(0, 1, "h5_get_file_size");
2628 
2629     /* The files that share some should have a growth rate in between
2630      * files that share all messages and normal files
2631      */
2632     if((share_some_med.interleaved - share_some_med.first_dset) <=
2633             (mult_index_med.interleaved - mult_index_med.first_dset))
2634         VERIFY(0, 1, "h5_get_file_size");
2635     if((share_some_med.interleaved - share_some_med.first_dset) >=
2636             (norm_sizes.interleaved - norm_sizes.first_dset))
2637         VERIFY(0, 1, "h5_get_file_size");
2638     if((share_some_btree.interleaved - share_some_btree.first_dset) <=
2639             (mult_index_btree.interleaved - mult_index_btree.first_dset))
2640         VERIFY(0, 1, "h5_get_file_size");
2641     if((share_some_btree.interleaved - share_some_btree.first_dset) >=
2642             (norm_sizes.interleaved - norm_sizes.first_dset))
2643         VERIFY(0, 1, "h5_get_file_size");
2644 
2645 
2646     /* Check the file that only stored gigantic messages in its second
2647      * index.  Since no messages were that big, it should be identical
2648      * to the file with an empty index.
2649      */
2650     if(share_some_btree.empty_size != share_some_toobig_index.empty_size)
2651         VERIFY(0, 1, "h5_get_file_size");
2652     if(share_some_btree.first_dset != share_some_toobig_index.first_dset)
2653         VERIFY(0, 1, "h5_get_file_size");
2654     if(share_some_btree.dsets1 != share_some_toobig_index.dsets1)
2655         VERIFY(0, 1, "h5_get_file_size");
2656     if(share_some_btree.dsets2 != share_some_toobig_index.dsets2)
2657         VERIFY(0, 1, "h5_get_file_size");
2658     if(share_some_btree.interleaved != share_some_toobig_index.interleaved)
2659         VERIFY(0, 1, "h5_get_file_size");
2660     if(share_some_btree.attrs1 != share_some_toobig_index.attrs1)
2661         VERIFY(0, 1, "h5_get_file_size");
2662     if(share_some_btree.attrs2 != share_some_toobig_index.attrs2)
2663         VERIFY(0, 1, "h5_get_file_size");
2664 
2665 
2666     /* Check the file that shares even very tiny messages.  Once messages
2667      * are written to it, it should gain a little space from sharing the
2668      * messages and lose a little space to overhead so that it's just slightly
2669      * smaller than a file that doesn't share tiny messages.
2670      * If the overhead increases or the size of messages decreases, these
2671      * numbers may be off.
2672      */
2673     if(share_tiny_index.empty_size != type_space_index.empty_size)
2674         VERIFY(share_tiny_index.empty_size, type_space_index.empty_size, "h5_get_file_size");
2675 
2676     if(share_tiny_index.first_dset >= (h5_stat_size_t)((float)type_space_index.first_dset * OVERHEAD_ALLOWED))
2677         VERIFY(share_tiny_index.first_dset, type_space_index.first_dset, "h5_get_file_size");
2678     if(share_tiny_index.first_dset < type_space_index.first_dset)
2679         VERIFY(0, 1, "h5_get_file_size");
2680 
2681     if(share_tiny_index.second_dset >= type_space_index.second_dset)
2682         VERIFY(share_tiny_index.second_dset, type_space_index.second_dset, "h5_get_file_size");
2683     if((h5_stat_size_t)((float)share_tiny_index.second_dset * OVERHEAD_ALLOWED) < type_space_index.second_dset)
2684         VERIFY(0, 1, "h5_get_file_size");
2685 
2686     if(share_tiny_index.dsets1 >= type_space_index.dsets1)
2687         VERIFY(0, 1, "h5_get_file_size");
2688     if((h5_stat_size_t)((float)share_tiny_index.dsets1 * OVERHEAD_ALLOWED) < type_space_index.dsets1)
2689         VERIFY(0, 1, "h5_get_file_size");
2690 
2691     if(share_tiny_index.dsets2 >= type_space_index.dsets2)
2692         VERIFY(0, 1, "h5_get_file_size");
2693     if((h5_stat_size_t)((float)share_tiny_index.dsets2 * OVERHEAD_ALLOWED) < type_space_index.dsets2)
2694         VERIFY(0, 1, "h5_get_file_size");
2695 
2696     if(share_tiny_index.interleaved >= type_space_index.interleaved)
2697         VERIFY(0, 1, "h5_get_file_size");
2698     if((h5_stat_size_t)((float)share_tiny_index.interleaved * OVERHEAD_ALLOWED) < type_space_index.interleaved)
2699         VERIFY(0, 1, "h5_get_file_size");
2700 
2701     if(share_tiny_index.attrs1 >= type_space_index.attrs1)
2702         VERIFY(0, 1, "h5_get_file_size");
2703     if((h5_stat_size_t)((float)share_tiny_index.attrs1 * OVERHEAD_ALLOWED) < type_space_index.attrs1)
2704         VERIFY(0, 1, "h5_get_file_size");
2705 
2706     if(share_tiny_index.attrs2 >= type_space_index.attrs2)
2707         VERIFY(0, 1, "h5_get_file_size");
2708     if((h5_stat_size_t)((float)share_tiny_index.attrs2 * OVERHEAD_ALLOWED) < type_space_index.attrs2)
2709         VERIFY(0, 1, "h5_get_file_size");
2710 } /* test_sohm_size2 */
2711 
2712 
2713 /*-------------------------------------------------------------------------
2714  * Function:    delete_helper_write
2715  *
2716  * Purpose:     Creates a dataset and attribute in file FILE_ID using value X
2717  *              in the DSPACE_ID and DCPL_ID arrays.
2718  *
2719  * Programmer:  James Laird
2720  *              Tuesday, December 19, 2006
2721  *
2722  * Modifications:
2723  *
2724  *-------------------------------------------------------------------------
2725  */
2726 static void
delete_helper_write(hid_t file_id,hid_t * dspace_id,hid_t * dcpl_id,int x)2727 delete_helper_write(hid_t file_id, hid_t *dspace_id, hid_t *dcpl_id, int x)
2728 {
2729     hid_t  dset_id = -1;
2730     hid_t  attr_id = -1;
2731     char   wdata;
2732     herr_t ret;
2733 
2734     dset_id = H5Dcreate2(file_id, DSETNAME[x], H5T_NATIVE_CHAR, dspace_id[x], H5P_DEFAULT, dcpl_id[x], H5P_DEFAULT);
2735     CHECK_I(dset_id, "H5Dcreate2");
2736     wdata = (char)(x + 'a');
2737     ret = H5Dwrite(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &wdata);
2738     CHECK_I(ret, "H5Dwrite");
2739 
2740     attr_id = H5Acreate2(dset_id, "attr_name", H5T_NATIVE_CHAR, dspace_id[x], H5P_DEFAULT, H5P_DEFAULT);
2741     CHECK_I(attr_id, "H5Acreate2");
2742     ret = H5Awrite(attr_id, H5T_NATIVE_CHAR, &wdata);
2743     CHECK_I(ret, "H5Awrite");
2744 
2745     ret = H5Aclose(attr_id);
2746     CHECK_I(ret, "H5Aclose");
2747     ret = H5Dclose(dset_id);
2748     CHECK_I(ret, "H5Dclose");
2749 } /* delete_helper_write */
2750 
2751 
2752 /*-------------------------------------------------------------------------
2753  * Function:    delete_helper_read
2754  *
2755  * Purpose:     Checks the value of the dataset and attribute created by
2756  *              delete_helper_write.
2757  *
2758  * Programmer:  James Laird
2759  *              Tuesday, December 19, 2006
2760  *
2761  * Modifications:
2762  *
2763  *-------------------------------------------------------------------------
2764  */
2765 static void
delete_helper_read(hid_t file_id,hid_t * dspace_id,int x)2766 delete_helper_read(hid_t file_id, hid_t *dspace_id, int x)
2767 {
2768     hid_t dset_id = -1;
2769     hid_t attr_id = -1;
2770     char rdata;
2771     herr_t ret;
2772 
2773     dset_id = H5Dopen2(file_id, DSETNAME[x], H5P_DEFAULT);
2774     CHECK_I(dset_id, "H5Dopen2");
2775     rdata = '\0';
2776     ret = H5Dread(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &rdata);
2777     CHECK_I(ret, "H5Dread");
2778     VERIFY(rdata, (x + 'a'), "H5Dread");
2779 
2780     attr_id = H5Aopen(dset_id, "attr_name", H5P_DEFAULT);
2781     CHECK_I(attr_id, "H5Aopen");
2782     rdata = '\0';
2783     ret = H5Aread(attr_id, H5T_NATIVE_CHAR, &rdata);
2784     CHECK_I(ret, "H5Dread");
2785     VERIFY(rdata, (x + 'a'), "H5Dread");
2786 
2787     ret = H5Aclose(attr_id);
2788     CHECK_I(ret, "H5Aclose");
2789     ret = H5Dclose(dset_id);
2790     CHECK_I(ret, "H5Dclose");
2791 } /* delete_helper_read */
2792 
2793 
2794 /*-------------------------------------------------------------------------
2795  * Function:    delete_helper
2796  *
2797  * Purpose:     Creates some shared messages, deletes them, and creates some
2798  *              more messages.  The second batch of messages should use the
2799  *              space freed by the first batch, so should be about the same
2800  *              size as a file that never had the first batch of messages
2801  *              created.
2802  *
2803  *              FCPL_ID is the file creation property list to use.
2804  *              DSPACE_ID and DCPL_ID are arrays of different dataspaces
2805  *              and property lists with filter pipelines used to create the
2806  *              messages.
2807  *
2808  * Programmer:  James Laird
2809  *              Tuesday, December 19, 2006
2810  *
2811  * Modifications:
2812  *
2813  *-------------------------------------------------------------------------
2814  */
2815 static void
delete_helper(hid_t fcpl_id,hid_t * dspace_id,hid_t * dcpl_id)2816 delete_helper(hid_t fcpl_id, hid_t *dspace_id, hid_t *dcpl_id)
2817 {
2818     hid_t file_id=-1;
2819     int x;
2820     h5_stat_size_t norm_filesize;
2821     h5_stat_size_t deleted_filesize;
2822     herr_t ret;
2823 
2824     /* Get the size of a "normal" file with no deleted messages */
2825     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
2826     CHECK_I(file_id, "H5Fcreate");
2827 
2828     /* Create batch of messages in the file starting at message 2 */
2829     for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
2830         delete_helper_write(file_id, dspace_id, dcpl_id, x);
2831     }
2832 
2833     /* Check that messages can be read */
2834     for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
2835         delete_helper_read(file_id, dspace_id, x);
2836     }
2837 
2838     /* Close file and get filesize */
2839     ret = H5Fclose(file_id);
2840     CHECK_I(ret, "H5Fclose");
2841     norm_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
2842 
2843     /* Create a new file with messages 0 to (HALF_DELETE_NUM_MESGS - 1) */
2844     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
2845     CHECK_I(file_id, "H5Fcreate");
2846 
2847     for(x=0; x<HALF_DELETE_NUM_MESGS; ++x) {
2848         delete_helper_write(file_id, dspace_id, dcpl_id, x);
2849     }
2850 
2851     /* Verify each dataset, then delete it (which should delete
2852      * its shared messages as well
2853      */
2854     for(x=0; x<HALF_DELETE_NUM_MESGS; ++x) {
2855         delete_helper_read(file_id, dspace_id, x);
2856         ret = H5Ldelete(file_id, DSETNAME[x], H5P_DEFAULT);
2857         CHECK_I(ret, "H5Ldelete");
2858     }
2859 
2860     /* The file is now empty.  Write and verify the second batch of messages
2861      * again.
2862      */
2863     for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
2864         delete_helper_write(file_id, dspace_id, dcpl_id, x);
2865     }
2866     for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
2867         delete_helper_read(file_id, dspace_id, x);
2868     }
2869 
2870     /* Close file and get filesize */
2871     ret = H5Fclose(file_id);
2872     CHECK_I(ret, "H5Fclose");
2873     deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
2874 
2875     /* The two filesizes should be almost the same */
2876     if(norm_filesize > (h5_stat_size_t)((float)deleted_filesize * OVERHEAD_ALLOWED))
2877         VERIFY(norm_filesize, deleted_filesize, "h5_get_file_size");
2878     if(deleted_filesize > (h5_stat_size_t)((float)norm_filesize * OVERHEAD_ALLOWED))
2879         VERIFY(deleted_filesize, norm_filesize, "h5_get_file_size");
2880 } /* delete_helper */
2881 
2882 
2883 /*-------------------------------------------------------------------------
2884  * Function:    test_sohm_delete
2885  *
2886  * Purpose:     Tests shared object header message deletion.
2887  *
2888  *              Creates lots of shared messages, then ensures that they
2889  *              can be deleted without corrupting the remaining messages.
2890  *              Also checks that indexes convert from B-trees back into
2891  *              lists.
2892  *
2893  * Programmer:  James Laird
2894  *              Tuesday, December 19, 2006
2895  *
2896  * Modifications:
2897  *
2898  *-------------------------------------------------------------------------
2899  */
2900 static void
test_sohm_delete(void)2901 test_sohm_delete(void)
2902 {
2903     hid_t fcpl_id;
2904     /* We'll use dataspaces and filter pipelines for this test.
2905      *  Create a number of distinct messages of each type.
2906      */
2907     hid_t dspace_id[DELETE_NUM_MESGS] = {0};
2908     hid_t dcpl_id[DELETE_NUM_MESGS] = {0};
2909     unsigned u;
2910     int x;
2911     hsize_t dims[] = DELETE_DIMS;
2912     herr_t ret;
2913 
2914     MESSAGE(5, ("Testing deletion of SOHMs\n"));
2915 
2916     /* Create a number of different dataspaces.
2917      * For simplicity, each dataspace has only one element.
2918      */
2919    for(u = 0; u < DELETE_NUM_MESGS; ++u) {
2920         dspace_id[u] = H5Screate_simple((int)(u + 1), dims, dims);
2921         CHECK_I(dspace_id[u], "H5Screate_simple");
2922     } /* end for */
2923 
2924     /* Create a number of different filter pipelines. */
2925     dcpl_id[0] = H5Pcreate(H5P_DATASET_CREATE);
2926     CHECK_I(dcpl_id[0], "H5Pcreate");
2927 
2928     ret = H5Pset_chunk(dcpl_id[0], 1, dims);
2929     CHECK_I(ret, "H5Pset_chunk");
2930     ret = H5Pset_shuffle(dcpl_id[0]);
2931     CHECK_I(ret, "H5Pset_shuffle");
2932 
2933     for(u = 1; u < DELETE_NUM_MESGS; u += 2) {
2934         dcpl_id[u] = H5Pcopy(dcpl_id[u - 1]);
2935         CHECK_I(dcpl_id[u], "H5Pcopy");
2936         ret = H5Pset_chunk(dcpl_id[u], (int)(u + 1), dims);
2937         CHECK_I(ret, "H5Pset_chunk");
2938         ret = H5Pset_deflate(dcpl_id[u], 1);
2939         CHECK_I(ret, "H5Pset_deflate");
2940 
2941         dcpl_id[u + 1] = H5Pcopy(dcpl_id[u]);
2942         CHECK_I(dcpl_id[u + 1], "H5Pcopy");
2943         ret = H5Pset_chunk(dcpl_id[u + 1], (int)(u + 2), dims);
2944         CHECK_I(ret, "H5Pset_chunk");
2945         ret = H5Pset_shuffle(dcpl_id[u + 1]);
2946         CHECK_I(ret, "H5Pset_shuffle");
2947     } /* end for */
2948 
2949     /* Create an fcpl where all messages are shared in the same index */
2950     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
2951     CHECK_I(fcpl_id, "H5Pcreate");
2952     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
2953     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
2954     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
2955     CHECK_I(ret, "H5Pset_shared_mesg_index");
2956 
2957 
2958     /* Use big list indexes */
2959     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 4 * DELETE_NUM_MESGS, 0);
2960     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2961 
2962     /* Test that messages can be created and deleted properly */
2963     delete_helper(fcpl_id, dspace_id, dcpl_id);
2964 
2965     /* Use B-tree indexes */
2966     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
2967     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2968 
2969     delete_helper(fcpl_id, dspace_id, dcpl_id);
2970 
2971 
2972     /* Use small list indexes that will convert from lists to B-trees and back */
2973     ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS, HALF_DELETE_NUM_MESGS - 1);
2974     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2975 
2976     delete_helper(fcpl_id, dspace_id, dcpl_id);
2977 
2978 
2979     /* Use two indexes */
2980     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
2981     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
2982     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_ATTR_FLAG, 16);
2983     CHECK_I(ret, "H5Pset_shared_mesg_index");
2984     ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_DTYPE_FLAG, 16);
2985     CHECK_I(ret, "H5Pset_shared_mesg_index");
2986 
2987     /* Use big list indexes */
2988     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 5000, 0);
2989     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2990 
2991 
2992     /* Use B-tree indexes */
2993     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
2994     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
2995 
2996     delete_helper(fcpl_id, dspace_id, dcpl_id);
2997 
2998 
2999     /* Set phase change values so that one index converts to a B-tree and one doesn't */
3000     ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS + 1, 0);
3001     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3002 
3003     delete_helper(fcpl_id, dspace_id, dcpl_id);
3004 
3005 
3006     /* Test with varying message sizes (ideally, so some messages are too
3007      * small to be written but some are big enough that they are still written
3008      */
3009     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
3010     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3011     for(u = DELETE_MIN_MESG_SIZE; u <= DELETE_MAX_MESG_SIZE; u += 10) {
3012         ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, u);
3013         CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3014         delete_helper(fcpl_id, dspace_id, dcpl_id);
3015     } /* end for */
3016 
3017     /* Cleanup */
3018     ret = H5Pclose(fcpl_id);
3019     CHECK_I(ret, "H5Pclose");
3020 
3021     for(x = DELETE_NUM_MESGS - 1; x >= 0; --x) {
3022         ret = H5Sclose(dspace_id[x]);
3023         CHECK_I(ret, "H5Sclose");
3024         ret = H5Pclose(dcpl_id[x]);
3025         CHECK_I(ret, "H5Pclose");
3026     } /* end for */
3027 } /* test_sohm_delete */
3028 
3029 
3030 /*-------------------------------------------------------------------------
3031  * Function:    verify_dset_create_and_delete_does_not_grow_file
3032  *
3033  * Purpose:     Tests that shared object header message deletion returns
3034  *              the file to its previous state using the supplied FCPL.
3035  *
3036  *              Creates a file according to the supplied FCPL,
3037  *              then creates datasets and deletes them.
3038  *              Done in two passes: once with one dataset, once with two.
3039  *
3040  * Programmer:  James Laird
3041  *              Wednesday, January 3, 2007
3042  *
3043  * Modifications:
3044  *
3045  *-------------------------------------------------------------------------
3046  */
3047 static int
verify_dset_create_and_delete_does_not_grow_file(hid_t fcpl_id)3048 verify_dset_create_and_delete_does_not_grow_file(hid_t fcpl_id)
3049 {
3050     hid_t file_id;
3051     hid_t dspace_id;
3052     hid_t dset_id;
3053     hsize_t dims[1] = {1};
3054     h5_stat_size_t initial_filesize, deleted_filesize;
3055     int old_nerrs;              /* Number of errors when entering this routine */
3056     herr_t ret;
3057 
3058     /* Retrieve the current # of reported errors */
3059     old_nerrs = GetTestNumErrs();
3060 
3061     /* Create a dataspace for later */
3062     dspace_id = H5Screate_simple(1, dims, dims);
3063     CHECK_I(dspace_id, "H5Screate_simple");
3064 
3065     /* Create a file using the FCPL supplied*/
3066     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
3067     CHECK_I(file_id, "H5Fcreate");
3068 
3069     /* Close the file and get its size */
3070     ret = H5Fclose(file_id);
3071     CHECK_I(ret, "H5Fclose");
3072     initial_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
3073 
3074 
3075     /* Re-create the file and create a dataset in it */
3076     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
3077     CHECK_I(file_id, "H5Fcreate");
3078 
3079     dset_id = H5Dcreate2(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
3080     CHECK_I(dset_id, "H5Dcreate2");
3081 
3082     /* Close the dataset and delete it */
3083     ret = H5Dclose(dset_id);
3084     CHECK_I(ret, "H5Dclose");
3085     ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
3086     CHECK_I(ret, "H5Ldelete");
3087 
3088     /* Close the file and get its size */
3089     ret = H5Fclose(file_id);
3090     CHECK_I(ret, "H5Fclose");
3091     deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
3092 
3093     VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
3094 
3095 
3096     /* Repeat, creating two datasets in the file */
3097     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
3098     CHECK_I(file_id, "H5Fcreate");
3099 
3100     /* Create and close the first dataset */
3101     dset_id = H5Dcreate2(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
3102     CHECK_I(dset_id, "H5Dcreate2");
3103     ret = H5Dclose(dset_id);
3104     CHECK_I(ret, "H5Dclose");
3105 
3106     /* Create and close the second.  These messages should be shared */
3107     dset_id = H5Dcreate2(file_id, "dset2", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
3108     CHECK_I(dset_id, "H5Dcreate2");
3109     ret = H5Dclose(dset_id);
3110     CHECK_I(ret, "H5Dclose");
3111 
3112     /* Delete both datasets */
3113     ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
3114     CHECK_I(ret, "H5Ldelete");
3115     ret = H5Ldelete(file_id, "dset2", H5P_DEFAULT);
3116     CHECK_I(ret, "H5Ldelete");
3117 
3118     /* Close the file and get its size */
3119     ret = H5Fclose(file_id);
3120     CHECK_I(ret, "H5Fclose");
3121     deleted_filesize = h5_get_file_size(FILENAME, H5P_DEFAULT);
3122 
3123     VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
3124 
3125 
3126     /* Cleanup */
3127     ret = H5Sclose(dspace_id);
3128     CHECK_I(ret, "H5Sclose");
3129 
3130     /* Retrieve current # of errors */
3131     if(old_nerrs == GetTestNumErrs())
3132         return(0);
3133     else
3134         return(-1);
3135 } /* verify_dset_create_and_delete_does_not_grow_file */
3136 
3137 
3138 /*-------------------------------------------------------------------------
3139  * Function:    test_sohm_delete_revert
3140  *
3141  * Purpose:     Verifies that creation and deletion of datasets with shared
3142  *              message headers will not increase file size.
3143  *
3144  * Programmer:  James Laird
3145  *              Wednesday, January 3, 2007
3146  *
3147  * Modifications:
3148  *
3149  *-------------------------------------------------------------------------
3150  */
3151 static void
test_sohm_delete_revert(void)3152 test_sohm_delete_revert(void)
3153 {
3154     hid_t fcpl_id;
3155     herr_t ret;
3156 
3157     MESSAGE(5, ("Testing that file reverts to original size on SOHM deletion\n"));
3158 
3159     /* Create an fcpl with messages in two indexes */
3160     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
3161     CHECK_I(fcpl_id, "H5Pcreate");
3162     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
3163     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3164     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_DTYPE_FLAG, 10);
3165     CHECK_I(ret, "H5Pset_shared_mesg_index");
3166     ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_SHMESG_SDSPACE_FLAG, 10);
3167     CHECK_I(ret, "H5Pset_shared_mesg_index");
3168 
3169     /* Call the helper function to test this FCPL. */
3170     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3171     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3172 
3173     /* Try using B-trees */
3174     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
3175     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3176     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3177     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3178 
3179 
3180     /* Try sharing all messages */
3181     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
3182     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3183     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 10);
3184     CHECK_I(ret, "H5Pset_shared_mesg_index");
3185     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 5);
3186     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3187 
3188     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3189     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3190 
3191     /* Try using B-trees */
3192     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
3193     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3194     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3195     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3196 
3197     /* There should be at least two messages in the test (datatype and
3198      * dataspace).  Use an index that will transition from a list to
3199      * a B-tree and back.
3200      */
3201     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1, 2);
3202     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3203     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3204     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3205 
3206 
3207     /* Try with shared messages enabled, but when messages are too big
3208      * to be shared.
3209      */
3210     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 35);
3211     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3212     ret = verify_dset_create_and_delete_does_not_grow_file(fcpl_id);
3213     CHECK_I(ret, "verify_dset_create_and_delete_does_not_grow_file");
3214 
3215     ret = H5Pclose(fcpl_id);
3216     CHECK_I(ret, "H5Pclose");
3217 } /* test_sohm_delete_revert */
3218 
3219 
3220 /*-------------------------------------------------------------------------
3221  * Function:    verify_dset_create_and_open_through_extlink_with_sohm
3222  *
3223  * Purpose:     Tests that a dataset created through an external link can
3224  *              be opened (that shared messages were created or not and
3225  *              were shared in the right file).
3226  *
3227  * Programmer:  James Laird
3228  *              Friday, December 22, 2006
3229  *
3230  * Modifications:
3231  *
3232  *-------------------------------------------------------------------------
3233  */
3234 static void
verify_dset_create_and_open_through_extlink_with_sohm(hid_t src_fcpl_id,hid_t dst_fcpl_id)3235 verify_dset_create_and_open_through_extlink_with_sohm(hid_t src_fcpl_id, hid_t dst_fcpl_id)
3236 {
3237     hid_t src_file_id = -1;
3238     hid_t dst_file_id = -1;
3239     hid_t space_id = -1;
3240     hid_t dset_id = -1;
3241     hsize_t dims[] = {1, 1};
3242     herr_t ret;
3243 
3244     /* Create files */
3245     src_file_id = H5Fcreate(FILENAME_SRC, H5F_ACC_TRUNC, src_fcpl_id, H5P_DEFAULT);
3246     CHECK_I(src_file_id, "H5Fcreate");
3247     dst_file_id = H5Fcreate(FILENAME_DST, H5F_ACC_TRUNC, dst_fcpl_id, H5P_DEFAULT);
3248     CHECK_I(dst_file_id, "H5Fcreate");
3249 
3250     /* Create an external link from the source file to the destination file */
3251     ret = H5Lcreate_external(FILENAME_DST, "/", src_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);
3252     CHECK_I(ret, "H5Lcreate_external");
3253 
3254     /* Create a dataset through the external link */
3255     space_id = H5Screate_simple(2, dims, dims);
3256     CHECK_I(space_id, "H5Screate_simple");
3257     dset_id = H5Dcreate2(src_file_id, "ext_link/dataset", H5T_NATIVE_FLOAT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
3258     CHECK_I(dset_id, "H5Dcreate2");
3259 
3260     /* Close the dataset and both files to make sure everything gets flushed
3261      * out of memory
3262      */
3263     ret = H5Sclose(space_id);
3264     CHECK_I(ret, "H5Sclose");
3265     ret = H5Dclose(dset_id);
3266     CHECK_I(ret, "H5Dclose");
3267     ret = H5Fclose(src_file_id);
3268     CHECK_I(ret, "H5Fclose");
3269     ret = H5Fclose(dst_file_id);
3270     CHECK_I(ret, "H5Fclose");
3271 
3272     /* Ensure that the dataset can be opened.  If the messages were written in
3273      * the wrong file, it'll be impossible to read the dataset's object
3274      * header.
3275      */
3276     dst_file_id = H5Fopen(FILENAME_DST, H5F_ACC_RDONLY, H5P_DEFAULT);
3277     CHECK_I(dst_file_id, "H5Fopen");
3278     dset_id = H5Dopen2(dst_file_id, "dataset", H5P_DEFAULT);
3279     CHECK_I(dset_id, "H5Dopen2");
3280 
3281     /* Cleanup */
3282     ret = H5Dclose(dset_id);
3283     CHECK_I(ret, "H5Dclose");
3284     ret = H5Fclose(dst_file_id);
3285     CHECK_I(ret, "H5Fclose");
3286 } /* verify_dset_create_and_open_through_extlink_with_sohm */
3287 
3288 
3289 /*-------------------------------------------------------------------------
3290  * Function:    test_sohm_extlink
3291  *
3292  * Purpose:     Test creating SOHMs through external links (to make sure that
3293  *              they're created in the correct file).
3294  *
3295  * Programmer:  James Laird
3296  *              Friday, December 22, 2006
3297  *
3298  * Modifications:
3299  *
3300  *-------------------------------------------------------------------------
3301  */
3302 static void
test_sohm_extlink(void)3303 test_sohm_extlink(void)
3304 {
3305     hid_t fcpl_id = -1;
3306     herr_t ret;
3307 
3308     MESSAGE(5, ("Testing SOHM creation through external links\n"));
3309 
3310     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
3311     CHECK_I(fcpl_id, "H5Pcreate");
3312     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
3313     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3314     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
3315     CHECK_I(ret, "H5Pset_shared_mesg_index");
3316 
3317     verify_dset_create_and_open_through_extlink_with_sohm(fcpl_id, H5P_DEFAULT);
3318     verify_dset_create_and_open_through_extlink_with_sohm(H5P_DEFAULT, fcpl_id);
3319     verify_dset_create_and_open_through_extlink_with_sohm(fcpl_id, fcpl_id);
3320 
3321     ret = H5Pclose(fcpl_id);
3322     CHECK_I(ret, "H5Pclose");
3323 } /* test_sohm_extlink */
3324 
3325 
3326 /*-------------------------------------------------------------------------
3327  * Function:    verify_dataset_extension
3328  *
3329  * Purpose:     Tests extending a dataset's dataspace when sharing is
3330  *              enabled.
3331  *
3332  *              If close_reopen is TRUE, closes and reopens the file to
3333  *              ensure that data is correctly written to disk.
3334  *
3335  * Programmer:  James Laird
3336  *              Wednesday, January 10, 2007
3337  *
3338  * Modifications:
3339  *
3340  *-------------------------------------------------------------------------
3341  */
3342 static int
verify_dataset_extension(hid_t fcpl_id,hbool_t close_reopen)3343 verify_dataset_extension(hid_t fcpl_id, hbool_t close_reopen)
3344 {
3345     hid_t file_id = -1;
3346     hid_t orig_space_id = -1;
3347     hid_t space1_id, space2_id, space3_id;
3348     hid_t dcpl_id = -1;
3349     hid_t dset1_id, dset2_id, dset3_id;
3350     hsize_t dims1[] = {1, 2};
3351     hsize_t max_dims[] = {H5S_UNLIMITED, 2};
3352     hsize_t dims2[] = {5, 2};
3353     hsize_t out_dims[2];
3354     hsize_t out_maxdims[2];
3355     int x;
3356     int old_nerrs;           /* Number of errors when entering this routine */
3357     herr_t ret;
3358 
3359     hsize_t *space_dims[3];
3360 
3361 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3362  * Macro:      TSOHM_VDE_VERIFY_SPACES
3363  *
3364  * Purpose:    Encapsulate a common pattern
3365  *             Open, read-verify, and close the dataspaces for datasets 1-3
3366  *
3367  * Programmer: Jacob Smith
3368  *             2018 November 5
3369  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3370  */
3371 #define TSOHM_VDE_VERIFY_SPACES(dims)                                     \
3372 {                                                                         \
3373     /* Open dataspaces                                                    \
3374      */                                                                   \
3375     space1_id = H5Dget_space(dset1_id);                                   \
3376     CHECK_I(space1_id, "H5Dget_space");                                   \
3377     space2_id = H5Dget_space(dset2_id);                                   \
3378     CHECK_I(space2_id, "H5Dget_space");                                   \
3379     space3_id = H5Dget_space(dset3_id);                                   \
3380     CHECK_I(space3_id, "H5Dget_space");                                   \
3381     /* Verify dataspaces                                                  \
3382      */                                                                   \
3383     ret = H5Sget_simple_extent_dims(space1_id, out_dims, out_maxdims);    \
3384     CHECK_I(ret, "H5Sget_simple_extent_dims");                            \
3385     for(x=0; x<EXTEND_NDIMS; ++x) {                                       \
3386         VERIFY(out_dims[x], (dims)[0][x], "H5Sget_simple_extent_dims");   \
3387         VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
3388     }                                                                     \
3389     ret = H5Sget_simple_extent_dims(space2_id, out_dims, out_maxdims);    \
3390     CHECK_I(ret, "H5Sget_simple_extent_dims");                            \
3391     for(x=0; x<EXTEND_NDIMS; ++x) {                                       \
3392         VERIFY(out_dims[x], (dims)[1][x], "H5Sget_simple_extent_dims");   \
3393         VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
3394     }                                                                     \
3395     ret = H5Sget_simple_extent_dims(space3_id, out_dims, out_maxdims);    \
3396     CHECK_I(ret, "H5Sget_simple_extent_dims");                            \
3397     for(x=0; x<EXTEND_NDIMS; ++x) {                                       \
3398         VERIFY(out_dims[x], (dims)[2][x], "H5Sget_simple_extent_dims");   \
3399         VERIFY(out_maxdims[x], max_dims[x], "H5Sget_simple_extent_dims"); \
3400     }                                                                     \
3401     /* Close dataspaces                                                   \
3402      */                                                                   \
3403     CHECK_I(H5Sclose(space1_id), "H5Sclose");                             \
3404     CHECK_I(H5Sclose(space2_id), "H5Sclose");                             \
3405     CHECK_I(H5Sclose(space3_id), "H5Sclose");                             \
3406 } /* define TSOHM_VDE_VERIFY_SPACES */
3407 
3408 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3409  * Macro:      TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS()
3410  *
3411  * Purpose:    Encapsulate a common pattern
3412  *             Wrapper to close and reopen file and datasets:
3413  *                + "dataset" (dset_id)
3414  *                + if n > 1 then include "dataset2" (dset_id2)
3415  *                + if n > 2 then include "dataset3" (dset_id3)
3416  *                + file (file_id)
3417  *
3418  * Programmer: Jacob Smith
3419  *             2018 November 5
3420  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3421  */
3422 #define TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(n)               \
3423 {                                                              \
3424     CHECK_I(H5Dclose(dset1_id), "H5Dclose");                   \
3425     if ((n) > 1)                                               \
3426         CHECK_I(H5Dclose(dset2_id), "H5Dclose");               \
3427     if ((n) > 2)                                               \
3428         CHECK_I(H5Dclose(dset3_id), "H5Dclose");               \
3429     CHECK_I(H5Fclose(file_id), "H5Fclose");                    \
3430                                                                \
3431     file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);    \
3432     CHECK_I(file_id, "H5Fopen");                               \
3433     dset1_id = H5Dopen2(file_id, "dataset", H5P_DEFAULT);      \
3434     CHECK_I(dset1_id, "H5Dopen2");                             \
3435     if ((n) > 1) {                                             \
3436         dset2_id = H5Dopen2(file_id, "dataset2", H5P_DEFAULT); \
3437         CHECK_I(dset2_id, "H5Dopen2");                         \
3438     }                                                          \
3439     if ((n) > 2) {                                             \
3440         dset3_id = H5Dopen2(file_id, "dataset3", H5P_DEFAULT); \
3441         CHECK_I(dset3_id, "H5Dopen2");                         \
3442     }                                                          \
3443 } /* define TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS */
3444 
3445     /* Remember the current # of reported errors */
3446     old_nerrs = GetTestNumErrs();
3447 
3448     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
3449     CHECK_I(file_id, "H5Fcreate");
3450 
3451     /* Create property list with chunking */
3452     dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
3453     CHECK_I(dcpl_id, "H5Pcreate");
3454     ret = H5Pset_chunk(dcpl_id, 2, dims1);
3455     CHECK_I(ret, "H5Pset_chunk");
3456 
3457     /* Create a dataspace and a dataset*/
3458     orig_space_id = H5Screate_simple(EXTEND_NDIMS, dims1, max_dims);
3459     CHECK_I(orig_space_id, "H5Screate_simple");
3460     dset1_id = H5Dcreate2(file_id, "dataset", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3461     CHECK_I(dset1_id, "H5Dcreate2");
3462     if(close_reopen)
3463         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
3464 
3465     /* Create another dataset starting with the same dataspace */
3466     dset2_id = H5Dcreate2(file_id, "dataset2", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3467     CHECK_I(dset2_id, "H5Dcreate2");
3468     if (close_reopen)
3469         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
3470 
3471     /* Create a third dataset with the same dataspace */
3472     dset3_id = H5Dcreate2(file_id, "dataset3", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3473     CHECK_I(dset3_id, "H5Dcreate2");
3474     if (close_reopen)
3475         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3476 
3477     /* Extend the first dataset */
3478     ret = H5Dset_extent(dset1_id, dims2);
3479     CHECK_I(ret, "H5Dset_extent");
3480     if (close_reopen)
3481         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3482 
3483     space_dims[0] = dims2;
3484     space_dims[1] = dims1;
3485     space_dims[2] = dims1;
3486     TSOHM_VDE_VERIFY_SPACES(space_dims);
3487 
3488     /* Extend the second dataset */
3489     ret = H5Dset_extent(dset2_id, dims2);
3490     CHECK_I(ret, "H5Dset_extent");
3491     if(close_reopen)
3492         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3493 
3494     space_dims[1] = dims2;
3495     TSOHM_VDE_VERIFY_SPACES(space_dims);
3496 
3497     /* Extend the third dataset */
3498     ret = H5Dset_extent(dset3_id, dims2);
3499     CHECK_I(ret, "H5Dset_extent");
3500     if(close_reopen)
3501         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3502 
3503     space_dims[2] = dims2;
3504     TSOHM_VDE_VERIFY_SPACES(space_dims);
3505 
3506     /* Close the datasets and file */
3507     ret = H5Dclose(dset1_id);
3508     CHECK_I(ret, "H5Dclose");
3509     ret = H5Dclose(dset2_id);
3510     CHECK_I(ret, "H5Dclose");
3511     ret = H5Dclose(dset3_id);
3512     CHECK_I(ret, "H5Dclose");
3513     ret = H5Fclose(file_id);
3514     CHECK_I(ret, "H5Fclose");
3515 
3516 
3517 
3518     /* Change the order in which datasets are extended to ensure that there
3519      * are no problems if a dataspace goes from being shared to not being
3520      * shared or vice versa.
3521      */
3522     file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
3523     CHECK_I(file_id, "H5Fcreate");
3524     dset1_id = H5Dcreate2(file_id, "dataset", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3525     CHECK_I(dset1_id, "H5Dcreate2");
3526     if (close_reopen)
3527         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
3528 
3529     /* Extend the first dataset */
3530     ret = H5Dset_extent(dset1_id, dims2);
3531     CHECK_I(ret, "H5Dset_extent");
3532     if (close_reopen)
3533         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(1);
3534 
3535     /* Create the second dataset.  Its dataspace will be unshared and then
3536      * become shared when extended.
3537      */
3538     dset2_id = H5Dcreate2(file_id, "dataset2", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3539     CHECK_I(dset2_id, "H5Dcreate2");
3540     if (close_reopen)
3541         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
3542 
3543     /* Extend the second dataset */
3544     ret = H5Dset_extent(dset2_id, dims2);
3545     CHECK_I(ret, "H5Dset_extent");
3546     if (close_reopen)
3547         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(2);
3548 
3549     /* Create the third dataset.  Its dataspace will be unshared and then
3550      * become shared when extended.
3551      */
3552     dset3_id = H5Dcreate2(file_id, "dataset3", H5T_NATIVE_LONG, orig_space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
3553     CHECK_I(dset3_id, "H5Dcreate2");
3554     if(close_reopen)
3555         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3556 
3557     /* Extend the third dataset */
3558     ret = H5Dset_extent(dset3_id, dims2);
3559     CHECK_I(ret, "H5Dset_extent");
3560     if(close_reopen)
3561         TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS(3);
3562 
3563     TSOHM_VDE_VERIFY_SPACES(space_dims);
3564 
3565     /* Close the datasets and file */
3566     ret = H5Dclose(dset1_id);
3567     CHECK_I(ret, "H5Dclose");
3568     ret = H5Dclose(dset2_id);
3569     CHECK_I(ret, "H5Dclose");
3570     ret = H5Dclose(dset3_id);
3571     CHECK_I(ret, "H5Dclose");
3572     ret = H5Fclose(file_id);
3573     CHECK_I(ret, "H5Fclose");
3574 
3575     /* Cleanup */
3576     ret = H5Sclose(orig_space_id);
3577     CHECK_I(ret, "H5Sclose");
3578     ret = H5Pclose(dcpl_id);
3579     CHECK_I(ret, "H5Pclose");
3580 
3581     /* Complain if this test generated errors */
3582     if(old_nerrs == GetTestNumErrs())
3583         return(0);
3584     else
3585         return(-1);
3586 /* macros are exclusive to this function */
3587 #undef TSOHM_VDE_CLOSE_REOPEN_FILE_AND_DSETS
3588 #undef TSOHM_VDE_VERIFY_SPACES
3589 } /* verify_dataset_extension */
3590 
3591 
3592 /*-------------------------------------------------------------------------
3593  * Function:    test_sohm_extend_dset
3594  *
3595  * Purpose:     Test extended shared dataspaces.  An extended dataset's
3596  *              dataspace will change, possibly confusing the shared message
3597  *              code.
3598  *
3599  * Programmer:  James Laird
3600  *              Wednesday, January 10, 2007
3601  *
3602  * Modifications:
3603  *
3604  *-------------------------------------------------------------------------
3605  */
3606 static void
test_sohm_extend_dset(void)3607 test_sohm_extend_dset(void)
3608 {
3609     hid_t fcpl_id = -1;
3610     herr_t ret;
3611 
3612     MESSAGE(5, ("Testing extending shared dataspaces\n"));
3613 
3614     fcpl_id = H5Pcreate(H5P_FILE_CREATE);
3615     CHECK_I(fcpl_id, "H5Pcreate");
3616 
3617     /* Test extending datasets with different FCPLs */
3618     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
3619     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3620 
3621     /* No shared messages */
3622     ret = verify_dataset_extension(fcpl_id, FALSE);
3623     CHECK_I(ret, "verify_dataset_extension");
3624     ret = verify_dataset_extension(fcpl_id, TRUE);
3625     CHECK_I(ret, "verify_dataset_extension");
3626 
3627 
3628     /* Only dataspaces */
3629     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_SDSPACE_FLAG, 16);
3630     CHECK_I(ret, "H5Pset_shared_mesg_index");
3631 
3632     ret = verify_dataset_extension(fcpl_id, FALSE);
3633     CHECK_I(ret, "verify_dataset_extension");
3634     ret = verify_dataset_extension(fcpl_id, TRUE);
3635     CHECK_I(ret, "verify_dataset_extension");
3636 
3637     /* All messages */
3638     ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
3639     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3640     ret = H5Pset_shared_mesg_index(fcpl_id, 0, H5O_SHMESG_ALL_FLAG, 16);
3641     CHECK_I(ret, "H5Pset_shared_mesg_index");
3642 
3643     ret = verify_dataset_extension(fcpl_id, FALSE);
3644     CHECK_I(ret, "verify_dataset_extension");
3645     ret = verify_dataset_extension(fcpl_id, TRUE);
3646     CHECK_I(ret, "verify_dataset_extension");
3647 
3648 
3649     /* All messages in lists */
3650     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 100, 50);
3651     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3652 
3653     ret = verify_dataset_extension(fcpl_id, FALSE);
3654     CHECK_I(ret, "verify_dataset_extension");
3655     ret = verify_dataset_extension(fcpl_id, TRUE);
3656     CHECK_I(ret, "verify_dataset_extension");
3657 
3658 
3659     /* All messages in lists converted to B-trees */
3660     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1, 0);
3661     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3662 
3663     ret = verify_dataset_extension(fcpl_id, FALSE);
3664     CHECK_I(ret, "verify_dataset_extension");
3665     ret = verify_dataset_extension(fcpl_id, TRUE);
3666     CHECK_I(ret, "verify_dataset_extension");
3667 
3668 
3669     /* All messages in B-trees */
3670     ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
3671     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3672 
3673     ret = verify_dataset_extension(fcpl_id, FALSE);
3674     CHECK_I(ret, "verify_dataset_extension");
3675     ret = verify_dataset_extension(fcpl_id, TRUE);
3676     CHECK_I(ret, "verify_dataset_extension");
3677 
3678     ret = H5Pclose(fcpl_id);
3679     CHECK_I(ret, "H5Pclose");
3680 } /* test_sohm_extend_dset */
3681 
3682 
3683 /*-------------------------------------------------------------------------
3684  * Function:    test_sohm_external_dtype
3685  *
3686  * Purpose:     When a datatype is a SOHM type in one file, test that the
3687  *              second file using the same datatype actually save it in
3688  *              the file, too.
3689  *
3690  * Programmer:  Raymond Lu
3691  *              13 October, 2008
3692  *
3693  * Modifications:
3694  *
3695  *-------------------------------------------------------------------------
3696  */
3697 static void
test_sohm_external_dtype(void)3698 test_sohm_external_dtype(void)
3699 {
3700     typedef struct s1_t {
3701         int a;
3702         int b;
3703     } s1_t;
3704     s1_t  *s_ptr, *orig;
3705     hid_t fcpl, file1, file2;
3706     hid_t dataset1, dataset2;
3707     hid_t s1_tid, dset1_tid, dset2_tid, space;
3708     hsize_t dims[2] = {NX, NY};
3709     H5T_class_t dtype_class;
3710     size_t dmsg_count;
3711     unsigned x, i;
3712     herr_t ret;
3713 
3714     MESSAGE(5, ("Testing shared external datatype\n"));
3715 
3716     fcpl = H5Pcreate(H5P_FILE_CREATE);
3717     CHECK_I(fcpl, "H5Pcreate");
3718     ret = H5Pset_shared_mesg_nindexes(fcpl, TEST_NUM_INDEXES);
3719     CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
3720     for(x=0; x<TEST_NUM_INDEXES; ++x) {
3721         ret = H5Pset_shared_mesg_index(fcpl, x, test_type_flags[x], test_minsizes[x]);
3722         CHECK_I(ret, "H5Pset_shared_mesg_index");
3723     }
3724     ret = H5Pset_shared_mesg_phase_change(fcpl, TEST_L2B, TEST_B2L);
3725     CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
3726 
3727     space = H5Screate_simple(2, dims, NULL);
3728     CHECK_I(space, "H5Screate_simple");
3729 
3730     s1_tid = H5Tcreate(H5T_COMPOUND, sizeof(s1_t));
3731     CHECK_I(s1_tid, "H5Tcreate");
3732     ret = H5Tinsert(s1_tid, "a", HOFFSET(s1_t,a), H5T_NATIVE_INT);
3733     CHECK_I(ret, "H5Tinsert");
3734     ret = H5Tinsert (s1_tid, "b", HOFFSET(s1_t,b), H5T_NATIVE_INT);
3735     CHECK_I(ret, "H5Tinsert");
3736 
3737     /* Set up dataset in first file */
3738     file1 = H5Fcreate(FILENAME_SRC, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT);
3739     CHECK_I(file1, "H5Fcreate");
3740 
3741     /* Check on datatype storage status. It should be zero now. */
3742     ret = H5F_get_sohm_mesg_count_test(file1, H5O_DTYPE_ID, &dmsg_count);
3743     CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
3744     VERIFY(dmsg_count, 0, "H5F_get_sohm_mesg_count_test");
3745 
3746     dataset1 = H5Dcreate2(file1, "dataset_1", s1_tid, space, H5P_DEFAULT, H5P_DEFAULT,
3747         H5P_DEFAULT);
3748     CHECK_I(dataset1, "H5Dcreate2");
3749 
3750     /* Check on datatype storage status.  It should be 1 now. */
3751     ret = H5F_get_sohm_mesg_count_test(file1, H5O_DTYPE_ID, &dmsg_count);
3752     CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
3753     VERIFY(dmsg_count, 1, "H5F_get_sohm_mesg_count_test");
3754 
3755     dset1_tid = H5Dget_type(dataset1);
3756     CHECK_I(dset1_tid, "H5Dget_type");
3757 
3758     /* Allocate space and initialize data */
3759     orig = (s1_t*)HDmalloc(NX * NY * sizeof(s1_t));
3760     if (orig == NULL)
3761         CHECK_I(-1, "HDmalloc");
3762     for(i=0; i<NX*NY; i++) {
3763         s_ptr = (s1_t*)orig + i;
3764         s_ptr->a = (int)(i * 3 + 1);
3765         s_ptr->b = (int)(i * 3 + 2);
3766     }
3767 
3768     ret = H5Dwrite(dataset1, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig);
3769     CHECK_I(ret, "H5Dwrite");
3770     ret = H5Dclose(dataset1);
3771     CHECK_I(ret, "H5Dclose");
3772 
3773     /* Create dataset in second file using datatype from dataset in the first file */
3774     file2 = H5Fcreate(FILENAME_DST, H5F_ACC_TRUNC, fcpl, H5P_DEFAULT);
3775     CHECK_I(file2, "H5Fcreate");
3776 
3777     /* Check on datatype storage status. It should be zero now. */
3778     ret = H5F_get_sohm_mesg_count_test(file2, H5O_DTYPE_ID, &dmsg_count);
3779     CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
3780     VERIFY(dmsg_count, 0, "H5F_get_sohm_mesg_count_test");
3781 
3782     dataset2 = H5Dcreate2(file2, "dataset_2", dset1_tid, space, H5P_DEFAULT, H5P_DEFAULT,
3783         H5P_DEFAULT);
3784     CHECK_I(dataset2, "H5Dcreate2");
3785 
3786     /* Check on datatype storage status.  It should be 1 now. */
3787     ret = H5F_get_sohm_mesg_count_test(file2, H5O_DTYPE_ID, &dmsg_count);
3788     CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
3789     VERIFY(dmsg_count, 1, "H5F_get_sohm_mesg_count_test");
3790 
3791     ret = H5Dwrite(dataset2, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig);
3792     CHECK_I(ret, "H5Dwrite");
3793 
3794     /* Close references to the first file */
3795     ret = H5Dclose(dataset2);
3796     CHECK_I(ret, "H5Dclose");
3797     ret = H5Tclose(dset1_tid);
3798     CHECK_I(ret, "H5Tclose");
3799     ret = H5Fclose(file1);
3800     CHECK_I(ret, "H5Fclose");
3801 
3802     /* Verify that datatype details are still accessible by second file */
3803     dataset2 = H5Dopen2(file2, "dataset_2", H5P_DEFAULT);
3804     CHECK_I(dataset2, "H5Dopen2");
3805 
3806     dset2_tid = H5Dget_type(dataset2);
3807     CHECK_I(dset2_tid, "H5Dget_type");
3808 
3809     dtype_class = H5Tget_class(dset2_tid);
3810     VERIFY(dtype_class, H5T_COMPOUND, "H5Tget_class");
3811 
3812     /* Cleanup */
3813     ret = H5Tclose(dset2_tid);
3814     CHECK_I(ret, "H5Tclose");
3815     ret = H5Dclose(dataset2);
3816     CHECK_I(ret, "H5Dclose");
3817     ret = H5Sclose(space);
3818     CHECK_I(ret, "H5Sclose");
3819     ret = H5Tclose(s1_tid);
3820     CHECK_I(ret, "H5Tclose");
3821     ret = H5Pclose(fcpl);
3822     CHECK_I(ret, "H5Pclose");
3823     ret = H5Fclose(file2);
3824     CHECK_I(ret, "H5Fclose");
3825     HDfree(orig);
3826 } /* test_sohm_external_dtype */
3827 
3828 
3829 /****************************************************************
3830 **
3831 **  test_sohm(): Main Shared Object Header Message testing routine.
3832 **
3833 ****************************************************************/
3834 void
test_sohm(void)3835 test_sohm(void)
3836 {
3837     MESSAGE(5, ("Testing Shared Object Header Messages\n"));
3838 
3839     test_sohm_fcpl();           /* Test SOHMs and file creation plists */
3840     test_sohm_fcpl_errors();    /* Bogus H5P* calls for SOHMs */
3841     test_sohm_size1();          /* Tests the sizes of files with one SOHM */
3842 #if 0 /* TODO: REVEALS BUG TO BE FIXED - SEE JIRA HDFFV-10645 */
3843     test_sohm_size_consistency_open_create();
3844 #endif /* Jira HDFFV-10645 */
3845     test_sohm_attrs();          /* Tests shared messages in attributes */
3846     test_sohm_size2(0);         /* Tests the sizes of files with multiple SOHMs */
3847     test_sohm_size2(1);         /* Tests the sizes of files with multiple
3848                                  * SOHMs, closing and reopening file after
3849                                  * each write. */
3850     test_sohm_delete();         /* Test deleting shared messages */
3851     test_sohm_delete_revert();  /* Test that a file with SOHMs becomes an
3852                                  * empty file again when they are deleted. */
3853     test_sohm_extlink();        /* Test SOHMs when external links are used */
3854 
3855     test_sohm_extend_dset();    /* Test extending shared datasets */
3856     test_sohm_external_dtype(); /* Test using datatype in another file */
3857 } /* test_sohm */
3858 
3859 
3860 /*-------------------------------------------------------------------------
3861  * Function:    cleanup_sohm
3862  *
3863  * Purpose:     Cleanup temporary test files
3864  *
3865  * Return:      none
3866  *
3867  * Programmer:  James Laird
3868  *              October 9, 2006
3869  *
3870  * Modifications:
3871  *
3872  *-------------------------------------------------------------------------
3873  */
3874 void
cleanup_sohm(void)3875 cleanup_sohm(void)
3876 {
3877     HDremove(FILENAME);
3878     HDremove(FILENAME_SRC);
3879     HDremove(FILENAME_DST);
3880 } /* cleanup_sohm */
3881 
3882