1 /* This is part of the netCDF package.
2 Copyright 2018 University Corporation for Atmospheric Research/Unidata
3 See COPYRIGHT file for conditions of use.
4
5 Test HDF5 file code. These are not intended to be exhaustive tests,
6 but they use HDF5 the same way that netCDF-4 does, so if these
7 tests don't work, than netCDF-4 won't work either.
8
9 $Id: tst_h_dimscales.c,v 1.15 2010/06/01 15:34:51 ed Exp $
10 */
11 #include "h5_err_macros.h"
12 #include <hdf5.h>
13 #include <H5DSpublic.h>
14
15 #define FILE_NAME "tst_h_dimscales.h5"
16 #define STR_LEN 255
17 #define MAX_DIMS 255
18
alien_visitor(hid_t did,unsigned dim,hid_t dsid,void * visitor_data)19 herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid,
20 void *visitor_data)
21 {
22 char name1[STR_LEN], name2[STR_LEN];
23 H5G_stat_t statbuf;
24
25 (*(hid_t *)visitor_data) = dsid;
26 if (H5Iget_name(did, name1, STR_LEN) < 0) ERR;
27 if (H5Iget_name(dsid, name2, STR_LEN) < 0) ERR;
28 /* printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", */
29 /* did, dim, dsid, name1); */
30 /* printf("name of dsid: %s\n", name2); */
31
32 if (H5Gget_objinfo(did, ".", 1, &statbuf) < 0) ERR;
33 /* printf("statbuf.fileno = %d statbuf.objno = %d\n",
34 statbuf.fileno, statbuf.objno);*/
35
36 return 0;
37 }
38
39 int
rec_scan_group(hid_t grpid)40 rec_scan_group(hid_t grpid)
41 {
42 hid_t spaceid, datasetid = 0, child_grpid;
43 hsize_t num_obj, i;
44 int obj_class;
45 char obj_name[STR_LEN + 1];
46 htri_t is_scale;
47 int num_scales;
48 hsize_t dims[MAX_DIMS], max_dims[MAX_DIMS];
49 int ndims, d;
50
51 /* Loop through datasets to find variables. */
52 if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
53 for (i=0; i<num_obj; i++)
54 {
55 /* Get the type (i.e. group, dataset, etc.), and the name of
56 * the object. */
57 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
58 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
59 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n",
60 obj_class, obj_name);*/
61
62 /* Deal with groups and datasets, ignore the rest. */
63 switch(obj_class)
64 {
65 case H5G_GROUP:
66 if ((child_grpid = H5Gopen(grpid, obj_name)) < 0) ERR;
67 if (rec_scan_group(child_grpid)) ERR;
68 break;
69 case H5G_DATASET:
70 /* Open the dataset. */
71 if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
72 /*printf("\nobj_name %s\n", obj_name);*/
73
74 /* Get the dimensions of this dataset. */
75 if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
76 if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
77 if (ndims > MAX_DIMS) ERR;
78 if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;
79
80 /* Is this a dimscale? */
81 if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
82 if (is_scale)
83 {
84 /*printf("dimension scale! Hoorah for the Pirate King!\n");*/
85 }
86 else
87 {
88 hid_t visitor_data = 0;
89
90 /* Here's how to get the number of scales attached
91 * to the dataset's dimension 0. */
92 if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
93 if (num_scales != 1) ERR;
94
95 /* Go through all dimscales for this var and learn about them. */
96 for (d = 0; d < ndims; d++)
97 if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
98 &visitor_data) < 0) ERR;
99 }
100 if (H5Dclose(datasetid) < 0) ERR;
101 break;
102 case H5G_TYPE:
103 printf("found a type!\n");
104 break;
105 case H5G_LINK:
106 printf("found a link! Yikes!\n");
107 break;
108 default:
109 printf("Unknown object class %d!", obj_class);
110 }
111 }
112
113 return 0;
114 }
115
116 int
main()117 main()
118 {
119 printf("\n*** Checking HDF5 dimension scales.\n");
120 #define GRP_NAME "simple_scales"
121 #define DIMSCALE_NAME "dimscale"
122 #define NAME_ATTRIBUTE "Billy-Bob"
123 #define VAR1_NAME "var1"
124 #define VAR2_NAME "var2"
125 #define VAR3_NAME "var3"
126 #define DIM1_LEN 3
127 #define DIM2_LEN 2
128 #define FIFTIES_SONG "Mamma said they'll be days like this. They'll be days like this, my mamma said."
129
130 printf("*** Creating simple dimension scales file...");
131 {
132 hid_t fileid, grpid, dimscaleid;
133 hid_t dimscale_spaceid, var1_spaceid, var3_spaceid;
134 hid_t var1_datasetid, var2_datasetid, var3_datasetid;
135 hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
136 hsize_t dimscale_dims[1] = {DIM1_LEN};
137
138 /* Open file and create group. */
139 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
140 H5P_DEFAULT)) < 0) ERR;
141 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
142
143 /* Create our dimension scale. Use the built-in NAME attribute
144 * on the dimscale. */
145 if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims,
146 dimscale_dims)) < 0) ERR;
147 if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
148 dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
149 if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
150
151 /* Create a 1D variable which uses the dimscale. Attach a label
152 * to this scale. */
153 if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
154 if ((var1_datasetid = H5Dcreate(grpid, VAR1_NAME, H5T_NATIVE_INT,
155 var1_spaceid, H5P_DEFAULT)) < 0) ERR;
156 if (H5DSattach_scale(var1_datasetid, dimscaleid, 0) < 0) ERR;
157 if (H5DSset_label(var1_datasetid, 0, FIFTIES_SONG) < 0) ERR;
158
159 /* Create a 1D variabls that doesn't use the dimension scale. */
160 if ((var2_datasetid = H5Dcreate(grpid, VAR2_NAME, H5T_NATIVE_INT,
161 var1_spaceid, H5P_DEFAULT)) < 0) ERR;
162
163 /* Create a 2D dataset which uses the scale for one of its
164 * dimensions. */
165 if ((var3_spaceid = H5Screate_simple(2, dims, dims)) < 0) ERR;
166 if ((var3_datasetid = H5Dcreate(grpid, VAR3_NAME, H5T_NATIVE_INT,
167 var3_spaceid, H5P_DEFAULT)) < 0) ERR;
168 if (H5DSattach_scale(var3_datasetid, dimscaleid, 0) < 0) ERR;
169
170 /* Close up the shop. */
171 if (H5Dclose(dimscaleid) < 0 ||
172 H5Dclose(var1_datasetid) < 0 ||
173 H5Dclose(var2_datasetid) < 0 ||
174 H5Dclose(var3_datasetid) < 0 ||
175 H5Sclose(var1_spaceid) < 0 ||
176 H5Sclose(var3_spaceid) < 0 ||
177 H5Sclose(dimscale_spaceid) < 0 ||
178 H5Gclose(grpid) < 0 ||
179 H5Fclose(fileid) < 0) ERR;
180
181 /* HELP! If you are reading this in the future, and time
182 * machines have been invented, please come back to July 10,
183 * 2005, the Java Java coffee shop in Lafayette, 8:00 am MST +-
184 * 20 minutes. Bring back some advanced weapons systems to
185 * destroy the sound system here, which is playing 50's rock and
186 * roll. Do-op, do-op, la-ma la-ma, ding dong. Save me!!! (Mind
187 * you, James Brown is a different story!) */
188 }
189 SUMMARIZE_ERR;
190 printf("*** Checking that simple dimscale file can be read...");
191 {
192 hid_t fileid, grpid, datasetid = 0;
193 hsize_t num_obj, i;
194 int obj_class;
195 char obj_name[STR_LEN + 1];
196 htri_t is_scale;
197 int num_scales;
198
199 /* Reopen the file and group. */
200 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
201 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
202
203 /* Loop through datasets to find variables. */
204 if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
205 for (i=0; i<num_obj; i++)
206 {
207 /* Get the type (i.e. group, dataset, etc.), and the name of the
208 * object. Confusingly, this is a different type than the type
209 * of a variable. This type might be better called "class" or
210 * "type of type" */
211 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
212 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
213 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
214
215 /* Deal with groups and datasets. */
216 switch(obj_class)
217 {
218 case H5G_GROUP:
219 break;
220 case H5G_DATASET:
221
222 /*Close the last datasetid, if one is open. */
223 if (datasetid > 0)
224 {
225 H5Dclose(datasetid);
226 }
227
228 if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
229 if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
230 if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
231 if (is_scale)
232 {
233 char nom_de_quincey[STR_LEN+1];
234
235 /* A dimscale comes with a NAME attribute, in
236 * addition to its real name. */
237 if (H5DSget_scale_name(datasetid, nom_de_quincey,
238 STR_LEN) < 0) ERR;
239 if (strcmp(nom_de_quincey, NAME_ATTRIBUTE)) ERR;
240
241 /*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/
242
243 }
244 else
245 {
246 char label[STR_LEN+1];
247
248 /* Here's how to get the number of scales attached
249 * to the dataset. I would think that this would
250 * return 0 scales for a dataset that doesn't have
251 * scales, but instead it errors. So take an error
252 * to be the same as no dimension scales. */
253 num_scales = H5DSget_num_scales(datasetid, 0);
254 if (strcmp(obj_name, VAR1_NAME) == 0 && num_scales != 1) ERR;
255 if (strcmp(obj_name, VAR2_NAME) == 0 && num_scales > 0) ERR;
256 if (strcmp(obj_name, VAR3_NAME) == 0 && num_scales != 1) ERR;
257
258 /* There's also a label for dimension 0 of var1. */
259 if (strcmp(obj_name, VAR1_NAME) == 0)
260 {
261 if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
262 if (strcmp(label, FIFTIES_SONG)) ERR;
263 }
264 }
265 break;
266 case H5G_TYPE:
267 break;
268 case H5G_LINK:
269 break;
270 default:
271 printf("Unknown object class %d!", obj_class);
272 }
273 }
274
275 /* Close up the shop. */
276 if (H5Dclose(datasetid) < 0 ||
277 H5Gclose(grpid) < 0 ||
278 H5Fclose(fileid) < 0) ERR;
279 }
280
281 SUMMARIZE_ERR;
282 printf("*** Creating simple dimension scales file with lots of datasets...");
283
284 #define NUM_DATASETS 500
285 {
286 hid_t fileid, grpid, dimscaleid;
287 hid_t dimscale_spaceid, var1_spaceid;
288 hid_t var1_datasetid[NUM_DATASETS];
289 hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
290 hsize_t dimscale_dims[1] = {DIM1_LEN};
291 char var_name[STR_LEN + 1];
292 int v;
293
294 /* Open file and create group. */
295 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
296 H5P_DEFAULT)) < 0) ERR;
297 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
298
299 /* Create our dimension scale. Use the built-in NAME attribute
300 * on the dimscale. */
301 if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims,
302 dimscale_dims)) < 0) ERR;
303 if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
304 dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
305 if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
306
307 /* Create many 1D datasets which use the dimscale. */
308 if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
309 for (v = 0; v < NUM_DATASETS; v++)
310 {
311 sprintf(var_name, "var_%d", v);
312 if ((var1_datasetid[v] = H5Dcreate(grpid, var_name, H5T_NATIVE_INT,
313 var1_spaceid, H5P_DEFAULT)) < 0) ERR;
314 if (H5DSattach_scale(var1_datasetid[v], dimscaleid, 0) < 0) ERR;
315 }
316
317 /* Close up the shop. */
318 for (v = 0; v < NUM_DATASETS; v++)
319 if (H5Dclose(var1_datasetid[v]) < 0) ERR;
320 if (H5Dclose(dimscaleid) < 0 ||
321 H5Sclose(var1_spaceid) < 0 ||
322 H5Sclose(dimscale_spaceid) < 0 ||
323 H5Gclose(grpid) < 0 ||
324 H5Fclose(fileid) < 0) ERR;
325 }
326
327 SUMMARIZE_ERR;
328 printf("*** Creating a file with an unlimited dimension scale...");
329
330 {
331 hid_t fileid, grpid, spaceid, datasetid, dimscaleid, cparmsid;
332 hsize_t dims[1] = {1}, maxdims[1] = {H5S_UNLIMITED};
333
334 /* Create file and group. */
335 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
336 H5P_DEFAULT)) < 0) ERR;
337 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
338
339 if ((spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;
340
341 /* Modify dataset creation properties, i.e. enable chunking */
342 if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
343 if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
344
345 /* Create our dimension scale, as an unlimited dataset. */
346 if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
347 spaceid, cparmsid)) < 0) ERR;
348 if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
349
350 /* Create a variable which uses it. */
351 if ((datasetid = H5Dcreate(grpid, VAR1_NAME, H5T_NATIVE_INT,
352 spaceid, cparmsid)) < 0) ERR;
353 if (H5DSattach_scale(datasetid, dimscaleid, 0) < 0) ERR;
354 if (H5DSset_label(datasetid, 0, "dimension label") < 0) ERR;
355
356 /* Close up the shop. */
357 if (H5Dclose(dimscaleid) < 0 ||
358 H5Dclose(datasetid) < 0 ||
359 H5Sclose(spaceid) < 0 ||
360 H5Gclose(grpid) < 0 ||
361 H5Fclose(fileid) < 0) ERR;
362 }
363
364 SUMMARIZE_ERR;
365 printf("*** Checking that unlimited dimscale file can be read...");
366
367 {
368 hid_t fileid, grpid, spaceid = 0, datasetid = 0;
369 hsize_t volatile num_obj, i;
370 int obj_class;
371 char obj_name[STR_LEN + 1];
372 htri_t is_scale;
373 int num_scales;
374 hsize_t dims[1], maxdims[1];
375
376 /* Reopen the file and group. */
377 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
378 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
379
380 /* Loop through datasets to find variables. */
381 if (H5Gget_num_objs(grpid, (hsize_t *)&num_obj) < 0) ERR;
382 for (i=0; i<num_obj; i++)
383 {
384 /* Get the type (i.e. group, dataset, etc.), and the name of
385 * the object. */
386 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
387 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
388 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
389
390 /* Deal with groups and datasets. */
391 switch(obj_class)
392 {
393 case H5G_GROUP:
394 break;
395 case H5G_DATASET:
396
397 /*Close the last datasetid, if one is open. */
398 if (datasetid > 0)
399 {
400 H5Dclose(datasetid);
401 datasetid = 0;
402 }
403
404 /* Open the dataset. */
405 if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
406
407 /* This should be an unlimited dataset. */
408 if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
409 if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
410 if (maxdims[0] != H5S_UNLIMITED) ERR;
411
412 /* Is this a dimscale? */
413 if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
414 if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
415 if (is_scale)
416 {
417 char nom_de_quincey[STR_LEN+1];
418
419 /* A dimscale comes with a NAME attribute, in
420 * addition to its real name. */
421 if (H5DSget_scale_name(datasetid, nom_de_quincey, STR_LEN) < 0) ERR;
422 /*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/
423
424 }
425 else
426 {
427 char label[STR_LEN+1];
428 hid_t visitor_data = 0;
429
430 /* Here's how to get the number of scales attached
431 * to the dataset's dimension 0. */
432 if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
433 if (num_scales != 1) ERR;
434
435 /* Go through all dimscales for this var and learn about them. */
436 if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor,
437 &visitor_data) < 0) ERR;
438
439 /* There's also a label for dimension 0. */
440 if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
441
442 /*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/
443 }
444 break;
445 case H5G_TYPE:
446 break;
447 case H5G_LINK:
448 break;
449 default:
450 printf("Unknown object class %d!", obj_class);
451 }
452 }
453
454 /* Close up the shop. */
455 if (H5Dclose(datasetid) < 0 ||
456 H5Sclose(spaceid) < 0 ||
457 H5Gclose(grpid) < 0 ||
458 H5Fclose(fileid) < 0) ERR;
459 }
460
461 SUMMARIZE_ERR;
462 printf("*** Creating some 3D datasets using shared dimscales...");
463
464 {
465 #define NDIMS 3
466 #define TIME_DIM 0
467 #define LAT_DIM 1
468 #define LON_DIM 2
469 #define LAT_LEN 2
470 #define LON_LEN 3
471 #define LAT_NAME "Lat"
472 #define LON_NAME "Lon"
473 #define TIME_NAME "Time"
474 #define PRES_NAME "Pressure"
475 #define TEMP_NAME "Temperature"
476
477 hid_t fileid, grpid, lat_spaceid, lon_spaceid, time_spaceid, spaceid;
478 hid_t lat_scaleid, lon_scaleid, time_scaleid;
479 hid_t pres_dsid, temp_dsid, cparmsid;
480 hsize_t dims[NDIMS], max_dims[NDIMS];
481
482 /* Create file and group. */
483 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
484 H5P_DEFAULT)) < 0) ERR;
485 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
486
487 /* Create 3 1D spaces for the 3 dimension scale datasets. Time
488 * starts out as size 0. It's an unlimited dimension scale. */
489 dims[0] = 0;
490 max_dims[0] = H5S_UNLIMITED;
491 if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
492 dims[0] = LAT_LEN;
493 max_dims[0] = LAT_LEN;
494 if ((lat_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
495 dims[0] = LON_LEN;
496 max_dims[0] = LON_LEN;
497 if ((lon_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
498
499 /* Enable chunking for unlimited time scale. */
500 if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
501 dims[TIME_DIM] = 1;
502 if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
503
504 /* Create our dimension scales. */
505 if ((time_scaleid = H5Dcreate(grpid, TIME_NAME, H5T_NATIVE_INT,
506 time_spaceid, cparmsid)) < 0) ERR;
507 if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
508 if ((lat_scaleid = H5Dcreate(grpid, LAT_NAME, H5T_NATIVE_FLOAT,
509 lat_spaceid, H5P_DEFAULT)) < 0) ERR;
510 if (H5DSset_scale(lat_scaleid, LAT_NAME) < 0) ERR;
511 if ((lon_scaleid = H5Dcreate(grpid, LON_NAME, H5T_NATIVE_FLOAT,
512 lon_spaceid, H5P_DEFAULT)) < 0) ERR;
513 if (H5DSset_scale(lon_scaleid, LON_NAME) < 0) ERR;
514
515 /* Create a space corresponding to these three dimensions. */
516 dims[TIME_DIM] = 0;
517 dims[LAT_DIM] = LAT_LEN;
518 dims[LON_DIM] = LON_LEN;
519 max_dims[TIME_DIM] = H5S_UNLIMITED;
520 max_dims[LAT_DIM] = LAT_LEN;
521 max_dims[LON_DIM] = LON_LEN;
522 if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;
523
524 /* Create two variables which use them, and attach the dimension scales. */
525 dims[TIME_DIM] = 1;
526 if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
527 if ((pres_dsid = H5Dcreate(grpid, PRES_NAME, H5T_NATIVE_FLOAT,
528 spaceid, cparmsid)) < 0) ERR;
529 if (H5DSattach_scale(pres_dsid, time_scaleid, 0) < 0) ERR;
530 if (H5DSattach_scale(pres_dsid, lat_scaleid, 1) < 0) ERR;
531 if (H5DSattach_scale(pres_dsid, lon_scaleid, 2) < 0) ERR;
532 if (H5DSset_label(pres_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
533 if (H5DSset_label(pres_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
534 if (H5DSset_label(pres_dsid, LON_DIM, LON_NAME) < 0) ERR;
535 if ((temp_dsid = H5Dcreate(grpid, TEMP_NAME, H5T_NATIVE_FLOAT,
536 spaceid, cparmsid)) < 0) ERR;
537 if (H5DSattach_scale(temp_dsid, time_scaleid, 0) < 0) ERR;
538 if (H5DSattach_scale(temp_dsid, lat_scaleid, 1) < 0) ERR;
539 if (H5DSattach_scale(temp_dsid, lon_scaleid, 2) < 0) ERR;
540 if (H5DSset_label(temp_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
541 if (H5DSset_label(temp_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
542 if (H5DSset_label(temp_dsid, LON_DIM, LON_NAME) < 0) ERR;
543
544 /* Close up the shop. */
545 if (H5Dclose(pres_dsid) < 0 ||
546 H5Dclose(temp_dsid) < 0 ||
547 H5Dclose(lat_scaleid) < 0 ||
548 H5Dclose(lon_scaleid) < 0 ||
549 H5Dclose(time_scaleid) < 0 ||
550 H5Sclose(spaceid) < 0 ||
551 H5Gclose(grpid) < 0 ||
552 H5Fclose(fileid) < 0) ERR;
553 }
554
555 SUMMARIZE_ERR;
556 printf("*** Checking 3D datasets created with shared dimscales...");
557
558 {
559 hid_t fileid, grpid, spaceid = 0, datasetid = 0;
560 hsize_t num_obj, i;
561 int obj_class;
562 char obj_name[STR_LEN + 1];
563 htri_t is_scale;
564 int num_scales;
565 hsize_t dims[NDIMS], max_dims[NDIMS];
566 int d;
567
568 /* Reopen the file and group. */
569 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
570 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
571
572 /* Loop through datasets to find variables. */
573 if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
574 for (i=0; i<num_obj; i++)
575 {
576 /* Get the type (i.e. group, dataset, etc.), and the name of
577 * the object. */
578 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
579 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
580 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
581
582 /* Deal with groups and datasets. */
583 switch(obj_class)
584 {
585 case H5G_GROUP:
586 break;
587 case H5G_DATASET:
588 /* Open the dataset. */
589 if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
590 /*printf("\nobj_name %s\n", obj_name);*/
591
592 /* Get the dimensions of this dataset. */
593 if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
594 if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;
595
596 /* Is this a dimscale? */
597 if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
598 if (is_scale)
599 {
600 char nom_de_quincey[STR_LEN+1];
601
602 /* A dimscale comes with a NAME attribute, in
603 * addition to its real name. */
604 if (H5DSget_scale_name(datasetid, nom_de_quincey,
605 STR_LEN) < 0) ERR;
606 /*printf("found scale %s, NAME %s id 0x%x\n", obj_name,
607 nom_de_quincey, datasetid);*/
608
609 /* Check size depending on name. */
610 if ((!strcmp(obj_name, LAT_NAME) && dims[TIME_DIM] != LAT_LEN) ||
611 (!strcmp(obj_name, LON_NAME) && dims[TIME_DIM] != LON_LEN) ||
612 (!strcmp(obj_name, TIME_NAME) &&
613 max_dims[TIME_DIM] != H5S_UNLIMITED)) ERR;
614
615 }
616 else
617 {
618 char label[STR_LEN+1];
619 hid_t visitor_data = 0;
620
621 /* SHould have these dimensions... */
622 if (dims[TIME_DIM] != 0 || dims[LAT_DIM] != LAT_LEN ||
623 dims[LON_DIM] != LON_LEN) ERR;
624 if (max_dims[TIME_DIM] != H5S_UNLIMITED) ERR;
625
626 /* Here's how to get the number of scales attached
627 * to the dataset's dimension 0. */
628 if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
629 if (num_scales != 1) ERR;
630
631 /* Go through all dimscales for this var and learn
632 * about them. What I want is the dataset id of each
633 * dimscale. Then... */
634 for (d = 0; d < NDIMS; d++)
635 if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
636 &visitor_data) < 0) ERR;
637 /*printf("visitor_data: 0x%x\n", visitor_data);*/
638
639 /* There's also a label for each dimension. */
640 if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
641 if (strcmp(label, TIME_NAME)) ERR;
642 if (H5DSget_label(datasetid, 1, label, STR_LEN) < 0) ERR;
643 if (strcmp(label, LAT_NAME)) ERR;
644 if (H5DSget_label(datasetid, 2, label, STR_LEN) < 0) ERR;
645 if (strcmp(label, LON_NAME)) ERR;
646 }
647 if (H5Dclose(datasetid) < 0) ERR;
648 break;
649 case H5G_TYPE:
650 break;
651 case H5G_LINK:
652 break;
653 default:
654 printf("Unknown object class %d!", obj_class);
655 }
656 }
657
658 /* Close up the shop. */
659 if (H5Sclose(spaceid) < 0 ||
660 H5Gclose(grpid) < 0 ||
661 H5Fclose(fileid) < 0) ERR;
662 }
663
664 SUMMARIZE_ERR;
665 printf("*** Creating 3D datasets using shared dimscales in groups...");
666
667 {
668 #define FATHER "Adam"
669 #define GOOD_CHILD "Able"
670 #define BAD_CHILD "Cain"
671 #define DISTANCE_LEN 3
672 #define SMELLINESS_NAME "Smelliness"
673 #define DISTANCE_NAME "Distance"
674 #define TIME_NAME "Time"
675 #define TIME_DIM 0
676 #define SMELLINESS_DIM 1
677 #define DISTANCE_DIM 2
678 #define GOAT_NAME "Billy_goat_gruff"
679 #define CAMEL_NAME "Grumpy_the_camel"
680
681 hid_t fileid, smelliness_spaceid, distance_spaceid, time_spaceid, spaceid;
682 hid_t adam_grpid, able_grpid, cain_grpid;
683 hid_t time_scaleid, smelliness_scaleid, distance_scaleid;
684 hid_t goat_dsid, camel_dsid, cparmsid;
685 hsize_t dims[NDIMS], max_dims[NDIMS];
686
687 /* Create file and group. */
688 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
689 H5P_DEFAULT)) < 0) ERR;
690 if ((adam_grpid = H5Gcreate(fileid, FATHER, 0)) < 0) ERR;
691 if ((able_grpid = H5Gcreate(adam_grpid, GOOD_CHILD, 0)) < 0) ERR;
692 if ((cain_grpid = H5Gcreate(adam_grpid, BAD_CHILD, 0)) < 0) ERR;
693
694 /* Create 3 1D spaces for the 3 dimension scale datasets. Time
695 * and smelliness starts out as 0. They are unlimited dimension
696 * scales. */
697 dims[0] = 0;
698 max_dims[0] = H5S_UNLIMITED;
699 if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
700 dims[0] = 0;
701 max_dims[0] = H5S_UNLIMITED;
702 if ((smelliness_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
703 dims[0] = DISTANCE_LEN;
704 max_dims[0] = DISTANCE_LEN;
705 if ((distance_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
706
707 /* Enable chunking for unlimited time and smelliness scale. */
708 if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
709 dims[0] = 1;
710 if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
711
712 /* Create our dimension scales. */
713 if ((time_scaleid = H5Dcreate(adam_grpid, TIME_NAME, H5T_NATIVE_INT,
714 time_spaceid, cparmsid)) < 0) ERR;
715 if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
716 if ((smelliness_scaleid = H5Dcreate(adam_grpid, SMELLINESS_NAME, H5T_NATIVE_FLOAT,
717 smelliness_spaceid, cparmsid)) < 0) ERR;
718 if (H5DSset_scale(smelliness_scaleid, SMELLINESS_NAME) < 0) ERR;
719 if ((distance_scaleid = H5Dcreate(adam_grpid, DISTANCE_NAME, H5T_NATIVE_FLOAT,
720 distance_spaceid, H5P_DEFAULT)) < 0) ERR;
721 if (H5DSset_scale(distance_scaleid, DISTANCE_NAME) < 0) ERR;
722
723 /* Create a space corresponding to these three dimensions. */
724 dims[TIME_DIM] = 0;
725 dims[SMELLINESS_DIM] = 0;
726 dims[DISTANCE_DIM] = DISTANCE_LEN;
727 max_dims[TIME_DIM] = H5S_UNLIMITED;
728 max_dims[SMELLINESS_DIM] = H5S_UNLIMITED;
729 max_dims[DISTANCE_DIM] = DISTANCE_LEN;
730 if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;
731
732 /* Set up chunking for our 3D vars. */
733 dims[TIME_DIM] = 1;
734 dims[SMELLINESS_DIM] = 1;
735 if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
736
737 /* Create two variables which use them, and attach the dimension scales. */
738 if ((goat_dsid = H5Dcreate(able_grpid, GOAT_NAME, H5T_NATIVE_FLOAT,
739 spaceid, cparmsid)) < 0) ERR;
740 if (H5DSattach_scale(goat_dsid, time_scaleid, 0) < 0) ERR;
741 if (H5DSattach_scale(goat_dsid, smelliness_scaleid, 1) < 0) ERR;
742 if (H5DSattach_scale(goat_dsid, distance_scaleid, 2) < 0) ERR;
743 if ((camel_dsid = H5Dcreate(cain_grpid, CAMEL_NAME, H5T_NATIVE_FLOAT,
744 spaceid, cparmsid)) < 0) ERR;
745 if (H5DSattach_scale(camel_dsid, time_scaleid, 0) < 0) ERR;
746 if (H5DSattach_scale(camel_dsid, smelliness_scaleid, 1) < 0) ERR;
747 if (H5DSattach_scale(camel_dsid, distance_scaleid, 2) < 0) ERR;
748
749 /* Close up the shop. */
750 if (H5Dclose(goat_dsid) < 0 ||
751 H5Dclose(camel_dsid) < 0 ||
752 H5Dclose(smelliness_scaleid) < 0 ||
753 H5Dclose(distance_scaleid) < 0 ||
754 H5Dclose(time_scaleid) < 0 ||
755 H5Sclose(spaceid) < 0 ||
756 H5Gclose(cain_grpid) < 0 ||
757 H5Gclose(able_grpid) < 0 ||
758 H5Gclose(adam_grpid) < 0 ||
759 H5Fclose(fileid) < 0) ERR;
760 }
761
762 SUMMARIZE_ERR;
763 printf("*** Checking 3D datasets in groups created with shared dimscales...");
764
765 {
766 hid_t fileid, grpid;
767
768 /* Reopen the file and group. */
769 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
770 if ((grpid = H5Gopen(fileid, FATHER)) < 0) ERR;
771
772 /* If we can't scan the group, crash into a flaming heap of
773 * smoking, smoldering rubbish. */
774 if (rec_scan_group(grpid)) ERR;
775
776 /* Close up the shop. */
777 if (H5Gclose(grpid) < 0 ||
778 H5Fclose(fileid) < 0) ERR;
779 }
780
781 SUMMARIZE_ERR;
782 FINAL_RESULTS;
783 }
784