1 /*
2                             hsize_t _size = 3;
3 Copyright (c) 1994 - 2010, Lawrence Livermore National Security, LLC.
4 LLNL-CODE-425250.
5 All rights reserved.
6 
7 This file is part of Silo. For details, see silo.llnl.gov.
8 
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13    * Redistributions of source code must retain the above copyright
14      notice, this list of conditions and the disclaimer below.
15    * Redistributions in binary form must reproduce the above copyright
16      notice, this list of conditions and the disclaimer (as noted
17      below) in the documentation and/or other materials provided with
18      the distribution.
19    * Neither the name of the LLNS/LLNL nor the names of its
20      contributors may be used to endorse or promote products derived
21      from this software without specific prior written permission.
22 
23 THIS SOFTWARE  IS PROVIDED BY  THE COPYRIGHT HOLDERS  AND CONTRIBUTORS
24 "AS  IS" AND  ANY EXPRESS  OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
25 LIMITED TO, THE IMPLIED  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 A  PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN  NO  EVENT SHALL  LAWRENCE
27 LIVERMORE  NATIONAL SECURITY, LLC,  THE U.S.  DEPARTMENT OF  ENERGY OR
28 CONTRIBUTORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 EXEMPLARY, OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT NOT  LIMITED TO,
30 PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS  OF USE,  DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 LIABILITY, WHETHER  IN CONTRACT, STRICT LIABILITY,  OR TORT (INCLUDING
33 NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT  OF THE USE  OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 
36 This work was produced at Lawrence Livermore National Laboratory under
37 Contract No.  DE-AC52-07NA27344 with the DOE.
38 
39 Neither the  United States Government nor  Lawrence Livermore National
40 Security, LLC nor any of  their employees, makes any warranty, express
41 or  implied,  or  assumes  any  liability or  responsibility  for  the
42 accuracy, completeness,  or usefulness of  any information, apparatus,
43 product, or  process disclosed, or  represents that its use  would not
44 infringe privately-owned rights.
45 
46 Any reference herein to  any specific commercial products, process, or
47 services by trade name,  trademark, manufacturer or otherwise does not
48 necessarily  constitute or imply  its endorsement,  recommendation, or
49 favoring  by  the  United  States  Government  or  Lawrence  Livermore
50 National Security,  LLC. The views  and opinions of  authors expressed
51 herein do not necessarily state  or reflect those of the United States
52 Government or Lawrence Livermore National Security, LLC, and shall not
53 be used for advertising or product endorsement purposes.
54 */
55 
56 /* Define this symbol BEFORE including hdf5.h to indicate the HDF5 code
57    in this file uses version 1.6 of the HDF5 API. This is harmless for
58    versions of HDF5 before 1.8 and ensures correct compilation with
59    version 1.8 and thereafter. When, and if, the HDF5 code in this file
60    is explicitly upgraded to the 1.8 API, this symbol should be removed. */
61 #define H5_USE_16_API
62 
63 #include <errno.h>
64 #include <assert.h>
65 #if HAVE_STRING_H
66 #include <string.h>
67 #endif
68 #if HAVE_STDLIB_H
69 #include <stdlib.h> /*missing from silo header files*/
70 #endif
71 #include <stdio.h>
72 #include "silo_hdf5_private.h"
73 #include "H5FDsilo.h"
74 #if defined(HAVE_HDF5_H) && defined(HAVE_LIBHDF5) /* [ */
75 
76 /* HZIP node order permuation vector construction.
77    To construct a permutation vector, work backwards
78    from the highest numbered node on the canonical
79    element, finding its cooresponding node number on
80    the source element. Put the resulting number in
81    the highest nibble of the unsigned word for the
82    permutation vector. Then, move to the next highest
83    numbered node on the canonical element, repeating
84    all these steps to arrive at a value for the next
85    highest order nibble in the word. 3D example...
86 
87        3-------2       2-------3
88       /|      /|      /|      /|
89      4-------5 |     6-------7 |
90      | |     | | --> | |     | |
91      | 0-----|-1     | 0-----|-1
92      |/      |/      |/      |/
93      7-------6       4-------5
94 
95      source data     canonical
96      ordering        ordering
97 
98              0x54672310
99 
100    2D example...
101        (Note the zone on the left is also Silo/VisIt
102         node order for a quad)
103 
104        1-------2       2-------3
105        |       |       |       |
106        |       |       |       |
107        |       | -->   |       |
108        0-------3       0-------1
109 
110             0x00002130
111 
112   HZIP Compression integration overview...
113 
114   HZIP is a unique among compression algorithms in that it is
115   capabable of exploiting mesh structure in order to improve
116   performance. However, this means that the compressor needs
117   to maintain information on the mesh connectivity in order to
118   compress any variables defined on the mesh. Other compressors
119   operate either on raw byte streams or, maybe, multidimensional
120   integer and floating point arrays. FPZIP does that for example.
121   But, to use HZIP, Silo needs to maintain a cache of recently
122   used nodelists. Since Silo imposes no order on how objects are
123   written or read, if the writer doen't write in the correct order,
124   things will fail. During read, however, the silo library can
125   ensure tha all information necessary to decompress is available
126   when necessary.
127 
128   The design here attempts to localize as much of the compression
129   know how to an HDF5 'filter.' It is best if the compressor is
130   properly integrated with HDF5 using HDF5's filter architecture.
131   This is substantially easier for generic compressors because
132   there isn't any information other than the data stream required
133   to compress or decompress. That is not true for HZIP compression.
134   The HDF5 filter that implements HZIP compression,
135   db_hdf5_hzip_filter_op, must exploit a lot of information apart
136   from the actual data stream it is compressing or decompressing.
137   This extra information is managed in db_hdf5_hzip_params. In
138   a handful of places in the driver, we've had to add code to
139   manage HZIP compression information so that the compressor will
140   have all the information it needs. These places are the
141   PrepareForXXXCompression|Decompression methods.
142 
143   There are a number of issues...
144   a) HZIP compresses only node-centered data, not zone-centerd.
145   b) HZIP compresses only 2D quad meshes or 3D hex meshes.
146   c) HZIP is designed for unstructured grid. To use it on structured
147      grid, we create a fictitious nodelist at will.
148   d) The silo client must call DBFreeResources (which happens
149      automatically on DBClose) to free up stored nodelists
150      used by HZIP. It is best if the client operate in such a
151      way that reads or writes for all variables of a mesh
152      occur shortly after the mesh itself and that the client
153      does not iterate through a slew of meshes and then the
154      variables for those meshes.
155   e) To use HZIP, you need to give it a buffer to place the
156      compressed result it. But, you can't allocate such a
157      buffer without knowing size. So, we take the approach
158      of having a min. compression ratio and allocating a
159      (possibly too large) buffer for HZIP to compress into.
160      If HZIP cannot compress into this size, it fails and
161      we skip the compression. If it can, HDF5 ultimately
162      writes only the compressed bytes. Same is true for FPZIP.
163   f) To use HDF5 filters, the datasets must be 'chunked.'
164      With chunked datasets, HDF5 essentially makes a copy
165      of the data on write effecting performance and memory
166      usage.
167   g) Silo supports data read masks. If you attempt to read
168      a mesh without reading its zonelist and the zonelist
169      (and mesh) are compressed, then the result will fail
170      (presently in unpredictable ways) because HZIP needs
171      the nodelist in order to decompress.
172   h) In integrating compression, we have to take care that
173      new calls introduced to support compression that ALWAYS
174      happen (whether we are compressing or not) do not
175      negatively affect performance of the 'old' Silo.
176      An example is in PrepareForUcdvarDecompression.
177   f) Silex cannot browse HZIP compressed objects because it
178      does not operate at the correct level of abstraction.
179      It uses DBGetObject calls only.
180 
181 */
182 
183 /* For Lindstrom compression libs */
184 #define DB_HDF5_HZIP_ID (H5Z_FILTER_RESERVED+1)
185 #define DB_HDF5_FPZIP_ID (H5Z_FILTER_RESERVED+2)
186 #ifdef HAVE_HZIP
187 #include <hzip.h>
188 #ifdef HAVE_LIBZ
189 static struct HZMCODECzlib db_hdf5_hzip_zlib_codec_params;
190 #endif
191 static struct HZMCODECbase db_hdf5_hzip_base_codec_params;
192 static const unsigned SILO_HZIP_PERMUTATION[4] = {0,0,((unsigned) (0x00002130)), ((unsigned) (0x65217430))};
193 #endif
194 #ifdef HAVE_FPZIP
195 #include <fpzip.h>
196 #endif
197 
198 /* Defining these to check overhead of PROTECT */
199 #if 0
200 #   define PROTECT      if(1)
201 #   define CLEANUP      else
202 #   define END_PROTECT  /*void*/
203 #   define UNWIND()     ;
204 #endif
205 
206 #define COMPRESSION_ERRMODE_FALLBACK 0
207 #define COMPRESSION_ERRMODE_FAIL     1
208 #define ALLOW_MESH_COMPRESSION 0x00000001
209 
210 #define FALSE           0
211 #define TRUE            1
212 
213 #define LINKGRP         "/.silo/"       /*name of link group            */
214 #define MAX_VARS        16              /*max vars per DB*var object    */
215 #define OPTDUP(S)       ((S)&&*(S)?strdup(S):NULL)
216 #define BASEDUP(S)       ((S)&&*(S)?db_FullName2BaseName(S):NULL)
217 #define ALIGN(ADDR,N)   (((ADDR)+(N)-1)&~((N)-1))
218 
219 /* copies of equiv. symbols in H5LT library */
220 #define db_hdf5_H5LT_FILE_IMAGE_OPEN_RW      0x0001
221 #define db_hdf5_H5LT_FILE_IMAGE_DONT_COPY    0x0002
222 #define db_hdf5_H5LT_FILE_IMAGE_DONT_RELEASE 0x0004
223 
224 /* useful macro for comparing HDF5 versions */
225 #define HDF5_VERSION_GE(Maj,Min,Rel)  \
226         (((H5_VERS_MAJOR==Maj) && (H5_VERS_MINOR==Min) && (H5_VERS_RELEASE>=Rel)) || \
227          ((H5_VERS_MAJOR==Maj) && (H5_VERS_MINOR>Min)) || \
228          (H5_VERS_MAJOR>Maj))
229 
230 /* to encode the version of the hdf5 library in any silo executable */
231 char SILO_built_with_H5_lib_vers_info_g[] = "SILO built with "
232 #if HDF5_VERSION_GE(1,4,2)
233 H5_VERS_INFO;
234 #else
235 "HDF5 library: Version 1.4.1 or earlier";
236 #endif
237 
238 /* some necessary forward declarations */
239 PRIVATE int db_hdf5_fullname(DBfile_hdf5 *dbfile, char *name, char *full);
240 PRIVATE int hdf2silo_type(hid_t type);
241 PRIVATE int db_hdf5_WriteCKZ(DBfile *_dbfile, char const *vname, void const *var,
242               int const *dims, int ndims, int datatype, int nofilters);
243 
244 /* callbacks prototypes for file image ops */
245 #if HDF5_VERSION_GE(1,8,9)
246 PRIVATE void *image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *udata);
247 PRIVATE void *image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op, void *udata);
248 PRIVATE void *image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *udata);
249 PRIVATE herr_t image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *udata);
250 PRIVATE void *udata_copy(void *udata);
251 PRIVATE herr_t udata_free(void *udata);
252 
253 /* Data structure to pass application data to image file callbacks. */
254 typedef struct {
255     void *app_image_ptr;	/* Pointer to application buffer */
256     size_t app_image_size;	/* Size of application buffer */
257     void *fapl_image_ptr;	/* Pointer to FAPL buffer */
258     size_t fapl_image_size;	/* Size of FAPL buffer */
259     int fapl_ref_count;		/* Reference counter for FAPL buffer */
260     void *vfd_image_ptr;	/* Pointer to VFD buffer */
261     size_t vfd_image_size;	/* Size of VFD buffer */
262     int vfd_ref_count;		/* Reference counter for VFD buffer */
263     unsigned flags;		/* Flags indicate how the file image will */
264                                 /* be open */
265     int ref_count;		/* Reference counter on udata struct */
266 } db_hdf5_H5LT_file_image_ud_t;
267 #endif
268 
269 /* Symbolic constants used in calls to db_StringListToStringArray
270    to indicate behavior. A '!' in front means to not perform the
271    associated action. For HDF5 driver, we handle the slash swap
272    on the 'names' member of multi-block objects only and we
273    never skip first semicolon. */
274 static int const        skipFirstSemicolon = 0;
275 
276 /* Use `float' for all memory floating point values? */
277 static int              force_single_g;
278 
279 /* used to control behavior of GetZonelist */
280 static char const      *calledFromGetUcdmesh = 0;
281 
282 /* Struct used when building the CWD name */
283 typedef struct silo_hdf5_comp_t {
284     char                *name;
285     unsigned long       objno[2];
286 } silo_hdf5_comp_t;
287 
288 /* Attributes for various types of objects */
289 typedef struct DBcurve_mt {
290     int                 npts;
291     int                 guihide;
292     int                 coord_sys;
293     char                xvarname[256];
294     char                yvarname[256];
295     char                label[256];
296     char                xlabel[256];
297     char                ylabel[256];
298     char                xunits[256];
299     char                yunits[256];
300     char                reference[256];
301     double              missing_value;
302 } DBcurve_mt;
303 static hid_t DBcurve_mt5 = -1;
304 
305 typedef struct DBcsgmesh_mt {
306     int            block_no;
307     int            group_no;
308     int            cycle;
309     int            nbounds;
310     int            lcoeffs;
311     float          time;
312     double         dtime;
313     int            ndims;
314     int            origin;
315     int            guihide;
316     double         min_extents[3];
317     double         max_extents[3];
318     char           units[3][256];
319     char           labels[3][256];
320     char           name[256];
321     char           typeflags[256];
322     char           bndids[256];
323     char           coeffs[256];
324     char           zonel_name[256];
325     char           bndnames[256];
326     char           mrgtree_name[256];
327     int            tv_connectivity;
328     int            disjoint_mode;
329     char           alt_nodenum_vars[256];
330 } DBcsgmesh_mt;
331 static hid_t DBcsgmesh_mt5;
332 
333 typedef struct DBcsgvar_mt {
334     int            cycle;
335     float          time;
336     double         dtime;
337     int            datatype;
338     int            nels;
339     int            nvals;
340     int            centering;
341     int            use_specmf;
342     int            ascii_labels;
343     int            guihide;
344     char           name[256];
345     char           units[256];
346     char           label[256];
347     char           vals[MAX_VARS][256];
348     char           meshname[256];
349     char           region_pnames[256];
350     int            conserved;
351     int            extensive;
352     double         missing_value;
353 } DBcsgvar_mt;
354 static hid_t DBcsgvar_mt5;
355 
356 typedef struct DBcsgzonelist_mt {
357     int            nregs;
358     int            origin;
359     int            lxform;
360     int            datatype;
361     int            nzones;
362     int            min_index;
363     int            max_index;
364     char           typeflags[256];
365     char           leftids[256];
366     char           rightids[256];
367     char           xform[256];
368     char           zonelist[256];
369     char           regnames[256];
370     char           zonenames[256];
371     char           alt_zonenum_vars[256];
372 } DBcsgzonelist_mt;
373 static hid_t DBcsgzonelist_mt5;
374 
375 typedef struct DBdefvars_mt {
376     int            ndefs;
377     char           names[256];
378     char           types[256];
379     char           defns[256];
380     char           guihides[256];
381 } DBdefvars_mt;
382 static hid_t DBdefvars_mt5;
383 
384 typedef struct DBquadmesh_mt {
385     char                coord[3][256];
386     double              min_extents[3];
387     double              max_extents[3];
388     int                 ndims;
389     int                 coordtype;
390     int                 nspace;
391     int                 nnodes;
392     int                 facetype;
393     int                 major_order;
394     int                 cycle;
395     int                 coord_sys;
396     int                 planar;
397     int                 origin;
398     int                 group_no;
399     int                 dims[3];
400     int                 min_index[3];
401     int                 max_index[3];
402     int                 baseindex[3];
403     float               time;
404     double              dtime;
405     int                 guihide;
406     char                label[3][256];
407     char                units[3][256];
408     char                mrgtree_name[256];
409     char                ghost_node_labels[256];
410     char                ghost_zone_labels[256];
411     char                alt_nodenum_vars[256];
412     char                alt_zonenum_vars[256];
413 } DBquadmesh_mt;
414 static hid_t DBquadmesh_mt5;
415 
416 typedef struct DBquadvar_mt {
417     char                value[MAX_VARS][256];
418     char                mixed_value[MAX_VARS][256];
419     char                meshid[256];
420     int                 ndims;
421     int                 nvals;
422     int                 nels;
423     int                 origin;
424     int                 mixlen;
425     int                 major_order;
426     int                 datatype;
427     int                 cycle;
428     float               time;
429     double              dtime;
430     int                 use_specmf;
431     int                 ascii_labels;
432     int                 dims[3];
433     int                 zones[3];
434     int                 min_index[3];
435     int                 max_index[3];
436     float               align[3];
437     int                 guihide;
438     char                label[256];
439     char                units[256];
440     char                region_pnames[256];
441     int                 conserved;
442     int                 extensive;
443     int                 centering;
444     double              missing_value;
445 } DBquadvar_mt;
446 static hid_t    DBquadvar_mt5;
447 
448 typedef struct DBucdmesh_mt {
449     char                coord[3][256];
450     int                 ndims;
451     int                 nnodes;
452     int                 nzones;
453     int                 facetype;
454     int                 cycle;
455     int                 coord_sys;
456     int                 topo_dim;
457     int                 planar;
458     int                 origin;
459     int                 group_no;
460     float               time;
461     double              dtime;
462     int                 guihide;
463     char                facelist[256];
464     char                zonelist[256];
465     char                gnodeno[256];
466     double              min_extents[3];
467     double              max_extents[3];
468     char                label[3][256];
469     char                units[3][256];
470     char                phzonelist[256];
471     char                mrgtree_name[256];
472     int                 tv_connectivity;
473     int                 disjoint_mode;
474     int                 gnznodtype;
475     char                ghost_node_labels[256];
476     char                alt_nodenum_vars[256];
477 } DBucdmesh_mt;
478 static hid_t    DBucdmesh_mt5;
479 
480 typedef struct DBucdvar_mt {
481     char                value[MAX_VARS][256];
482     char                mixed_value[MAX_VARS][256];
483     char                meshid[256];
484     int                 ndims;
485     int                 nvals;
486     int                 nels;
487     int                 centering;
488     int                 origin;
489     int                 mixlen;
490     int                 datatype;
491     int                 cycle;
492     int                 use_specmf;
493     int                 ascii_labels;
494     float               time;
495     double              dtime;
496     int                 lo_offset;
497     int                 hi_offset;
498     int                 guihide;
499     char                label[256];
500     char                units[256];
501     char                region_pnames[256];
502     int                 conserved;
503     int                 extensive;
504     double              missing_value;
505 } DBucdvar_mt;
506 static hid_t    DBucdvar_mt5;
507 
508 typedef struct DBfacelist_mt {
509     int                 ndims;
510     int                 nfaces;
511     int                 nshapes;
512     int                 ntypes;
513     int                 lnodelist;
514     int                 origin;
515     char                nodelist[256];
516     char                shapecnt[256];
517     char                shapesize[256];
518     char                typelist[256];
519     char                types[256];
520     char                zoneno[256];
521 } DBfacelist_mt;
522 static hid_t    DBfacelist_mt5;
523 
524 typedef struct DBzonelist_mt {
525     int                 ndims;
526     int                 nzones;
527     int                 nshapes;
528     int                 lnodelist;
529     int                 origin;
530     int                 lo_offset;
531     int                 hi_offset;
532     char                nodelist[256];
533     char                shapecnt[256];
534     char                shapesize[256];
535     char                shapetype[256];
536     char                gzoneno[256];
537     int                 gnznodtype;
538     char                ghost_zone_labels[256];
539     char                alt_zonenum_vars[256];
540 } DBzonelist_mt;
541 static hid_t    DBzonelist_mt5;
542 
543 typedef struct DBphzonelist_mt {
544     int                 nfaces;
545     int                 lnodelist;
546     int                 nzones;
547     int                 lfacelist;
548     int                 origin;
549     int                 lo_offset;
550     int                 hi_offset;
551     char                nodecnt[256];
552     char                nodelist[256];
553     char                extface[256];
554     char                facecnt[256];
555     char                facelist[256];
556     char                gzoneno[256];
557     int                 gnznodtype;
558     char                ghost_zone_labels[256];
559     char                alt_zonenum_vars[256];
560 } DBphzonelist_mt;
561 static hid_t    DBphzonelist_mt5;
562 
563 typedef struct DBmaterial_mt {
564     int                 ndims;
565     int                 nmat;
566     int                 mixlen;
567     int                 origin;
568     int                 major_order;
569     int                 datatype;
570     int                 dims[3];
571     int                 allowmat0;
572     int                 guihide;
573     char                meshid[256];
574     char                matlist[256];
575     char                matnos[256];
576     char                mix_vf[256];
577     char                mix_next[256];
578     char                mix_mat[256];
579     char                mix_zone[256];
580     char                matnames[256];
581     char                matcolors[256];
582 } DBmaterial_mt;
583 static hid_t    DBmaterial_mt5;
584 
585 typedef struct DBmultimesh_mt {
586     int                 nblocks;
587     int                 cycle;
588     int                 ngroups;
589     int                 blockorigin;
590     int                 grouporigin;
591     float               time;
592     double              dtime;
593     int                 guihide;
594     int                 extentssize;
595     char                meshtypes[256];
596     char                meshnames[256];
597     char                extents[256];
598     char                zonecounts[256];
599     char                has_external_zones[256];
600     int                 lgroupings;
601     char                groupings[256];
602     char                groupnames[256];
603     char                mrgtree_name[256];
604     int                 tv_connectivity;
605     int                 disjoint_mode;
606     int                 topo_dim;
607     char                file_ns_name[256];
608     char                block_ns_name[256];
609     int                 block_type;
610     char                empty_list[256];
611     int                 empty_cnt;
612     int                 repr_block_idx;
613     char                alt_nodenum_vars[256];
614     char                alt_zonenum_vars[256];
615 } DBmultimesh_mt;
616 static hid_t    DBmultimesh_mt5;
617 
618 typedef struct DBmultimeshadj_mt {
619     int                 nblocks;
620     int                 blockorigin;
621     int                 lneighbors;
622     int                 totlnodelists;
623     int                 totlzonelists;
624     char                meshtypes[256];
625     char                nneighbors[256];
626     char                neighbors[256];
627     char                back[256];
628     char                lnodelists[256];
629     char                nodelists[256];
630     char                lzonelists[256];
631     char                zonelists[256];
632 } DBmultimeshadj_mt;
633 static hid_t DBmultimeshadj_mt5;
634 
635 typedef struct DBmultivar_mt {
636     int                 nvars;
637     int                 cycle;
638     int                 ngroups;
639     int                 blockorigin;
640     int                 grouporigin;
641     float               time;
642     double              dtime;
643     int                 extentssize;
644     int                 guihide;
645     char                vartypes[256];
646     char                varnames[256];
647     char                extents[256];
648     char                region_pnames[256];
649     char                mmesh_name[256];
650     int                 tensor_rank;
651     int                 conserved;
652     int                 extensive;
653     char                file_ns_name[256];
654     char                block_ns_name[256];
655     int                 block_type;
656     char                empty_list[256];
657     int                 empty_cnt;
658     int                 repr_block_idx;
659     double              missing_value;
660 } DBmultivar_mt;
661 static hid_t    DBmultivar_mt5;
662 
663 typedef struct DBmultimat_mt {
664     int                 nmats;
665     int                 cycle;
666     int                 ngroups;
667     int                 blockorigin;
668     int                 grouporigin;
669     float               time;
670     double              dtime;
671     int                 allowmat0;
672     int                 guihide;
673     char                matnames[256];
674     char                matnos[256];
675     char                mixlens[256];
676     char                matcounts[256];
677     char                matlists[256];
678     int                 nmatnos;
679     char                material_names[256];
680     char                mat_colors[256];
681     char                mmesh_name[256];
682     char                file_ns_name[256];
683     char                block_ns_name[256];
684     char                empty_list[256];
685     int                 empty_cnt;
686     int                 repr_block_idx;
687 } DBmultimat_mt;
688 static hid_t    DBmultimat_mt5;
689 
690 typedef struct DBmultimatspecies_mt {
691     int                 nspec;
692     int                 nmat;
693     int                 cycle;
694     int                 ngroups;
695     int                 blockorigin;
696     int                 grouporigin;
697     float               time;
698     double              dtime;
699     int                 guihide;
700     char                specnames[256];
701     char                nmatspec[256];
702     char                matname[256];
703     char                species_names[256];
704     char                speccolors[256];
705     char                file_ns_name[256];
706     char                block_ns_name[256];
707     char                empty_list[256];
708     int                 empty_cnt;
709     int                 repr_block_idx;
710 } DBmultimatspecies_mt;
711 static hid_t    DBmultimatspecies_mt5;
712 
713 typedef struct DBmatspecies_mt {
714     int                 ndims;
715     int                 nmat;
716     int                 nspecies_mf;
717     int                 mixlen;
718     int                 major_order;
719     int                 datatype;
720     int                 dims[3];
721     int                 guihide;
722     char                matname[256];
723     char                speclist[256];
724     char                nmatspec[256];
725     char                species_mf[256];
726     char                mix_speclist[256];
727     char                specnames[256];
728     char                speccolors[256];
729 } DBmatspecies_mt;
730 static hid_t    DBmatspecies_mt5;
731 
732 typedef struct DBpointmesh_mt {
733     int                 ndims;
734     int                 nspace;
735     int                 nels;
736     int                 cycle;
737     int                 group_no;
738     float               time;
739     double              dtime;
740     int                 origin;
741     int                 min_index;
742     int                 max_index;
743     double              min_extents[3];
744     double              max_extents[3];
745     int                 guihide;
746     char                coord[3][256];
747     char                label[3][256];
748     char                units[3][256];
749     char                gnodeno[256];
750     char                mrgtree_name[256];
751     char                ghost_node_labels[256];
752     int                 gnznodtype;
753     char                alt_nodenum_vars[256];
754 } DBpointmesh_mt;
755 static hid_t    DBpointmesh_mt5;
756 
757 typedef struct DBpointvar_mt {
758     int                 nvals;
759     int                 nels;
760     int                 ndims;
761     int                 nspace;
762     int                 origin;
763     int                 min_index;
764     int                 max_index;
765     int                 datatype;
766     int                 cycle;
767     float               time;
768     double              dtime;
769     int                 guihide;
770     int                 ascii_labels;
771     char                meshid[256];
772     char                label[256];
773     char                units[256];
774     char                data[MAX_VARS][256];
775     char                region_pnames[256];
776     int                 conserved;
777     int                 extensive;
778     double              missing_value;
779 } DBpointvar_mt;
780 static hid_t    DBpointvar_mt5;
781 
782 typedef struct DBcompoundarray_mt {
783     int                 nelems;
784     int                 nvalues;
785     int                 datatype;
786     char                values[256];
787     char                elemnames[256];
788     char                elemlengths[256];
789 } DBcompoundarray_mt;
790 static hid_t    DBcompoundarray_mt5;
791 
792 typedef struct DBmrgtree_mt {
793     /* from the DBmrgtree header struct */
794     int            src_mesh_type;
795     int            type_info_bits;
796     int            num_nodes;
797     int            root;
798     char           src_mesh_name[256];
799 
800     /* contents of tree from the DBmrgtnode struct */
801     char           n_scalars[256]; /* scalar data for a node */
802     char           n_name[256];
803     char           n_names[256];
804     char           n_maps_name[256];
805     char           n_seg_ids[256];
806     char           n_seg_lens[256];
807     char           n_seg_types[256];
808     char           n_children[256];
809 
810     char           mrgvar_onames[256];
811     char           mrgvar_rnames[256];
812 } DBmrgtree_mt;
813 static hid_t   DBmrgtree_mt5;
814 
815 typedef struct DBgroupelmap_mt {
816     int            num_segments;
817     int            fracs_data_type;
818     char           groupel_types[256];
819     char           segment_lengths[256];
820     char           segment_ids[256];
821     char           segment_data[256];
822     char           frac_lengths[256];
823     char           segment_fracs[256];
824 } DBgroupelmap_mt;
825 static hid_t DBgroupelmap_mt5;
826 
827 typedef struct DBmrgvar_mt {
828     int nregns;
829     int ncomps;
830     int datatype;
831     char mrgt_name[256];
832     char reg_pnames[256];
833     char compnames[256];
834     char data[MAX_VARS][256];
835 } DBmrgvar_mt;
836 static hid_t DBmrgvar_mt5;
837 
838 static hid_t    T_char = -1;
839 static hid_t    T_short = -1;
840 static hid_t    T_int = -1;
841 static hid_t    T_long = -1;
842 static hid_t    T_llong = -1;
843 static hid_t    T_float = -1;
844 static hid_t    T_double = -1;
845 static hid_t    T_str256 = -1;
846 static hid_t    SCALAR = -1;
847 static hid_t    P_crprops = -1;
848 static hid_t    P_ckcrprops = -1;
849 static hid_t    P_rdprops = -1;
850 static hid_t    P_ckrdprops = -1;
851 
852 #define OPT(V)          ((V)?(V):"")
853 #define OFFSET(P,F)     ((char*)&((P).F)-(char*)&(P))
854 #define ENDOF(S)        ((S)+strlen(S))
855 
856 /*
857  * Use these macros to define compound data types. The following form defines
858  * an hdf5 data type called `DBcurve_mt5' which describes the C data type
859  * `DBcurve_mt'.
860  *
861  *      STRUCT(DBcurve) {
862  *          MEMBER(int,         npts);
863  *          MEMBER(int,         datatype);
864  *          MEMBER(str256,      label);
865  *      } DEFINE;
866  *
867  * The following construct creates a temporary hdf5 data type `_mt' that
868  * which is based on the C data type `DBcurve_mt' but which has minimal sizes
869  * for character strings and may be missing character string fields which are
870  * empty.
871  *
872  *      DBcurve_mt m;
873  *      STRUCT(DBcurve) {
874  *          MEMBER(int,         npts);
875  *          m.npts = npts;
876  *          MEMBER(int,         datatype);
877  *          m.datatype = dtype;
878  *          MEMBER(str(xname),  xvarname);
879  *          strcpy(m.xvarname, OPT(xname));
880  *      } OUTPUT(dbfile, DB_CURVE, "objname", &m);
881  */
882 #define STRUCT(S) {                                                           \
883     int         _i, _j=0;       /*counters*/                                  \
884     hsize_t     _size;          /*number of repeated components*/             \
885     size_t      _f_off=0;       /*offset into file data type*/                \
886     DBfile_hdf5 *_f=NULL;       /*file for target types*/                     \
887     S##_mt      _m;             /*temp to calculate offsets*/                 \
888     hid_t       _tmp_m, _tmp_f; /*memory and file temporaries*/               \
889     hid_t       _mt=-1, _ft=-1; /*memory and file data types*/                \
890     char        _fullname[256]; /*name for repeated members*/                 \
891                                                                               \
892     for (_i=0; _i<3; _i++) {                                                  \
893         switch (_i) {                                                         \
894         case 0:                                                               \
895             /*                                                                \
896              * Fall through to pick up closing arguments. Touch local         \
897              * variables so compiler doesn't complain about them not being    \
898              * used.                                                          \
899              */                                                               \
900             _size = sprintf(_fullname, "%d", _j);                             \
901             break;                                                            \
902                                                                               \
903         case 2:                                                               \
904             /* Define global DB*_mt5 data type for memory */                  \
905             S##_mt5 = _mt;                                                    \
906             break;                                                            \
907                                                                               \
908         case 1:                                                               \
909             /* Build data types, file multiplier is arbitrary */              \
910             _mt = H5Tcreate(H5T_COMPOUND, sizeof _m);                         \
911             if (_f) _ft = H5Tcreate(H5T_COMPOUND, 3*sizeof _m);               \
912             /* MEMBER DEFINITIONS HERE... */
913 
914 #define MEMBER_DUMMY(TYPE,NAME) {                                             \
915     _tmp_m = T_##TYPE; /*possible function call*/                             \
916     if (_tmp_m>=0) {                                                          \
917         db_hdf5_put_cmemb(_mt, #NAME, 0, 0, NULL, _tmp_m);                    \
918         if (_f && (_tmp_f=_f->T_##TYPE)>=0) {                                 \
919             db_hdf5_put_cmemb(_ft, #NAME, _f_off, 0, NULL, _tmp_f);           \
920             _f_off += H5Tget_size(_tmp_f);                                    \
921         }                                                                     \
922     }                                                                         \
923 }
924 
925 #define MEMBER_S(TYPE,NAME) {                                                 \
926     _tmp_m = T_##TYPE; /*possible function call*/                             \
927     if (_tmp_m>=0) {                                                          \
928         db_hdf5_put_cmemb(_mt, #NAME, OFFSET(_m, NAME), 0, NULL, _tmp_m);     \
929         if (_f && (_tmp_f=_f->T_##TYPE)>=0) {                                 \
930             db_hdf5_put_cmemb(_ft, #NAME, _f_off, 0, NULL, _tmp_f);           \
931             _f_off += H5Tget_size(_tmp_f);                                    \
932         }                                                                     \
933     }                                                                         \
934 }
935 
936 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
937 #define MEMBER_3(TYPE,NAME) {                                                 \
938     _tmp_m = T_##TYPE; /*possible function call*/                             \
939     if (_tmp_m>=0) {                                                          \
940         hid_t _m_ary;                                                         \
941         _size = 3;                                                            \
942         _m_ary = H5Tarray_create(_tmp_m, 1, &_size, NULL);                    \
943         db_hdf5_put_cmemb(_mt, #NAME, OFFSET(_m, NAME), 0, NULL, _m_ary);     \
944         H5Tclose(_m_ary);                                                     \
945         if (_f && (_tmp_f=_f->T_##TYPE)>=0) {                                 \
946             hid_t _f_ary = H5Tarray_create(_tmp_f, 1, &_size, NULL);          \
947             db_hdf5_put_cmemb(_ft, #NAME, _f_off, 0, NULL, _f_ary);           \
948             _f_off += H5Tget_size(_f_ary);                                    \
949             H5Tclose(_f_ary);                                                 \
950         }                                                                     \
951     }                                                                         \
952 }
953 #else
954 #define MEMBER_3(TYPE,NAME) {                                                 \
955     _tmp_m = T_##TYPE; /*possible function call*/                             \
956     if (_tmp_m>=0) {                                                          \
957         _size = 3;                                                            \
958         db_hdf5_put_cmemb(_mt, #NAME, OFFSET(_m, NAME), 1, &_size, _tmp_m);   \
959         if (_f && (_tmp_f=_f->T_##TYPE)>=0) {                                 \
960             db_hdf5_put_cmemb(_ft, #NAME, _f_off, 1, &_size, _tmp_f);         \
961             _f_off += 3*H5Tget_size(_tmp_f);                                  \
962         }                                                                     \
963     }                                                                         \
964 }
965 #endif
966 
967 #define MEMBER_R(TYPE,NAME,N) {                                               \
968     for (_j=0; _j<N; _j++) {                                                  \
969         _tmp_m = T_##TYPE; /*possible function call*/                         \
970         if (_tmp_m>=0) {                                                      \
971             sprintf(_fullname, "%s%d", #NAME, _j);                            \
972             db_hdf5_put_cmemb(_mt, _fullname, OFFSET(_m, NAME[_j]), 0, NULL,  \
973                               _tmp_m);                                        \
974             if (_f && (_tmp_f=_f->T_##TYPE)>=0) {                             \
975                 db_hdf5_put_cmemb(_ft, _fullname, _f_off, 0, NULL, _tmp_f);   \
976                 _f_off += H5Tget_size(_tmp_f);                                \
977             }                                                                 \
978         }                                                                     \
979     }                                                                         \
980 }
981 
982 #define OUTPUT(DBFILE,DBTYPE,NAME,MEM)                                        \
983             break;                                                            \
984         }                                                                     \
985         if (0==_i) _f=(DBFILE);                                               \
986         else if (1==_i) break;                                                \
987     }                                                                         \
988     if (!_f_off) MEMBER_DUMMY(int,dummy);                                     \
989     H5Tpack(_ft);                                                             \
990     db_hdf5_hdrwr(DBFILE, (char*)NAME, _mt, _ft, MEM, DBTYPE);                \
991     H5Tclose(_mt);                                                            \
992     H5Tclose(_ft);                                                            \
993     suppress_set_but_not_used_warning(&_size);                                \
994 }
995 
996 #define DEFINE                                                                \
997             break;                                                            \
998         }                                                                     \
999     }                                                                         \
1000     suppress_set_but_not_used_warning(&_size);                                \
1001 }
1002 
1003 /*ARGSUSED*/
1004 INTERNAL void
suppress_set_but_not_used_warning(void const * ptr)1005 suppress_set_but_not_used_warning(void const *ptr)
1006 {}
1007 
1008 #ifdef HAVE_FPZIP
1009 
1010 /* The following section of code are HDF5 filters to implement FPZIP
1011    compression algorithms
1012 
1013    Programmer: Mark C. Miller
1014    Created:    July, 2008
1015 */
1016 
1017 typedef struct db_hdf5_fpzip_params_t {
1018     int                 loss; /* set by client call to DBSetCompression() */
1019     int                 isfp;
1020     int                 dp;
1021     int                 totsize1d;
1022     int                 ndims;
1023     int                 dims[10];
1024 } db_hdf5_fpzip_params_t;
1025 static db_hdf5_fpzip_params_t db_hdf5_fpzip_params;
1026 
1027 static herr_t
db_hdf5_fpzip_can_apply(hid_t dcpl_id,hid_t type_id,hid_t space_id)1028 db_hdf5_fpzip_can_apply(hid_t dcpl_id, hid_t type_id, hid_t space_id)
1029 {
1030 #if HDF5_VERSION_GE(1,8,8)
1031     if (H5Tget_class(type_id) != H5T_FLOAT)
1032         return 0;
1033     return 1;
1034 #else
1035     /* Older versions of HDF5 don't like being told '0' for certain cases.
1036      * So, let it pass and handle it in the actual filter operation by
1037      * skipping non-float data there. */
1038     return 1;
1039 #endif
1040 }
1041 
1042 static herr_t
db_hdf5_fpzip_set_local(hid_t dcpl_id,hid_t type_id,hid_t space_id)1043 db_hdf5_fpzip_set_local(hid_t dcpl_id, hid_t type_id, hid_t space_id)
1044 {
1045     int i;
1046     hsize_t dims[10] = {1,1,1,1,1,1,1,1,1,1}, maxdims[10];
1047     db_hdf5_fpzip_params.dp = H5Tget_size(type_id) > sizeof(float) ? 1 : 0;
1048     db_hdf5_fpzip_params.totsize1d = (int) H5Sget_simple_extent_npoints(space_id);
1049     db_hdf5_fpzip_params.isfp = H5Tget_class(type_id) == H5T_FLOAT;
1050     db_hdf5_fpzip_params.ndims = H5Sget_simple_extent_ndims(space_id);
1051     H5Sget_simple_extent_dims(space_id, dims, maxdims);
1052     for (i = 0; i < db_hdf5_fpzip_params.ndims; i++)
1053         db_hdf5_fpzip_params.dims[i] = (int) dims[i];
1054     return 1;
1055 }
1056 
1057 static size_t
db_hdf5_fpzip_filter_op(unsigned int flags,size_t cd_nelmts,const unsigned int cd_values[],size_t nbytes,size_t * buf_size,void ** buf)1058 db_hdf5_fpzip_filter_op(unsigned int flags, size_t cd_nelmts,
1059     const unsigned int cd_values[], size_t nbytes,
1060     size_t *buf_size, void **buf)
1061 {
1062     size_t early_retval = 0;
1063 
1064     if (flags & H5Z_FLAG_REVERSE) /* read case */
1065     {
1066         int prec, dp;
1067         unsigned nx, ny, nz, nf;
1068         int new_buf_size;
1069         void *uncbuf;
1070 
1071         /* first, decode fpzip's header */
1072         fpzip_memory_read(*buf, 0, &prec, &dp, &nx, &ny, &nz, &nf);
1073         new_buf_size = nx * ny * nz * nf * (dp ? sizeof(double) : sizeof(float));
1074         if (new_buf_size <= 0)
1075            return early_retval;
1076 
1077         /* allocate space and do the decompression */
1078         uncbuf = malloc(new_buf_size);
1079         if (!fpzip_memory_read(*buf, uncbuf, &prec, &dp, &nx, &ny, &nz, &nf))
1080         {
1081             free(uncbuf);
1082             return early_retval;
1083         }
1084 
1085         free(*buf);
1086         *buf = uncbuf;
1087         *buf_size = new_buf_size;
1088         return new_buf_size;
1089     }
1090     else /* write case */
1091     {
1092         unsigned char *cbuf;
1093         int max_outbytes, outbytes, prec;
1094 
1095         /* We'll only compress floating point data here, not integer data */
1096         if (!db_hdf5_fpzip_params.isfp)
1097             return 0;
1098 
1099         /* We can't operate in place like HDF5 wants. But, thats ok.
1100          * Next, we can't easily predict compressed size but we need
1101          * to allocate a buffer to compress into. Fortunately, fpzip
1102          * will try to compress into any sized buffer we pass and
1103          * fail if it cannot. So, we decide here what is the minimum
1104          * compression we want, allocate a buffer of that size and
1105          * try to compress into it. If it fails, we return the right
1106          * stuff to HDF5 and do not compress */
1107 
1108         max_outbytes = nbytes / SILO_Globals.compressionMinratio;
1109         cbuf = (unsigned char *) malloc(max_outbytes);
1110 
1111         /* full precision */
1112         prec = 8 * (db_hdf5_fpzip_params.dp ? sizeof(double) : sizeof(float));
1113 
1114         /* precision with loss factored in */
1115         prec = (prec * (4 - db_hdf5_fpzip_params.loss)) / 4;
1116 
1117         if (db_hdf5_fpzip_params.ndims == 1 || db_hdf5_fpzip_params.ndims > 3)
1118         {
1119             outbytes = fpzip_memory_write(cbuf, max_outbytes, *buf,
1120                     &prec, db_hdf5_fpzip_params.dp,
1121                     db_hdf5_fpzip_params.totsize1d, 1, 1, 1);
1122         }
1123         else if (db_hdf5_fpzip_params.ndims == 2)
1124             outbytes = fpzip_memory_write(cbuf, max_outbytes, *buf,
1125                     &prec, db_hdf5_fpzip_params.dp,
1126                     db_hdf5_fpzip_params.dims[0],
1127                     db_hdf5_fpzip_params.dims[1], 1, 1);
1128         else
1129         {
1130             outbytes = fpzip_memory_write(cbuf, max_outbytes, *buf,
1131                     &prec, db_hdf5_fpzip_params.dp,
1132                     db_hdf5_fpzip_params.dims[0],
1133                     db_hdf5_fpzip_params.dims[1],
1134                     db_hdf5_fpzip_params.dims[2], 1);
1135         }
1136 
1137         /* If fpzip failed in any way, it returns zero */
1138         if (outbytes == 0)
1139         {
1140             free(cbuf);
1141             return early_retval;
1142         }
1143 
1144         /* We had a success. So, free old buffer and return new values */
1145         free(*buf);
1146         *buf = cbuf;
1147         *buf_size = max_outbytes;
1148         return outbytes;
1149     }
1150 }
1151 static H5Z_class_t db_hdf5_fpzip_class;
1152 #endif
1153 
1154 #ifndef HAVE_HZIP
1155 /*ARGSUSED*/
1156 static void
FreeNodelists(DBfile_hdf5 * dbfile,char const * meshname)1157 FreeNodelists(DBfile_hdf5 *dbfile, char const *meshname) {}
1158 #else
1159 
1160 /* The following section of code is used to mange caching of nodelists
1161    to support HZIP compression.
1162 
1163    Programmer: Mark C. Miller
1164    Created:    July, 2008
1165 */
1166 
1167 #define MAX_NODELIST_INFOS 32
1168 typedef struct _zlInfo {
1169     DBfile_hdf5 *db5file;
1170     char *meshname;
1171     char *zlname;
1172     DBzonelist *zl;
1173 } zlInfo_t;
1174 static zlInfo_t keptNodelistInfos[MAX_NODELIST_INFOS];
1175 
1176 /*
1177    We can lookup a nodelist either by its name or the name of the mesh that
1178    uses it. The preference is to use the name of the zonelist itself.
1179 */
1180 static const DBzonelist*
LookupNodelist(DBfile_hdf5 * dbfile,char const * zlname,char const * meshname)1181 LookupNodelist(DBfile_hdf5 *dbfile, char const *zlname, char const *meshname)
1182 {
1183     int i;
1184     char fullmname[256];
1185     char fullzlname[256];
1186     if (zlname)
1187         db_hdf5_fullname(dbfile, (char*) zlname, fullzlname);
1188     if (meshname)
1189         db_hdf5_fullname(dbfile, (char*) meshname, fullmname);
1190     for (i = 0; i < MAX_NODELIST_INFOS; i++)
1191     {
1192         if (keptNodelistInfos[i].zl && (keptNodelistInfos[i].db5file == dbfile))
1193         {
1194             if (zlname && keptNodelistInfos[i].zlname &&
1195                 (strcmp(fullzlname, keptNodelistInfos[i].zlname) == 0))
1196             {
1197                 if (meshname && !keptNodelistInfos[i].meshname)
1198                     keptNodelistInfos[i].meshname = STRDUP(fullmname);
1199                 return keptNodelistInfos[i].zl;
1200             }
1201             if (meshname && keptNodelistInfos[i].meshname &&
1202                 (strcmp(fullmname, keptNodelistInfos[i].meshname) == 0))
1203             {
1204                 if (zlname && !keptNodelistInfos[i].zlname)
1205                     keptNodelistInfos[i].zlname = STRDUP(fullzlname);
1206                 return keptNodelistInfos[i].zl;
1207             }
1208         }
1209     }
1210     return 0;
1211 }
1212 
1213 /*
1214  Part of registering a nodelist is to first check to see if we don't already
1215  have one. So, we call LookupNodelist as a first step.
1216 */
1217 static void
RegisterNodelist(DBfile_hdf5 * dbfile,char const * zlname,char const * meshname,int ntopodims,int nzones,int origin,int const * nodelist)1218 RegisterNodelist(DBfile_hdf5 *dbfile, char const *zlname, char const *meshname,
1219     int ntopodims, int nzones, int origin, int const *nodelist)
1220 {
1221     DBzonelist *zl;
1222     int i;
1223     int lnodelist = (1<<ntopodims) * nzones;
1224     int snodelist = lnodelist * sizeof(int);
1225     char fullname[256], fullmname[256];
1226 
1227     if (LookupNodelist(dbfile, zlname, meshname))
1228         return;
1229 
1230     if (zlname)
1231         db_hdf5_fullname(dbfile, (char*) zlname, fullname);
1232     if (meshname)
1233         db_hdf5_fullname(dbfile, (char*) meshname, fullmname);
1234 
1235     zl = DBAllocZonelist();
1236     if (!zl) return;
1237     zl->ndims = ntopodims;
1238     zl->nzones = nzones;
1239     zl->nshapes = 1;
1240     zl->origin = origin;
1241     zl->shapecnt = (int *)malloc(sizeof(int));
1242     zl->shapecnt[0] = nzones;
1243     zl->shapetype = (int *)malloc(sizeof(int));
1244     zl->shapetype[0] = ntopodims == 2 ? DB_ZONETYPE_QUAD : DB_ZONETYPE_HEX;
1245     zl->shapesize = (int *)malloc(sizeof(int));
1246     zl->shapesize[0] = (1 << ntopodims);
1247     zl->lnodelist = lnodelist;
1248     zl->nodelist = (int *)malloc(snodelist);
1249     memcpy(zl->nodelist, nodelist, snodelist);
1250 
1251     for (i = 0; i < MAX_NODELIST_INFOS; i++)
1252     {
1253         if (keptNodelistInfos[i].zl == 0)
1254             break;
1255     }
1256     if (i == MAX_NODELIST_INFOS)
1257         return;
1258 
1259     keptNodelistInfos[i].db5file = dbfile;
1260     if (zlname)
1261         keptNodelistInfos[i].zlname = STRDUP(fullname);
1262     if (meshname)
1263         keptNodelistInfos[i].meshname = STRDUP(fullmname);
1264     keptNodelistInfos[i].zl = zl;
1265 }
1266 
1267 static void
AddMeshnameToNodelist(DBfile_hdf5 * dbfile,char const * zlname,char const * meshname)1268 AddMeshnameToNodelist(DBfile_hdf5 *dbfile, char const *zlname, char const *meshname)
1269 {
1270     int i;
1271     char fullmname[256];
1272     char fullzlname[256];
1273 
1274     db_hdf5_fullname(dbfile, (char*) zlname, fullzlname);
1275     db_hdf5_fullname(dbfile, (char*) meshname, fullmname);
1276 
1277     for (i = 0; i < MAX_NODELIST_INFOS; i++)
1278     {
1279         if (keptNodelistInfos[i].zl && (keptNodelistInfos[i].db5file == dbfile))
1280         {
1281             if (keptNodelistInfos[i].zlname && !keptNodelistInfos[i].meshname &&
1282                 strcmp(fullzlname, keptNodelistInfos[i].zlname) == 0)
1283             {
1284                 keptNodelistInfos[i].meshname = STRDUP(fullmname);
1285                 break;
1286             }
1287         }
1288     }
1289 }
1290 
1291 static void
FreeNodelists(DBfile_hdf5 * dbfile,char const * meshname)1292 FreeNodelists(DBfile_hdf5 *dbfile, char const *meshname)
1293 {
1294     int i;
1295     if (meshname && dbfile) /* clear all for a given mesh */
1296     {
1297         char fullmname[256];
1298         db_hdf5_fullname(dbfile, (char*) meshname, fullmname);
1299 
1300         for (i = 0; i < MAX_NODELIST_INFOS; i++)
1301         {
1302             if (keptNodelistInfos[i].zl && keptNodelistInfos[i].meshname &&
1303                 (strcmp(fullmname, keptNodelistInfos[i].meshname) == 0))
1304             {
1305                 FREE(keptNodelistInfos[i].meshname);
1306                 FREE(keptNodelistInfos[i].zlname);
1307                 DBFreeZonelist(keptNodelistInfos[i].zl);
1308                 memset(&keptNodelistInfos[i], 0x0, sizeof(keptNodelistInfos[i]));
1309             }
1310         }
1311     }
1312     else if (dbfile) /* clear all for a given file */
1313     {
1314         for (i = 0; i < MAX_NODELIST_INFOS; i++)
1315         {
1316             if (keptNodelistInfos[i].zl && (keptNodelistInfos[i].db5file == dbfile))
1317             {
1318                 FREE(keptNodelistInfos[i].meshname);
1319                 FREE(keptNodelistInfos[i].zlname);
1320                 DBFreeZonelist(keptNodelistInfos[i].zl);
1321                 memset(&keptNodelistInfos[i], 0x0, sizeof(keptNodelistInfos[i]));
1322             }
1323         }
1324     }
1325     else /* clear everything that is non-empty */
1326     {
1327         for (i = 0; i < MAX_NODELIST_INFOS; i++)
1328         {
1329             if (keptNodelistInfos[i].zl)
1330             {
1331                 FREE(keptNodelistInfos[i].meshname);
1332                 FREE(keptNodelistInfos[i].zlname);
1333                 DBFreeZonelist(keptNodelistInfos[i].zl);
1334                 memset(&keptNodelistInfos[i], 0x0, sizeof(keptNodelistInfos[i]));
1335             }
1336         }
1337     }
1338 }
1339 
1340 /* The following section of code are HDF5 filters to implement FPZIP
1341    compression algorithms
1342 
1343    Programmer: Mark C. Miller
1344    Created:    July, 2008
1345 
1346    Modifications:
1347      Mark C. Miller, Thu Feb  4 20:02:00 PST 2010
1348      Corrected type for hztype local variable from int to HZtype.
1349 
1350 */
1351 
silo2hztype(int silo_type)1352 static HZtype silo2hztype(int silo_type)
1353 {
1354     switch (silo_type)
1355     {
1356         case DB_CHAR: return hzUCHAR;
1357         case DB_SHORT: return hzUSHORT;
1358         case DB_INT: return hzINT;
1359         case DB_FLOAT: return hzFLOAT;
1360         case DB_DOUBLE: return hzDOUBLE;
1361     }
1362     return hzUCHAR;
1363 }
1364 
hztype2silo(HZtype hztype)1365 static int hztype2silo(HZtype hztype)
1366 {
1367     switch (hztype)
1368     {
1369         case hzUCHAR: return DB_CHAR;
1370         case hzUSHORT: return DB_SHORT;
1371         case hzINT: return DB_INT;
1372         case hzFLOAT: return DB_FLOAT;
1373         case hzDOUBLE: return DB_DOUBLE;
1374     }
1375     return DB_CHAR;
1376 }
1377 
sizeof_hztype(HZtype hztype)1378 static int sizeof_hztype(HZtype hztype)
1379 {
1380     switch (hztype)
1381     {
1382         case hzUCHAR: return sizeof(unsigned char);
1383         case hzUSHORT: return sizeof(unsigned short);
1384         case hzINT: return sizeof(int);
1385         case hzFLOAT: return sizeof(float);
1386         case hzDOUBLE: return sizeof(double);
1387     }
1388     return sizeof(double);
1389 }
1390 
1391 typedef struct db_hdf5_hzip_params_t {
1392     /* these items set DBSetCompression call */
1393     unsigned            codec;
1394     void const         *params;
1395 
1396     /* these items set by hdf5 driver as needed. */
1397     int                 iszl;
1398     char const         *zlname;
1399     char const         *meshname;
1400     DBfile_hdf5        *dbfile;
1401     int                 zlorigin;
1402     int                 isquad;
1403 
1404     /* these items set by hdf5 filter's set_local method */
1405     int                 totsize1d;
1406     int                 ndims;
1407     int                 dims[10];
1408     HZtype              hztype;
1409 } db_hdf5_hzip_params_t;
1410 static db_hdf5_hzip_params_t db_hdf5_hzip_params;
1411 
1412 static void
db_hdf5_hzip_clear_params()1413 db_hdf5_hzip_clear_params()
1414 {
1415     unsigned tmpcodec = db_hdf5_hzip_params.codec;
1416     void const *tmpparams = db_hdf5_hzip_params.params;
1417     memset(&db_hdf5_hzip_params, 0, sizeof(db_hdf5_hzip_params));
1418     db_hdf5_hzip_params.codec = tmpcodec;
1419     db_hdf5_hzip_params.params = tmpparams;
1420 }
1421 
1422 static herr_t
db_hdf5_hzip_can_apply(hid_t dcpl_id,hid_t type_id,hid_t space_id)1423 db_hdf5_hzip_can_apply(hid_t dcpl_id, hid_t type_id, hid_t space_id)
1424 {
1425     return 1;
1426 }
1427 
1428 static herr_t
db_hdf5_hzip_set_local(hid_t dcpl_id,hid_t type_id,hid_t space_id)1429 db_hdf5_hzip_set_local(hid_t dcpl_id, hid_t type_id, hid_t space_id)
1430 {
1431     int i;
1432     hsize_t dims[10] = {1,1,1,1,1,1,1,1,1,1}, maxdims[10];
1433     db_hdf5_hzip_params.hztype = silo2hztype(hdf2silo_type(type_id));
1434     db_hdf5_hzip_params.totsize1d = (int) H5Sget_simple_extent_npoints(space_id);
1435     db_hdf5_hzip_params.ndims = H5Sget_simple_extent_ndims(space_id);
1436     H5Sget_simple_extent_dims(space_id, dims, maxdims);
1437     for (i = 0; i < db_hdf5_hzip_params.ndims; i++)
1438         db_hdf5_hzip_params.dims[i] = (int) dims[i];
1439     return 1;
1440 }
1441 
1442 static size_t
db_hdf5_hzip_filter_op(unsigned int flags,size_t cd_nelmts,const unsigned int cd_values[],size_t nbytes,size_t * buf_size,void ** buf)1443 db_hdf5_hzip_filter_op(unsigned int flags, size_t cd_nelmts,
1444     const unsigned int cd_values[], size_t nbytes,
1445     size_t *buf_size, void **buf)
1446 {
1447     int early_retval = 0;
1448 
1449     if (flags & H5Z_FLAG_REVERSE) /* read case */
1450     {
1451         if (db_hdf5_hzip_params.iszl) /* ucd mesh zonelist */
1452         {
1453             HZMstream *stream;
1454             int ndims = 0, nzones = 0, nread;
1455             int *nodelist = 0;
1456             int new_buf_size;
1457 
1458             /* To query stream for ndims, we need to specify a permutation
1459                which may be wrong. So, we open, query, close and re-open. */
1460             stream = hzip_mesh_open_mem(*buf, nbytes, 0);
1461             if (stream == 0) return early_retval;
1462 
1463             ndims = hzip_mesh_dimensions(stream);
1464             hzip_mesh_close(stream);
1465             if (ndims < 2 || ndims > 3) return early_retval;
1466 
1467             /* Ok, no re-open the stream with correct permutation */
1468             stream = hzip_mesh_open_mem(*buf, nbytes, SILO_HZIP_PERMUTATION[ndims]);
1469             if (stream == 0) return early_retval;
1470 
1471             ndims = hzip_mesh_dimensions(stream);
1472             if (ndims < 2 || ndims > 3) {hzip_mesh_close(stream); return early_retval;}
1473 
1474             nzones = hzip_mesh_cells(stream);
1475             if (nzones < 0) {hzip_mesh_close(stream); return early_retval;}
1476 
1477             new_buf_size = (1<<ndims) * nzones * sizeof(int);
1478             nodelist = (int *) malloc(new_buf_size);
1479             if (nodelist == 0) {hzip_mesh_close(stream); return early_retval;}
1480 
1481             nread = hzip_mesh_read(stream, nodelist, nzones);
1482             hzip_mesh_close(stream);
1483             if (nread != nzones)
1484             {
1485                 free(nodelist);
1486                 return early_retval;
1487             }
1488 
1489             RegisterNodelist(db_hdf5_hzip_params.dbfile, db_hdf5_hzip_params.zlname,
1490                 db_hdf5_hzip_params.meshname, ndims, nzones,
1491                 db_hdf5_hzip_params.zlorigin, nodelist);
1492 
1493             free(*buf);
1494             *buf = (void*) nodelist;
1495             *buf_size = new_buf_size;
1496             return new_buf_size;
1497         }
1498         else /* ucd or quad mesh node-centered (not zone-centered) variables */
1499         {
1500             HZNstream *stream;
1501             int i, ndims, nnodes, nread, nzones;
1502             void *var = 0;
1503             int new_buf_size;
1504             HZtype hztype;
1505             int *nodelist;
1506             int perm, origin;
1507 
1508             /* To query stream for ndims, we need to specify a permutation
1509                which may be wrong. So, we open, query, close and re-open. */
1510             stream = hzip_node_open_mem(*buf, nbytes, 0, 0);
1511             if (stream == 0) return early_retval;
1512 
1513             ndims = hzip_node_dimensions(stream);
1514             hzip_node_close(stream);
1515             if (ndims < 2 || ndims > 3) return early_retval;
1516 
1517             if (db_hdf5_hzip_params.isquad)
1518             {
1519                 nzones = 1;
1520                 for (i = 0; i < db_hdf5_hzip_params.ndims; i++)
1521                     nzones *= (db_hdf5_hzip_params.dims[i]-1);
1522 
1523                 nodelist = (int *) malloc((1<<ndims) * nzones * sizeof(int));
1524                 if (nodelist == 0) return early_retval;
1525                 perm = hzip_mesh_construct(nodelist, (unsigned) ndims,
1526                     (const unsigned *) db_hdf5_hzip_params.dims, 0);
1527 
1528                 origin = 0;
1529             }
1530             else
1531             {
1532                 const DBzonelist *zl = LookupNodelist(db_hdf5_hzip_params.dbfile,
1533                     db_hdf5_hzip_params.zlname, db_hdf5_hzip_params.meshname);
1534                 if (zl == 0 || zl->nodelist == 0)
1535                     return early_retval;
1536                 nodelist = zl->nodelist;
1537                 nzones = zl->nzones;
1538                 origin = zl->origin;
1539                 perm = SILO_HZIP_PERMUTATION[ndims];
1540             }
1541 
1542             /* Ok, now open with correct permutation */
1543             stream = hzip_node_open_mem(*buf, nbytes, perm, origin);
1544             if (stream == 0) return early_retval;
1545 
1546             ndims = hzip_node_dimensions(stream);
1547             if (ndims < 2 || ndims > 3) {hzip_node_close(stream); return early_retval;}
1548 
1549             nnodes = hzip_node_count(stream);
1550             if (nnodes < 0) {hzip_node_close(stream); return early_retval;}
1551 
1552             hztype = hzip_node_type(stream);
1553             new_buf_size = nnodes * sizeof_hztype(hztype);
1554             var = malloc(new_buf_size);
1555             if (var == 0) {hzip_node_close(stream); return early_retval;}
1556 
1557             nread = hzip_node_read(stream, var, nodelist, nzones);
1558             hzip_node_close(stream);
1559             if (nread != nnodes)
1560             {
1561                 if (db_hdf5_hzip_params.isquad)
1562                     free(nodelist);
1563                 free(var);
1564                 return early_retval;
1565             }
1566 
1567             if (db_hdf5_hzip_params.isquad)
1568                 free(nodelist);
1569             free(*buf);
1570             *buf = var;
1571             *buf_size = new_buf_size;
1572             return new_buf_size;
1573         }
1574     }
1575     else /* write case */
1576     {
1577         if (db_hdf5_hzip_params.iszl) /* ucd mesh zonelist */
1578         {
1579             int outbytes, ntopo, nzones;
1580             size_t max_outbytes;
1581             HZMstream* stream;
1582             unsigned char *buffer = 0;
1583 
1584             const DBzonelist *zl = LookupNodelist(db_hdf5_hzip_params.dbfile,
1585                 db_hdf5_hzip_params.zlname, db_hdf5_hzip_params.meshname);
1586             if (zl == 0 || zl->nodelist == 0) return early_retval;
1587             ntopo = zl->ndims;
1588             nzones = zl->nzones;
1589 
1590             max_outbytes = ((1<<ntopo) * nzones * sizeof(int)) / SILO_Globals.compressionMinratio;
1591             buffer = (unsigned char *) malloc(max_outbytes);
1592             if (buffer == 0) return early_retval;
1593 
1594             stream = hzip_mesh_create_mem(buffer, max_outbytes, SILO_HZIP_PERMUTATION[ntopo],
1595                 ntopo, nzones, db_hdf5_hzip_params.codec, db_hdf5_hzip_params.params);
1596 
1597             if (stream == 0)
1598             {
1599                 free(buffer);
1600                 return early_retval;
1601             }
1602 
1603             if (hzip_mesh_write(stream, (int *)(*buf), nzones) < 0)
1604             {
1605                 hzip_mesh_close(stream);
1606                 free(buffer);
1607                 return early_retval;
1608             }
1609 
1610             if ((outbytes = hzip_mesh_close(stream)) < 0)
1611             {
1612                 free(buffer);
1613                 return early_retval;
1614             }
1615 
1616             free(*buf);
1617             *buf = buffer;
1618             *buf_size = max_outbytes;
1619             return outbytes;
1620         }
1621         else /* ucd or quad mesh coords or nodal variables */
1622         {
1623             int i, outbytes;
1624             size_t max_outbytes;
1625             HZNstream* stream;
1626             unsigned char *buffer = 0;
1627             int *nodelist;
1628             int ndims, origin, nzones, perm;
1629 
1630             /* Find the nodelist for this write */
1631             if (db_hdf5_hzip_params.isquad)
1632             {
1633                 ndims = db_hdf5_hzip_params.ndims;
1634                 origin = 0;
1635                 nzones = 1;
1636                 for (i = 0; i < ndims; i++)
1637                     nzones *= (db_hdf5_hzip_params.dims[i]-1);
1638                 nodelist = (int *) malloc((1<<ndims) * nzones * sizeof(int));
1639                 if (nodelist == 0) return early_retval;
1640                 perm = hzip_mesh_construct(nodelist, (unsigned) ndims,
1641                     (const unsigned int *) db_hdf5_hzip_params.dims, 0);
1642             }
1643             else
1644             {
1645                 const DBzonelist *zl = LookupNodelist(db_hdf5_hzip_params.dbfile,
1646                                           db_hdf5_hzip_params.zlname,
1647                                           db_hdf5_hzip_params.meshname);
1648                 if (zl == 0 || zl->nodelist == 0) return early_retval;
1649                 nodelist = zl->nodelist;
1650                 ndims = zl->ndims;
1651                 origin = zl->origin;
1652                 nzones = zl->nzones;
1653                 perm = SILO_HZIP_PERMUTATION[ndims];
1654             }
1655 
1656             max_outbytes = (db_hdf5_hzip_params.totsize1d *
1657                            sizeof_hztype(db_hdf5_hzip_params.hztype)) / SILO_Globals.compressionMinratio;
1658             buffer = (unsigned char *) malloc(max_outbytes);
1659             if (buffer == 0) return early_retval;
1660 
1661             stream = hzip_node_create_mem(buffer, max_outbytes, perm,
1662                 origin, ndims, db_hdf5_hzip_params.totsize1d, db_hdf5_hzip_params.hztype,
1663                 db_hdf5_hzip_params.codec, 0);
1664 
1665             if (stream == 0)
1666             {
1667                 if (db_hdf5_hzip_params.isquad)
1668                     free(nodelist);
1669                 free(buffer);
1670                 return early_retval;
1671             }
1672 
1673             if (hzip_node_write(stream, *buf, nodelist, nzones) < 0)
1674             {
1675                 hzip_node_close(stream);
1676                 if (db_hdf5_hzip_params.isquad)
1677                     free(nodelist);
1678                 free(buffer);
1679                 return early_retval;
1680             }
1681 
1682             if ((outbytes = hzip_node_close(stream)) < 0)
1683             {
1684                 if (db_hdf5_hzip_params.isquad)
1685                     free(nodelist);
1686                 free(buffer);
1687                 return early_retval;
1688             }
1689 
1690             /* We had a success. So, free old buffer and return new values */
1691             if (db_hdf5_hzip_params.isquad)
1692                 free(nodelist);
1693             free(*buf);
1694             *buf = buffer;
1695             *buf_size = max_outbytes;
1696             return outbytes;
1697         }
1698     }
1699 }
1700 static H5Z_class_t db_hdf5_hzip_class;
1701 #endif
1702 
1703 INTERNAL char const *
friendly_name(char const * base_name,char const * fmtstr,void const * val)1704 friendly_name(char const *base_name, char const *fmtstr, void const *val)
1705 {
1706     static char retval[1024];
1707     static char totfmtstr[1024];
1708     char typechar;
1709     int i, flen;
1710 
1711     if (SILO_Globals.enableFriendlyHDF5Names == FALSE)
1712         return 0;
1713 
1714     if (fmtstr == 0)
1715         return base_name;
1716 
1717     sprintf(totfmtstr, "%s%s", base_name, fmtstr);
1718     if (val == 0)
1719         return totfmtstr;
1720 
1721     flen = strlen(fmtstr);
1722     for (i = 0; i < flen; i++)
1723     {
1724         if (fmtstr[i] == '%')
1725            break;
1726     }
1727     typechar = i+1 < flen ? fmtstr[i+1] : '\0';
1728     switch (typechar)
1729     {
1730         case 'd': sprintf(retval, totfmtstr, *((int const*) val)); break;
1731         case 's': sprintf(retval, totfmtstr, *((char const*) val)); break;
1732         case 'f': sprintf(retval, totfmtstr, *((const float*) val)); break;
1733         default: return totfmtstr;
1734     }
1735     return retval;
1736 }
1737 
1738 /*-------------------------------------------------------------------------
1739  * Function:    db_hdf5_file
1740  *
1741  * Purpose:     Returns the hdf5 file ID associated with the DBfile. The
1742  *              hdf5 file is not reopened; the caller should not close the
1743  *              file id.
1744  *
1745  * Return:      Success:        HDF5 file id
1746  *
1747  *              Failure:        -1
1748  *
1749  * Programmer:  Robb Matzke
1750  *              Tuesday, March 23, 1999
1751  *
1752  * Modifications:
1753  *
1754  *-------------------------------------------------------------------------
1755  */
1756 PRIVATE hid_t
db_hdf5_file(DBfile * _dbfile)1757 db_hdf5_file(DBfile *_dbfile)
1758 {
1759     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
1760     return dbfile->fid;
1761 }
1762 
1763 /*-------------------------------------------------------------------------
1764  * Function:    db_hdf5_cwg
1765  *
1766  * Purpose:     Returns the hdf5 group ID for the current working group of
1767  *              the DBfile. The group is not reopened; the caller should not
1768  *              close the group ID.
1769  *
1770  * Return:      Success:        HDF5 current working group ID
1771  *
1772  *              Failure:        -1
1773  *
1774  * Programmer:  Robb Matzke
1775  *              Tuesday, March 23, 1999
1776  *
1777  * Modifications:
1778  *
1779  *-------------------------------------------------------------------------
1780  */
1781 PRIVATE hid_t
db_hdf5_cwg(DBfile * _dbfile)1782 db_hdf5_cwg(DBfile *_dbfile)
1783 {
1784     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
1785     return dbfile->cwg;
1786 }
1787 
1788 /*-------------------------------------------------------------------------
1789  * Function:    db_hdf5_get_cmemb
1790  *
1791  * Purpose:     Returns information about a member of a compound type. If
1792  *              the member is an array then it returns information about
1793  *              the array instead.
1794  *
1795  * Return:      Success:        HDF5 datatype of member. The number of
1796  *                              items is returned in SIZE.
1797  *
1798  *              Failure:        -1
1799  *
1800  * Programmer:  Robb Matzke, 2001-01-26
1801  *
1802  * Modifications:
1803  *
1804  *-------------------------------------------------------------------------
1805  */
1806 PRIVATE hid_t
db_hdf5_get_cmemb(hid_t compound_type,int membno,int * ndims,int size[3])1807 db_hdf5_get_cmemb(hid_t compound_type, int membno, int *ndims/*out*/,
1808                   int size[3]/*out*/)
1809 {
1810     hid_t       type;
1811 
1812     if ((type=H5Tget_member_type(compound_type, membno))<0) return -1;
1813 
1814 #if (H5_VERS_MAJOR==1 && H5_VERS_MINOR>=4) || H5_VERS_MAJOR>1
1815     if (H5T_ARRAY==H5Tget_class(type)) {
1816         hsize_t bigdims[3];
1817         int i;
1818         *ndims = H5Tget_array_ndims(type);
1819         assert(*ndims<=3);
1820         H5Tget_array_dims(type, bigdims, NULL);
1821         for (i=0; i<*ndims; i++) size[i] = bigdims[i];
1822         type = H5Tget_super(type);
1823     } else {
1824         *ndims = 0;
1825     }
1826 #else
1827     *ndims = H5Tget_member_dims(compound_type, membno, size, NULL);
1828 #endif
1829     return type;
1830 }
1831 
1832 /*-------------------------------------------------------------------------
1833  * Function:    db_hdf5_put_cmemb
1834  *
1835  * Purpose:
1836  *
1837  * Return:      Success:
1838  *
1839  *
1840  *              Failure:        -1
1841  *
1842  * Programmer:  Robb Matzke, 2001-01-26
1843  *
1844  * Modifications:
1845  *
1846  *-------------------------------------------------------------------------
1847  */
1848 PRIVATE int
db_hdf5_put_cmemb(hid_t compound_type,char const * name,size_t offset,int ndims,int const * dim,hid_t type)1849 db_hdf5_put_cmemb(hid_t compound_type, char const *name, size_t offset,
1850                   int ndims, int const *dim, hid_t type)
1851 {
1852     int         retval;
1853 
1854 #if (H5_VERS_MAJOR==1 && H5_VERS_MINOR>=4) || H5_VERS_MAJOR>1
1855     if (ndims) {
1856         hsize_t bigdims[16];
1857         int i;
1858         for (i=0; i<ndims; i++) bigdims[i] = dim[i];
1859         type = H5Tarray_create(type, ndims, bigdims, NULL);
1860     }
1861     retval = H5Tinsert(compound_type, name, offset, type);
1862     if (ndims) H5Tclose(type);
1863 #else
1864     retval = H5Tinsert_array(compound_type, name, offset, ndims, dim, NULL,
1865                              type);
1866 #endif
1867     return retval;
1868 }
1869 
1870 /*-------------------------------------------------------------------------
1871  * Function:    T_str
1872  *
1873  * Purpose:     Returns fixed-length hdf5 string data type which has just
1874  *              enough space to store the specified string.
1875  *
1876  * Return:      Success:        An hdf5 data type which will be closed on the
1877  *                              next call to this function.
1878  *
1879  *              Failure:        -1
1880  *
1881  * Programmer:  Robb Matzke
1882  *              Tuesday, March 23, 1999
1883  *
1884  * Modifications:
1885  *
1886  *-------------------------------------------------------------------------
1887  */
1888 static int T_str_stype_set = 0;
1889 PRIVATE hid_t
T_str(char * s)1890 T_str(char *s)
1891 {
1892     static hid_t        stype = -1;
1893 
1894     if (!s || !*s) return -1;
1895     if (T_str_stype_set && stype>=0) H5Tclose(stype);
1896     stype = H5Tcopy(H5T_C_S1);
1897     H5Tset_size(stype, strlen(s)+1);
1898     T_str_stype_set = 1;
1899     return stype;
1900 }
1901 
1902 /*-------------------------------------------------------------------------
1903  * Function:    silo_walk_cb
1904  *
1905  * Purpose:     Error stack walk callback.
1906  *              Currently, only detects checksum errors.
1907  *
1908  * Return:      SUCCESS
1909  *
1910  * Programmer:  Mark C. Miller
1911  *              Tuesday, May 2, 2006
1912  *
1913  * Modifications:
1914  *
1915  *   Mark C. Miller, Thu Jul 17 23:11:41 PDT 2008
1916  *   Added code to detect compression errors.
1917  *-------------------------------------------------------------------------
1918  */
1919 PRIVATE herr_t
silo_walk_cb(int n,H5E_error_t * err_desc,void * client_data)1920 silo_walk_cb(int n, H5E_error_t *err_desc, void *client_data)
1921 {
1922     int *silo_error_code_p = (int *) client_data;
1923 
1924     /* Note that error code can be overwritten by later strstr
1925        comparisons. Where both checksum and compression errors
1926        occur, we declare it a compression error. */
1927     if (strstr(err_desc->desc, "letcher32") != 0)
1928         *silo_error_code_p = E_CHECKSUM;
1929     if (strstr(err_desc->desc, "zip") != 0)
1930         *silo_error_code_p = E_COMPRESSION;
1931     if (strstr(err_desc->desc, "Lindstrom-") != 0)
1932         *silo_error_code_p = E_COMPRESSION;
1933 
1934     return 0;
1935 }
1936 
1937 /*-------------------------------------------------------------------------
1938  * Function:    hdf5_to_silo_error
1939  *
1940  * Purpose:     Convert HDF5 error stack to a silo error code.
1941  *              Currently, only detects checksum errors.
1942  *
1943  * Return:      SUCCESS
1944  *
1945  * Programmer:  Mark C. Miller
1946  *              Tuesday, May 2, 2006
1947  *
1948  *-------------------------------------------------------------------------
1949  */
1950 PRIVATE void
hdf5_to_silo_error(char const * vname,char const * fname)1951 hdf5_to_silo_error(char const *vname, char const *fname)
1952 {
1953     int silo_error_code = E_NOERROR;
1954 
1955     H5Ewalk(H5E_WALK_UPWARD, silo_walk_cb, &silo_error_code);
1956 
1957     if (silo_error_code == E_NOERROR)
1958         silo_error_code = E_CALLFAIL;
1959 
1960     db_perror((char*)vname, silo_error_code, (char*)fname);
1961 }
1962 
1963 /*-------------------------------------------------------------------------
1964  * Function:    db_hdf5_init
1965  *
1966  * Purpose:     One-time initializations for this driver.
1967  *
1968  * Return:      void
1969  *
1970  * Programmer:  Robb Matzke
1971  *              Monday, March 22, 1999
1972  *
1973  * Modifications:
1974  *
1975  *   Mark C. Miller, Wed Sep  2 16:41:32 PDT 2009
1976  *   Made conditional compilation logic for VERSION_GE take into account
1977  *   H5_USE_16_API setting.
1978  *
1979  *   Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
1980  *   Adding support for long long type.
1981  *
1982  *   Mark C. Miller, Thu Feb 11 09:37:41 PST 2010
1983  *   Added logic to set HDF5's error output based on Silo's settings.
1984  *
1985  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
1986  *   Added support for namescheme/empty_list options for multi-block objs.
1987  *-------------------------------------------------------------------------
1988  */
1989 PRIVATE void
db_hdf5_init(void)1990 db_hdf5_init(void)
1991 {
1992 
1993 #if !(HDF5_VERSION_GE(1,8,4) && !HDF5_VERSION_GE(1,8,5))
1994     static int          ncalls;
1995     if (ncalls++) return;               /*already initialized*/
1996 #else
1997     H5open();
1998 #endif
1999 
2000     /* Turn off error messages from the hdf5 library */
2001     if (SILO_Globals._db_err_level_drvr == DB_ALL)
2002         H5Eset_auto((H5E_auto1_t) H5Eprint1, stderr);
2003     else
2004         H5Eset_auto(NULL, NULL);
2005 
2006     /* Define a scalar data space */
2007     SCALAR = H5Screate(H5S_SCALAR);
2008 
2009     /* Define atomic data types */
2010     T_char = H5T_NATIVE_UCHAR;
2011     T_short = H5T_NATIVE_SHORT;
2012     T_int = H5T_NATIVE_INT;
2013     T_long = H5T_NATIVE_LONG;
2014     T_llong = H5T_NATIVE_LLONG;
2015     T_float = H5T_NATIVE_FLOAT;
2016     T_double = H5T_NATIVE_DOUBLE;
2017 
2018     T_str256 = H5Tcopy(H5T_C_S1);       /*this is never freed!*/
2019     H5Tset_size(T_str256, 256);
2020 
2021     P_ckcrprops = H5Pcreate(H5P_DATASET_CREATE); /* never freed */
2022     if (SILO_Globals.enableChecksums)
2023        H5Pset_fletcher32(P_ckcrprops);
2024 
2025     /* for H5Dread calls, H5P_DEFAULT results in *enabled*
2026        checksums. So, we build the DISabled version here. */
2027     P_ckrdprops = H5Pcreate(H5P_DATASET_XFER);   /* never freed */
2028     H5Pset_edc_check(P_ckrdprops, H5Z_DISABLE_EDC);
2029 
2030 #ifdef HAVE_FPZIP
2031     db_hdf5_fpzip_params.loss = 0;
2032 #if HDF5_VERSION_GE(1,8,0) && !defined(H5_USE_16_API)
2033     db_hdf5_fpzip_class.version = H5Z_CLASS_T_VERS;
2034     db_hdf5_fpzip_class.encoder_present = 1;
2035     db_hdf5_fpzip_class.decoder_present = 1;
2036 #endif
2037     db_hdf5_fpzip_class.id = DB_HDF5_FPZIP_ID;
2038     db_hdf5_fpzip_class.name = "Lindstrom-fpzip";
2039     db_hdf5_fpzip_class.can_apply = db_hdf5_fpzip_can_apply;
2040     db_hdf5_fpzip_class.set_local = db_hdf5_fpzip_set_local;
2041     db_hdf5_fpzip_class.filter = db_hdf5_fpzip_filter_op;
2042     H5Zregister(&db_hdf5_fpzip_class);
2043 #endif
2044 
2045 #ifdef HAVE_HZIP
2046 
2047 #ifdef HAVE_LIBZ
2048     db_hdf5_hzip_zlib_codec_params = hzm_codec_zlib;
2049 #endif
2050     db_hdf5_hzip_base_codec_params = hzm_codec_base;
2051 
2052 #ifdef HAVE_LIBZ
2053     db_hdf5_hzip_params.codec = HZM_CODEC_ZLIB;
2054     db_hdf5_hzip_params.params = &db_hdf5_hzip_zlib_codec_params;
2055     ((struct HZMCODECzlib *) db_hdf5_hzip_params.params)->bits = 12;
2056 #else
2057     db_hdf5_hzip_params.codec = HZM_CODEC_BASE;
2058     db_hdf5_hzip_params.params = &db_hdf5_hzip_base_codec_params;
2059     ((struct HZMCODECbase *) db_hdf5_hzip_params.params)->bits = 12;
2060 #endif
2061 
2062 #if HDF5_VERSION_GE(1,8,0) && !defined(H5_USE_16_API)
2063     db_hdf5_hzip_class.version = H5Z_CLASS_T_VERS;
2064     db_hdf5_hzip_class.encoder_present = 1;
2065     db_hdf5_hzip_class.decoder_present = 1;
2066 #endif
2067     db_hdf5_hzip_class.id = DB_HDF5_HZIP_ID;
2068     db_hdf5_hzip_class.name = "Lindstrom-hzip";
2069     db_hdf5_hzip_class.can_apply = db_hdf5_hzip_can_apply;
2070     db_hdf5_hzip_class.set_local = db_hdf5_hzip_set_local;
2071     db_hdf5_hzip_class.filter = db_hdf5_hzip_filter_op;
2072 
2073     H5Zregister(&db_hdf5_hzip_class);
2074     /* Initialize support data structures for hzip */
2075     memset(keptNodelistInfos, 0x0, sizeof(keptNodelistInfos));
2076 
2077 #endif
2078 
2079     /* Define compound data types */
2080     STRUCT(DBcurve) {
2081         MEMBER_S(int,           npts);
2082         MEMBER_S(int,           guihide);
2083         MEMBER_S(int,           coord_sys);
2084         MEMBER_S(str256,        xvarname);
2085         MEMBER_S(str256,        yvarname);
2086         MEMBER_S(str256,        label);
2087         MEMBER_S(str256,        xlabel);
2088         MEMBER_S(str256,        ylabel);
2089         MEMBER_S(str256,        xunits);
2090         MEMBER_S(str256,        yunits);
2091         MEMBER_S(str256,        reference);
2092         MEMBER_S(double,        missing_value);
2093     } DEFINE;
2094 
2095     STRUCT(DBcsgmesh) {
2096         MEMBER_S(int,           block_no);
2097         MEMBER_S(int,           group_no);
2098         MEMBER_S(int,           cycle);
2099         MEMBER_S(int,           nbounds);
2100         MEMBER_S(int,           lcoeffs);
2101         MEMBER_S(float,         time);
2102         MEMBER_S(double,        dtime);
2103         MEMBER_S(int,           ndims);
2104         MEMBER_S(int,           origin);
2105         MEMBER_3(double,        min_extents);
2106         MEMBER_3(double,        max_extents);
2107         MEMBER_S(int,           guihide);
2108         MEMBER_R(str256,        units, 3);
2109         MEMBER_R(str256,        labels, 3);
2110         MEMBER_S(str256,        name);
2111         MEMBER_S(str256,        typeflags);
2112         MEMBER_S(str256,        bndids);
2113         MEMBER_S(str256,        coeffs);
2114         MEMBER_S(str256,        zonel_name);
2115         MEMBER_S(str256,        bndnames);
2116         MEMBER_S(str256,        mrgtree_name);
2117         MEMBER_S(int,           tv_connectivity);
2118         MEMBER_S(int,           disjoint_mode);
2119         MEMBER_S(str256,        alt_nodenum_vars);
2120     } DEFINE;
2121 
2122     STRUCT(DBcsgvar) {
2123         MEMBER_S(int,           cycle);
2124         MEMBER_S(float,         time);
2125         MEMBER_S(double,        dtime);
2126         MEMBER_S(int,           datatype);
2127         MEMBER_S(int,           nels);
2128         MEMBER_S(int,           nvals);
2129         MEMBER_S(int,           centering);
2130         MEMBER_S(int,           use_specmf);
2131         MEMBER_S(int,           ascii_labels);
2132         MEMBER_S(int,           guihide);
2133         MEMBER_S(str256,        name);
2134         MEMBER_S(str256,        units);
2135         MEMBER_S(str256,        label);
2136         MEMBER_R(str256,        vals,           MAX_VARS);
2137         MEMBER_S(str256,        meshname);
2138         MEMBER_S(str256,        region_pnames);
2139         MEMBER_S(int,           conserved);
2140         MEMBER_S(int,           extensive);
2141         MEMBER_S(double,        missing_value);
2142     } DEFINE;
2143 
2144     STRUCT(DBcsgzonelist) {
2145         MEMBER_S(int,           nregs);
2146         MEMBER_S(int,           origin);
2147         MEMBER_S(int,           lxform);
2148         MEMBER_S(int,           datatype);
2149         MEMBER_S(int,           nzones);
2150         MEMBER_S(int,           min_index);
2151         MEMBER_S(int,           max_index);
2152         MEMBER_S(str256,        typeflags);
2153         MEMBER_S(str256,        leftids);
2154         MEMBER_S(str256,        rightids);
2155         MEMBER_S(str256,        xform);
2156         MEMBER_S(str256,        zonelist);
2157         MEMBER_S(str256,        regnames);
2158         MEMBER_S(str256,        zonenames);
2159         MEMBER_S(str256,        alt_zonenum_vars);
2160     } DEFINE;
2161 
2162     STRUCT(DBdefvars) {
2163         MEMBER_S(int,           ndefs);
2164         MEMBER_S(str256,        names);
2165         MEMBER_S(str256,        types);
2166         MEMBER_S(str256,        defns);
2167         MEMBER_S(str256,        guihides);
2168     } DEFINE;
2169 
2170     STRUCT(DBquadmesh) {
2171         MEMBER_R(str256,        coord,          3);
2172         MEMBER_3(double,        min_extents);
2173         MEMBER_3(double,        max_extents);
2174         MEMBER_S(int,           ndims);
2175         MEMBER_S(int,           coordtype);
2176         MEMBER_S(int,           nspace);
2177         MEMBER_S(int,           nnodes);
2178         MEMBER_S(int,           facetype);
2179         MEMBER_S(int,           major_order);
2180         MEMBER_S(int,           cycle);
2181         MEMBER_S(int,           coord_sys);
2182         MEMBER_S(int,           planar);
2183         MEMBER_S(int,           origin);
2184         MEMBER_S(int,           group_no);
2185         MEMBER_3(int,           dims);
2186         MEMBER_3(int,           min_index);
2187         MEMBER_3(int,           max_index);
2188         MEMBER_3(int,           baseindex);
2189         MEMBER_S(float,         time);
2190         MEMBER_S(double,        dtime);
2191         MEMBER_S(int,           guihide);
2192         MEMBER_R(str256,        label,          3);
2193         MEMBER_R(str256,        units,          3);
2194         MEMBER_S(str256,        mrgtree_name);
2195         MEMBER_S(str256,        ghost_node_labels);
2196         MEMBER_S(str256,        ghost_zone_labels);
2197         MEMBER_S(str256,        alt_nodenum_vars);
2198         MEMBER_S(str256,        alt_zonenum_vars);
2199     } DEFINE;
2200 
2201     STRUCT(DBquadvar) {
2202         MEMBER_R(str256,        value,          MAX_VARS);
2203         MEMBER_R(str256,        mixed_value,    MAX_VARS);
2204         MEMBER_S(str256,        meshid);
2205         MEMBER_S(int,           ndims);
2206         MEMBER_S(int,           nvals);
2207         MEMBER_S(int,           nels);
2208         MEMBER_S(int,           origin);
2209         MEMBER_S(int,           mixlen);
2210         MEMBER_S(int,           major_order);
2211         MEMBER_S(int,           datatype);
2212         MEMBER_S(int,           cycle);
2213         MEMBER_S(float,         time);
2214         MEMBER_S(double,        dtime);
2215         MEMBER_S(int,           use_specmf);
2216         MEMBER_S(int,           ascii_labels);
2217         MEMBER_3(int,           dims);
2218         MEMBER_3(int,           zones);
2219         MEMBER_3(int,           min_index);
2220         MEMBER_3(int,           max_index);
2221         MEMBER_3(float,         align);
2222         MEMBER_S(int,           guihide);
2223         MEMBER_S(str256,        label);
2224         MEMBER_S(str256,        units);
2225         MEMBER_S(str256,        region_pnames);
2226         MEMBER_S(int,           conserved);
2227         MEMBER_S(int,           extensive);
2228         MEMBER_S(int,           centering);
2229         MEMBER_S(double,        missing_value);
2230     } DEFINE;
2231 
2232     STRUCT(DBucdmesh) {
2233         MEMBER_R(str256,        coord,          3);
2234         MEMBER_S(int,           ndims);
2235         MEMBER_S(int,           nnodes);
2236         MEMBER_S(int,           nzones);
2237         MEMBER_S(int,           facetype);
2238         MEMBER_S(int,           cycle);
2239         MEMBER_S(int,           coord_sys);
2240         MEMBER_S(int,           topo_dim);
2241         MEMBER_S(int,           planar);
2242         MEMBER_S(int,           origin);
2243         MEMBER_S(int,           group_no);
2244         MEMBER_S(float,         time);
2245         MEMBER_S(double,        dtime);
2246         MEMBER_S(str256,        facelist);
2247         MEMBER_S(str256,        zonelist);
2248         MEMBER_S(str256,        phzonelist);
2249         MEMBER_S(str256,        gnodeno);
2250         MEMBER_3(double,        min_extents);
2251         MEMBER_3(double,        max_extents);
2252         MEMBER_S(int,           guihide);
2253         MEMBER_R(str256,        label,          3);
2254         MEMBER_R(str256,        units,          3);
2255         MEMBER_S(str256,        mrgtree_name);
2256         MEMBER_S(int,           tv_connectivity);
2257         MEMBER_S(int,           disjoint_mode);
2258         MEMBER_S(int,           gnznodtype);
2259         MEMBER_S(str256,        ghost_node_labels);
2260         MEMBER_S(str256,        alt_nodenum_vars);
2261     } DEFINE;
2262 
2263     STRUCT(DBucdvar) {
2264         MEMBER_R(str256,        value,          MAX_VARS);
2265         MEMBER_R(str256,        mixed_value,    MAX_VARS);
2266         MEMBER_S(str256,        meshid);
2267         MEMBER_S(int,           ndims);
2268         MEMBER_S(int,           nvals);
2269         MEMBER_S(int,           nels);
2270         MEMBER_S(int,           centering);
2271         MEMBER_S(int,           origin);
2272         MEMBER_S(int,           mixlen);
2273         MEMBER_S(int,           datatype);
2274         MEMBER_S(int,           cycle);
2275         MEMBER_S(int,           use_specmf);
2276         MEMBER_S(int,           ascii_labels);
2277         MEMBER_S(float,         time);
2278         MEMBER_S(double,        dtime);
2279         MEMBER_S(int,           lo_offset);
2280         MEMBER_S(int,           hi_offset);
2281         MEMBER_S(int,           guihide);
2282         MEMBER_S(str256,        label);
2283         MEMBER_S(str256,        units);
2284         MEMBER_S(str256,        region_pnames);
2285         MEMBER_S(int,           conserved);
2286         MEMBER_S(int,           extensive);
2287         MEMBER_S(double,        missing_value);
2288     } DEFINE;
2289 
2290     STRUCT(DBfacelist) {
2291         MEMBER_S(int,           ndims);
2292         MEMBER_S(int,           nfaces);
2293         MEMBER_S(int,           nshapes);
2294         MEMBER_S(int,           ntypes);
2295         MEMBER_S(int,           lnodelist);
2296         MEMBER_S(int,           origin);
2297         MEMBER_S(str256,        nodelist);
2298         MEMBER_S(str256,        shapecnt);
2299         MEMBER_S(str256,        shapesize);
2300         MEMBER_S(str256,        typelist);
2301         MEMBER_S(str256,        types);
2302         MEMBER_S(str256,        zoneno);
2303     } DEFINE;
2304 
2305     STRUCT(DBzonelist) {
2306         MEMBER_S(int,           ndims);
2307         MEMBER_S(int,           nzones);
2308         MEMBER_S(int,           nshapes);
2309         MEMBER_S(int,           lnodelist);
2310         MEMBER_S(int,           origin);
2311         MEMBER_S(int,           lo_offset);
2312         MEMBER_S(int,           hi_offset);
2313         MEMBER_S(str256,        nodelist);
2314         MEMBER_S(str256,        shapecnt);
2315         MEMBER_S(str256,        shapesize);
2316         MEMBER_S(str256,        shapetype);
2317         MEMBER_S(str256,        gzoneno);
2318         MEMBER_S(int,           gnznodtype);
2319         MEMBER_S(str256,        ghost_zone_labels);
2320         MEMBER_S(str256,        alt_zonenum_vars);
2321     } DEFINE;
2322 
2323     STRUCT(DBphzonelist) {
2324         MEMBER_S(int,           nfaces);
2325         MEMBER_S(int,           lnodelist);
2326         MEMBER_S(int,           nzones);
2327         MEMBER_S(int,           lfacelist);
2328         MEMBER_S(int,           origin);
2329         MEMBER_S(int,           lo_offset);
2330         MEMBER_S(int,           hi_offset);
2331         MEMBER_S(str256,        nodecnt);
2332         MEMBER_S(str256,        nodelist);
2333         MEMBER_S(str256,        extface);
2334         MEMBER_S(str256,        facecnt);
2335         MEMBER_S(str256,        facelist);
2336         MEMBER_S(int,           gnznodtype);
2337         MEMBER_S(str256,        ghost_zone_labels);
2338         MEMBER_S(str256,        alt_zonenum_vars);
2339     } DEFINE;
2340 
2341     STRUCT(DBmaterial) {
2342         MEMBER_S(int,           ndims);
2343         MEMBER_S(int,           nmat);
2344         MEMBER_S(int,           mixlen);
2345         MEMBER_S(int,           origin);
2346         MEMBER_S(int,           major_order);
2347         MEMBER_S(int,           datatype);
2348         MEMBER_3(int,           dims);
2349         MEMBER_S(int,           allowmat0);
2350         MEMBER_S(int,           guihide);
2351         MEMBER_S(str256,        meshid);
2352         MEMBER_S(str256,        matlist);
2353         MEMBER_S(str256,        matnos);
2354         MEMBER_S(str256,        mix_vf);
2355         MEMBER_S(str256,        mix_next);
2356         MEMBER_S(str256,        mix_mat);
2357         MEMBER_S(str256,        mix_zone);
2358         MEMBER_S(str256,        matnames);
2359         MEMBER_S(str256,        matcolors);
2360     } DEFINE;
2361 
2362     STRUCT(DBmultimesh) {
2363         MEMBER_S(int,           nblocks);
2364         MEMBER_S(int,           cycle);
2365         MEMBER_S(int,           ngroups);
2366         MEMBER_S(int,           blockorigin);
2367         MEMBER_S(int,           grouporigin);
2368         MEMBER_S(float,         time);
2369         MEMBER_S(double,        dtime);
2370         MEMBER_S(int,           extentssize);
2371         MEMBER_S(int,           guihide);
2372         MEMBER_S(str256,        meshtypes);
2373         MEMBER_S(str256,        meshnames);
2374         MEMBER_S(str256,        extents);
2375         MEMBER_S(str256,        zonecounts);
2376         MEMBER_S(str256,        has_external_zones);
2377         MEMBER_S(int,           lgroupings);
2378         MEMBER_S(str256,        groupings);
2379         MEMBER_S(str256,        groupnames);
2380         MEMBER_S(str256,        mrgtree_name);
2381         MEMBER_S(int,           tv_connectivity);
2382         MEMBER_S(int,           disjoint_mode);
2383         MEMBER_S(int,           topo_dim);
2384         MEMBER_S(str256,        file_ns_name);
2385         MEMBER_S(str256,        block_ns_name);
2386         MEMBER_S(int,           block_type);
2387         MEMBER_S(str256,        empty_list);
2388         MEMBER_S(int,           empty_cnt);
2389         MEMBER_S(int,           repr_block_idx);
2390         MEMBER_S(str256,        alt_nodenum_vars);
2391         MEMBER_S(str256,        alt_zonenum_vars);
2392     } DEFINE;
2393 
2394     STRUCT(DBmultimeshadj) {
2395         MEMBER_S(int,           nblocks);
2396         MEMBER_S(int,           blockorigin);
2397         MEMBER_S(int,           lneighbors);
2398         MEMBER_S(int,           totlnodelists);
2399         MEMBER_S(int,           totlzonelists);
2400         MEMBER_S(str256,        meshtypes);
2401         MEMBER_S(str256,        nneighbors);
2402         MEMBER_S(str256,        neighbors);
2403         MEMBER_S(str256,        back);
2404         MEMBER_S(str256,        lnodelists);
2405         MEMBER_S(str256,        nodelists);
2406         MEMBER_S(str256,        lzonelists);
2407         MEMBER_S(str256,        zonelists);
2408     } DEFINE;
2409 
2410     STRUCT(DBmultivar) {
2411         MEMBER_S(int,           nvars);
2412         MEMBER_S(int,           cycle);
2413         MEMBER_S(int,           ngroups);
2414         MEMBER_S(int,           blockorigin);
2415         MEMBER_S(int,           grouporigin);
2416         MEMBER_S(float,         time);
2417         MEMBER_S(double,        dtime);
2418         MEMBER_S(int,           extentssize);
2419         MEMBER_S(int,           guihide);
2420         MEMBER_S(str256,        vartypes);
2421         MEMBER_S(str256,        varnames);
2422         MEMBER_S(str256,        extents);
2423         MEMBER_S(str256,        region_pnames);
2424         MEMBER_S(str256,        mmesh_name);
2425         MEMBER_S(int,           tensor_rank);
2426         MEMBER_S(int,           conserved);
2427         MEMBER_S(int,           extensive);
2428         MEMBER_S(str256,        file_ns_name);
2429         MEMBER_S(str256,        block_ns_name);
2430         MEMBER_S(int,           block_type);
2431         MEMBER_S(str256,        empty_list);
2432         MEMBER_S(int,           empty_cnt);
2433         MEMBER_S(int,           repr_block_idx);
2434         MEMBER_S(double,        missing_value);
2435     } DEFINE;
2436 
2437     STRUCT(DBmultimat) {
2438         MEMBER_S(int,           nmats);
2439         MEMBER_S(int,           cycle);
2440         MEMBER_S(int,           ngroups);
2441         MEMBER_S(int,           blockorigin);
2442         MEMBER_S(int,           grouporigin);
2443         MEMBER_S(float,         time);
2444         MEMBER_S(double,        dtime);
2445         MEMBER_S(int,           allowmat0);
2446         MEMBER_S(int,           guihide);
2447         MEMBER_S(str256,        matnames);
2448         MEMBER_S(str256,        matnos);
2449         MEMBER_S(str256,        mixlens);
2450         MEMBER_S(str256,        matcounts);
2451         MEMBER_S(str256,        matlists);
2452         MEMBER_S(int,           nmatnos);
2453         MEMBER_S(str256,        material_names);
2454         MEMBER_S(str256,        mat_colors);
2455         MEMBER_S(str256,        mmesh_name);
2456         MEMBER_S(str256,        file_ns_name);
2457         MEMBER_S(str256,        block_ns_name);
2458         MEMBER_S(str256,        empty_list);
2459         MEMBER_S(int,           empty_cnt);
2460         MEMBER_S(int,           repr_block_idx);
2461     } DEFINE;
2462 
2463     STRUCT(DBmultimatspecies) {
2464         MEMBER_S(int,           nspec);
2465         MEMBER_S(int,           nmat);
2466         MEMBER_S(int,           cycle);
2467         MEMBER_S(int,           ngroups);
2468         MEMBER_S(int,           blockorigin);
2469         MEMBER_S(int,           grouporigin);
2470         MEMBER_S(float,         time);
2471         MEMBER_S(double,        dtime);
2472         MEMBER_S(int,           guihide);
2473         MEMBER_S(str256,        specnames);
2474         MEMBER_S(str256,        nmatspec);
2475         MEMBER_S(str256,        matname);
2476         MEMBER_S(str256,        species_names);
2477         MEMBER_S(str256,        speccolors);
2478         MEMBER_S(str256,        file_ns_name);
2479         MEMBER_S(str256,        block_ns_name);
2480         MEMBER_S(str256,        empty_list);
2481         MEMBER_S(int,           empty_cnt);
2482         MEMBER_S(int,           repr_block_idx);
2483     } DEFINE;
2484 
2485     STRUCT(DBmatspecies) {
2486         MEMBER_S(int,           ndims);
2487         MEMBER_S(int,           nmat);
2488         MEMBER_S(int,           nspecies_mf);
2489         MEMBER_S(int,           mixlen);
2490         MEMBER_S(int,           major_order);
2491         MEMBER_S(int,           datatype);
2492         MEMBER_3(int,           dims);
2493         MEMBER_S(int,           guihide);
2494         MEMBER_S(str256,        matname);
2495         MEMBER_S(str256,        speclist);
2496         MEMBER_S(str256,        nmatspec);
2497         MEMBER_S(str256,        species_mf);
2498         MEMBER_S(str256,        mix_speclist);
2499         MEMBER_S(str256,        specnames);
2500         MEMBER_S(str256,        speccolors);
2501     } DEFINE;
2502 
2503     STRUCT(DBpointmesh) {
2504         MEMBER_S(int,           ndims);
2505         MEMBER_S(int,           nspace);
2506         MEMBER_S(int,           nels);
2507         MEMBER_S(int,           cycle);
2508         MEMBER_S(int,           group_no);
2509         MEMBER_S(float,         time);
2510         MEMBER_S(double,        dtime);
2511         MEMBER_S(int,           origin);
2512         MEMBER_S(int,           min_index);
2513         MEMBER_S(int,           max_index);
2514         MEMBER_3(double,        min_extents);
2515         MEMBER_3(double,        max_extents);
2516         MEMBER_S(int,           guihide);
2517         MEMBER_R(str256,        coord,          3);
2518         MEMBER_R(str256,        label,          3);
2519         MEMBER_R(str256,        units,          3);
2520         MEMBER_S(str256,        gnodeno);
2521         MEMBER_S(str256,        mrgtree_name);
2522         MEMBER_S(int,           gnznodtype);
2523         MEMBER_S(str256,        ghost_node_labels);
2524         MEMBER_S(str256,        alt_nodenum_vars);
2525     } DEFINE;
2526 
2527     STRUCT(DBpointvar) {
2528         MEMBER_S(int,           nvals);
2529         MEMBER_S(int,           nels);
2530         MEMBER_S(int,           ndims);
2531         MEMBER_S(int,           nspace);
2532         MEMBER_S(int,           origin);
2533         MEMBER_S(int,           min_index);
2534         MEMBER_S(int,           max_index);
2535         MEMBER_S(int,           datatype);
2536         MEMBER_S(int,           cycle);
2537         MEMBER_S(float,         time);
2538         MEMBER_S(double,        dtime);
2539         MEMBER_S(int,           guihide);
2540         MEMBER_S(int,           ascii_labels);
2541         MEMBER_S(str256,        meshid);
2542         MEMBER_S(str256,        label);
2543         MEMBER_S(str256,        units);
2544         MEMBER_R(str256,        data,           MAX_VARS);
2545         MEMBER_S(str256,        region_pnames);
2546         MEMBER_S(int,           conserved);
2547         MEMBER_S(int,           extensive);
2548         MEMBER_S(double,        missing_value);
2549     } DEFINE;
2550 
2551     STRUCT(DBcompoundarray) {
2552         MEMBER_S(int,           nelems);
2553         MEMBER_S(int,           nvalues);
2554         MEMBER_S(int,           datatype);
2555         MEMBER_S(str256,        values);
2556         MEMBER_S(str256,        elemnames);
2557         MEMBER_S(str256,        elemlengths);
2558     } DEFINE;
2559 
2560     STRUCT(DBmrgtree) {
2561         MEMBER_S(int,           src_mesh_type);
2562         MEMBER_S(int,           type_info_bits);
2563         MEMBER_S(int,           num_nodes);
2564         MEMBER_S(int,           root);
2565         MEMBER_S(str256,        src_mesh_name);
2566 
2567         MEMBER_S(str256,        n_scalars);
2568         MEMBER_S(str256,        n_name);
2569         MEMBER_S(str256,        n_names);
2570         MEMBER_S(str256,        n_maps_name);
2571         MEMBER_S(str256,        n_seg_ids);
2572         MEMBER_S(str256,        n_seg_lens);
2573         MEMBER_S(str256,        n_seg_types);
2574         MEMBER_S(str256,        n_children);
2575 
2576         MEMBER_S(str256,        mrgvar_onames);
2577         MEMBER_S(str256,        mrgvar_rnames);
2578     } DEFINE;
2579 
2580     STRUCT(DBgroupelmap) {
2581         MEMBER_S(int,           num_segments);
2582         MEMBER_S(int,           fracs_data_type);
2583         MEMBER_S(str256,        groupel_types);
2584         MEMBER_S(str256,        segment_lengths);
2585         MEMBER_S(str256,        segment_ids);
2586         MEMBER_S(str256,        segment_data);
2587         MEMBER_S(str256,        frac_lengths);
2588         MEMBER_S(str256,        segment_fracs);
2589     } DEFINE;
2590 
2591     STRUCT(DBmrgvar) {
2592         MEMBER_S(int,           nregns);
2593         MEMBER_S(int,           ncomps);
2594         MEMBER_S(int,           datatype);
2595         MEMBER_S(str256,        mrgt_name);
2596         MEMBER_S(str256,        reg_pnames);
2597         MEMBER_S(str256,        compnames);
2598         MEMBER_R(str256,        data,          MAX_VARS);
2599     } DEFINE;
2600 
2601 }
2602 
2603 /*-------------------------------------------------------------------------
2604  * Function:    db_hdf5_InitCallbacks
2605  *
2606  * Purpose:     Initialize the callbacks in a DBfile structure.
2607  *
2608  * Return:      void
2609  *
2610  * Programmer:  Robb Matzke
2611  *              Thursday, February 11, 1999
2612  *
2613  * Modifications:
2614  *
2615  *    Jeremy Meredith, Wed Oct 25 16:16:59 PDT 2000
2616  *    Added DB_INTEL so we had a little-endian target.
2617  *
2618  *    Mark C. Miller, Tue Feb  3 09:47:43 PST 2009
2619  *    Changed dbfile arg from public DBfile* to private DBfile_hdf5*
2620  *
2621  *    Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
2622  *    Adding support for long long type.
2623  *-------------------------------------------------------------------------
2624  */
2625 PRIVATE void
db_hdf5_InitCallbacks(DBfile_hdf5 * dbfile,int target)2626 db_hdf5_InitCallbacks(DBfile_hdf5 *dbfile, int target)
2627 {
2628     static char         *me = "db_hdf5_InitCallbacks";
2629 
2630     /* Initialize the driver global data structures */
2631     db_hdf5_init();
2632 
2633     /* Target data types */
2634     switch (target) {
2635     case DB_LOCAL:
2636         dbfile->T_char   = T_char;
2637         dbfile->T_short  = T_short;
2638         dbfile->T_int    = T_int;
2639         dbfile->T_long   = T_long;
2640         dbfile->T_llong  = T_llong;
2641         dbfile->T_float  = T_float;
2642         dbfile->T_double = T_double;
2643         dbfile->T_str    = T_str;
2644         break;
2645 
2646     case DB_SGI:
2647     case DB_SUN3:
2648     case DB_SUN4:
2649     case DB_RS6000:
2650         dbfile->T_char   = H5T_STD_I8BE;
2651         dbfile->T_short  = H5T_STD_I16BE;
2652         dbfile->T_int    = H5T_STD_I32BE;
2653         dbfile->T_long   = H5T_STD_I32BE;
2654         dbfile->T_llong  = H5T_STD_I64BE;
2655         dbfile->T_float  = H5T_IEEE_F32BE;
2656         dbfile->T_double = H5T_IEEE_F64BE;
2657         dbfile->T_str    = T_str;
2658         break;
2659 
2660     case DB_CRAY:
2661         dbfile->T_char   = H5T_STD_I8BE;
2662         dbfile->T_short  = H5T_STD_I64BE;
2663         dbfile->T_int    = H5T_STD_I64BE;
2664         dbfile->T_long   = H5T_STD_I64BE;
2665         dbfile->T_llong  = H5T_STD_I64BE;
2666         dbfile->T_float  = H5T_IEEE_F64BE; /*assuming new cray*/
2667         dbfile->T_double = H5T_IEEE_F64BE; /*assuming new cray*/
2668         dbfile->T_str    = T_str;
2669         break;
2670 
2671     case DB_INTEL:
2672         dbfile->T_char   = H5T_STD_I8LE;
2673         dbfile->T_short  = H5T_STD_I16LE;
2674         dbfile->T_int    = H5T_STD_I32LE;
2675         dbfile->T_long   = H5T_STD_I32LE;
2676         dbfile->T_llong  = H5T_STD_I64LE;
2677         dbfile->T_float  = H5T_IEEE_F32LE;
2678         dbfile->T_double = H5T_IEEE_F64LE;
2679         dbfile->T_str    = T_str;
2680         break;
2681 
2682     default:
2683         db_perror("target data type", E_BADARGS, me);
2684         return;
2685     }
2686 
2687     /* Properties of the driver */
2688     dbfile->pub.pathok = TRUE;
2689     dbfile->pub.Grab = FALSE;
2690 
2691     /* File operations */
2692     dbfile->pub.close = db_hdf5_Close;
2693     dbfile->pub.module = db_hdf5_Filters;
2694 
2695     /* Directory operations */
2696     dbfile->pub.cd = db_hdf5_SetDir;
2697     dbfile->pub.g_dir = db_hdf5_GetDir;
2698     dbfile->pub.newtoc = db_hdf5_NewToc;
2699     dbfile->pub.mkdir = db_hdf5_MkDir;
2700     dbfile->pub.cpdir = db_hdf5_CpDir;
2701 
2702     /* Variable inquiries */
2703     dbfile->pub.exist = db_hdf5_InqVarExists;
2704     dbfile->pub.g_varlen = db_hdf5_GetVarLength;
2705     dbfile->pub.g_varbl = db_hdf5_GetVarByteLength;
2706     dbfile->pub.g_vartype = db_hdf5_GetVarType;
2707     dbfile->pub.g_vardims = db_hdf5_GetVarDims;
2708 
2709     /* Variable I/O operations */
2710     dbfile->pub.g_var = db_hdf5_GetVar;
2711     dbfile->pub.r_var = db_hdf5_ReadVar;
2712     dbfile->pub.r_varslice = db_hdf5_ReadVarSlice;
2713     dbfile->pub.write = db_hdf5_Write;
2714     dbfile->pub.writeslice = db_hdf5_WriteSlice;
2715 
2716     /* Low-level object functions */
2717     dbfile->pub.g_obj = db_hdf5_GetObject;
2718     dbfile->pub.inqvartype = db_hdf5_InqVarType;
2719     dbfile->pub.i_meshtype = (int (*)(struct DBfile *, char const *)) db_hdf5_InqVarType; /*yes, Vartype*/
2720     dbfile->pub.i_meshname = db_hdf5_InqMeshName;
2721     dbfile->pub.g_comp = db_hdf5_GetComponent;
2722     dbfile->pub.g_comptyp = db_hdf5_GetComponentType;
2723     dbfile->pub.g_compnames = db_hdf5_GetComponentNames;
2724     dbfile->pub.c_obj = db_hdf5_WriteObject; /*DBChangeObject==DBWriteObject*/
2725     dbfile->pub.w_obj = db_hdf5_WriteObject;
2726     dbfile->pub.w_comp = db_hdf5_WriteComponent;
2727 
2728     /* Curve functions */
2729     dbfile->pub.g_cu = db_hdf5_GetCurve;
2730     dbfile->pub.p_cu = db_hdf5_PutCurve;
2731 
2732     /* CSG mesh functions */
2733     dbfile->pub.p_csgm = db_hdf5_PutCsgmesh;
2734     dbfile->pub.g_csgm = db_hdf5_GetCsgmesh;
2735     dbfile->pub.p_csgzl = db_hdf5_PutCSGZonelist;
2736     dbfile->pub.g_csgzl = db_hdf5_GetCSGZonelist;
2737     dbfile->pub.p_csgv = db_hdf5_PutCsgvar;
2738     dbfile->pub.g_csgv = db_hdf5_GetCsgvar;
2739 
2740     /* Defvars functions */
2741     dbfile->pub.g_defv = db_hdf5_GetDefvars;
2742     dbfile->pub.p_defv = db_hdf5_PutDefvars;
2743 
2744     /* Quadmesh functions */
2745     dbfile->pub.g_qm = db_hdf5_GetQuadmesh;
2746     dbfile->pub.g_qv = db_hdf5_GetQuadvar;
2747     dbfile->pub.p_qm = db_hdf5_PutQuadmesh;
2748     dbfile->pub.p_qv = db_hdf5_PutQuadvar;
2749 
2750     /* Unstructured mesh functions */
2751     dbfile->pub.g_um = db_hdf5_GetUcdmesh;
2752     dbfile->pub.g_uv = db_hdf5_GetUcdvar;
2753     dbfile->pub.g_fl = db_hdf5_GetFacelist;
2754     dbfile->pub.g_zl = db_hdf5_GetZonelist;
2755     dbfile->pub.g_phzl = db_hdf5_GetPHZonelist;
2756     dbfile->pub.p_um = db_hdf5_PutUcdmesh;
2757     dbfile->pub.p_sm = db_hdf5_PutUcdsubmesh;
2758     dbfile->pub.p_uv = db_hdf5_PutUcdvar;
2759     dbfile->pub.p_fl = db_hdf5_PutFacelist;
2760     dbfile->pub.p_zl = db_hdf5_PutZonelist;
2761     dbfile->pub.p_zl2 = db_hdf5_PutZonelist2;
2762     dbfile->pub.p_phzl = db_hdf5_PutPHZonelist;
2763 
2764     /* Material functions */
2765     dbfile->pub.g_ma = db_hdf5_GetMaterial;
2766     dbfile->pub.g_ms = db_hdf5_GetMatspecies;
2767     dbfile->pub.p_ma = db_hdf5_PutMaterial;
2768     dbfile->pub.p_ms = db_hdf5_PutMatspecies;
2769 
2770     /* Pointmesh functions */
2771     dbfile->pub.g_pm = db_hdf5_GetPointmesh;
2772     dbfile->pub.g_pv = db_hdf5_GetPointvar;
2773     dbfile->pub.p_pm = db_hdf5_PutPointmesh;
2774     dbfile->pub.p_pv = db_hdf5_PutPointvar;
2775 
2776     /* Multiblock functions */
2777     dbfile->pub.g_mm = db_hdf5_GetMultimesh;
2778     dbfile->pub.g_mmadj = db_hdf5_GetMultimeshadj;
2779     dbfile->pub.g_mv = db_hdf5_GetMultivar;
2780     dbfile->pub.g_mt = db_hdf5_GetMultimat;
2781     dbfile->pub.g_mms = db_hdf5_GetMultimatspecies;
2782     dbfile->pub.p_mm = db_hdf5_PutMultimesh;
2783     dbfile->pub.p_mmadj = db_hdf5_PutMultimeshadj;
2784     dbfile->pub.p_mv = db_hdf5_PutMultivar;
2785     dbfile->pub.p_mt = db_hdf5_PutMultimat;
2786     dbfile->pub.p_mms = db_hdf5_PutMultimatspecies;
2787 
2788     /* Compound arrays */
2789     dbfile->pub.g_ca = db_hdf5_GetCompoundarray;
2790     dbfile->pub.p_ca = db_hdf5_PutCompoundarray;
2791 
2792     /* Mrgtree functions */
2793     dbfile->pub.g_mrgt = db_hdf5_GetMrgtree;
2794     dbfile->pub.p_mrgt = db_hdf5_PutMrgtree;
2795 
2796     /* Groupel map functions */
2797     dbfile->pub.g_grplm = db_hdf5_GetGroupelmap;
2798     dbfile->pub.p_grplm = db_hdf5_PutGroupelmap;
2799 
2800     /* mrgvar functions */
2801     dbfile->pub.g_mrgv = db_hdf5_GetMrgvar;
2802     dbfile->pub.p_mrgv = db_hdf5_PutMrgvar;
2803 
2804     /* Compression support functions */
2805     dbfile->pub.free_z = db_hdf5_FreeCompressionResources;
2806 
2807     dbfile->pub.sort_obo = db_hdf5_SortObjectsByOffset;
2808 }
2809 
2810 /*-------------------------------------------------------------------------
2811  * Function:    build_fspace
2812  *
2813  * Purpose:     Build a file data space selection based on the silo OFFSET,
2814  *              LENGTH, and STRIDE. The COUNT for hdf5 hyperslabs is the
2815  *              number of times to stride whereas the LENGTH argument
2816  *              passed in is the number of elements over which we stride.
2817  *              An example:
2818  *
2819  *                0 1 2 3 4 5 6 7 8 9 10
2820  *               +-+-+-+-+-+-+-+-+-+-+-+  Silo: offset=2, stride=2, length=7
2821  *               | | |X| |X| |X| |X| | |  HDF5: offset=2, stride=2, count=4
2822  *               +-+-+-+-+-+-+-+-+-+-+-+
2823  *
2824  * Return:      Success:        Data space to be closed later. If SIZE is
2825  *                              non-null then the number of elements selected
2826  *                              in each dimension is written to that array.
2827  *
2828  *              Failure:        Negative, SIZE is undefined.
2829  *
2830  * Programmer:  Robb Matzke
2831  *              Thursday, February 11, 1999
2832  *
2833  * Modifications:
2834  *    Thomas R. Treadway, Wed Mar  7 09:59:27 PST 2007
2835  *    Changed hs_offset from hssize_t to hsize_t
2836  *
2837  *
2838  *-------------------------------------------------------------------------
2839  */
2840 PRIVATE hid_t
build_fspace(hid_t dset,int ndims,int const * offset,int const * length,int const * stride,hsize_t * size)2841 build_fspace(hid_t dset, int ndims, int const *offset, int const *length, int const *stride,
2842              hsize_t *size/*out*/)
2843 {
2844     hid_t       fspace = -1;
2845     int         i;
2846     hsize_t    hs_offset[H5S_MAX_RANK];
2847     hsize_t     hs_count[H5S_MAX_RANK], hs_stride[H5S_MAX_RANK];
2848 
2849     if (ndims>H5S_MAX_RANK) return -1;
2850     for (i=0; i<ndims; i++) {
2851         hs_offset[i] = offset[i];
2852         hs_stride[i] = stride[i];
2853 
2854         if (stride[i]) {
2855             hs_count[i] = (length[i]+stride[i]-1)/stride[i];
2856         } else {
2857             hs_count[i] = 1;
2858         }
2859         if (size) size[i] = hs_count[i];
2860     }
2861 
2862     if ((fspace=H5Dget_space(dset))<0) return -1;
2863     if (H5Sselect_hyperslab(fspace, H5S_SELECT_SET, hs_offset, hs_stride,
2864                             hs_count, NULL)<0) {
2865         H5Sclose(fspace);
2866         return -1;
2867     }
2868     return fspace;
2869 }
2870 
2871 /*-------------------------------------------------------------------------
2872  * Function:    silom2hdfm_type
2873  *
2874  * Purpose:     Return the hdf5 data type for memory that is equivalent to
2875  *              the specified silo memory data type.
2876  *
2877  * Return:      Success:        An hdf5 data type. Do not close it (well, if
2878  *                              you must, but you'll get an error from hdf5).
2879  *
2880  *              Failure:        Negative
2881  *
2882  * Programmer:  Robb Matzke
2883  *              Thursday, February 11, 1999
2884  *
2885  * Modifications:
2886  *
2887  *   Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
2888  *   Adding support for long long type.
2889  *
2890  *   Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
2891  *   Conditionally compile long long support only when its
2892  *   different from long.
2893  *
2894  *   Mark C. Miller, Mon Jan 11 16:02:16 PST 2010
2895  *   Made long long support UNconditionally compiled.
2896  *-------------------------------------------------------------------------
2897  */
2898 PRIVATE hid_t
silom2hdfm_type(int datatype)2899 silom2hdfm_type(int datatype)
2900 {
2901     hid_t       mtype = -1;
2902 
2903     switch (datatype) {
2904     case DB_INT:
2905         mtype = H5T_NATIVE_INT;
2906         break;
2907     case DB_SHORT:
2908         mtype = H5T_NATIVE_SHORT;
2909         break;
2910     case DB_LONG:
2911         mtype = H5T_NATIVE_LONG;
2912         break;
2913     case DB_LONG_LONG:
2914         mtype = H5T_NATIVE_LLONG;
2915         break;
2916     case DB_FLOAT:
2917         mtype = H5T_NATIVE_FLOAT;
2918         break;
2919     case DB_DOUBLE:
2920         mtype = H5T_NATIVE_DOUBLE;
2921         break;
2922     case DB_CHAR:
2923         mtype = H5T_NATIVE_UCHAR;
2924         break;
2925     }
2926     return mtype;
2927 }
2928 
2929 /*-------------------------------------------------------------------------
2930  * Function:    silof2hdff_type
2931  *
2932  * Purpose:     Return the hdf5 data type for the file that is equivalent to
2933  *              the specified silo file data type.
2934  *
2935  * Return:      Success:        An hdf5 data type. Do not close this type.
2936  *
2937  *              Failure:        Negative
2938  *
2939  * Programmer:  Robb Matzke
2940  *              Thursday, April 15, 1999
2941  *
2942  * Modifications:
2943  *
2944  *   Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
2945  *   Adding support for long long type.
2946  *
2947  *   Mark C. Miller, Mon Dec  7 09:50:19 PST 2009
2948  *   Conditionally compile long long support only when its
2949  *   different from long.
2950  *
2951  *   Mark C. Miller, Mon Jan 11 16:02:16 PST 2010
2952  *   Made long long support UNconditionally compiled.
2953  *-------------------------------------------------------------------------
2954  */
2955 PRIVATE hid_t
silof2hdff_type(DBfile_hdf5 * dbfile,int datatype)2956 silof2hdff_type(DBfile_hdf5 *dbfile, int datatype)
2957 {
2958     hid_t       ftype = -1;
2959 
2960     switch (datatype) {
2961     case DB_INT:
2962         ftype = dbfile->T_int;
2963         break;
2964     case DB_SHORT:
2965         ftype = dbfile->T_short;
2966         break;
2967     case DB_LONG:
2968         ftype = dbfile->T_long;
2969         break;
2970     case DB_LONG_LONG:
2971         ftype = dbfile->T_llong;
2972         break;
2973     case DB_FLOAT:
2974         ftype = dbfile->T_float;
2975         break;
2976     case DB_DOUBLE:
2977         ftype = dbfile->T_double;
2978         break;
2979     case DB_CHAR:
2980         ftype = dbfile->T_char;
2981         break;
2982     }
2983     return ftype;
2984 }
2985 
2986 /*-------------------------------------------------------------------------
2987  * Function:    hdf2silo_type
2988  *
2989  * Purpose:     Given an HDF5 file data type return and appropriate memory
2990  *              silo data type.
2991  *
2992  * Return:      Success:        Silo data type
2993  *
2994  *              Failure:        -1
2995  *
2996  * Programmer:  Robb Matzke
2997  *              Monday, April 12, 1999
2998  *
2999  * Modifications:
3000  *
3001  *   Mark C. Miler, made it return DB_FLOAT or DB_DOUBLE based on
3002  *   data type passed in and NOT on current forceSingle mode
3003  *
3004  *   Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
3005  *   Adding support for long long type.
3006  *-------------------------------------------------------------------------
3007  */
3008 PRIVATE int
hdf2silo_type(hid_t type)3009 hdf2silo_type(hid_t type)
3010 {
3011     size_t      size = H5Tget_size(type);
3012     int         retval = -1;
3013 
3014     switch (H5Tget_class(type)) {
3015     case H5T_INTEGER:
3016         if (sizeof(char)>=size) {
3017             retval = DB_CHAR;
3018         } else if (sizeof(int)!=sizeof(short) && sizeof(short)>=size) {
3019             retval = DB_SHORT;
3020         } else if (sizeof(int)>=size) {
3021             retval = DB_INT;
3022         } else if (sizeof(long)>=size) {
3023             retval = DB_LONG;
3024         } else {
3025             retval = DB_LONG_LONG;
3026         }
3027         break;
3028 
3029     case H5T_FLOAT:
3030         if (sizeof(double)!=sizeof(float) && sizeof(float)>=size) {
3031             retval = DB_FLOAT;
3032         } else if (sizeof(double)>=size) {
3033             retval = DB_DOUBLE;
3034         }
3035         break;
3036 
3037     default:
3038         /* Silo doesn't handle other types */
3039         break;
3040     }
3041     return retval;
3042 }
3043 
3044 /*-------------------------------------------------------------------------
3045  * Function:    silo2silo_type
3046  *
3047  * Purpose:     Translate a file silo data type to a memory silo data type.
3048  *              If the file data type is zero then we use either DB_FLOAT or
3049  *              DB_DOUBLE.
3050  *
3051  * Return:      Success:        silo data type
3052  *
3053  *              Failure:        never fails
3054  *
3055  * Programmer:  Robb Matzke
3056  *              Monday, April 12, 1999
3057  *
3058  * Modifications:
3059  *
3060  *-------------------------------------------------------------------------
3061  */
3062 PRIVATE int
silo2silo_type(int datatype)3063 silo2silo_type(int datatype)
3064 {
3065     switch (datatype) {
3066     case 0: return force_single_g ? DB_FLOAT : DB_DOUBLE;
3067     case DB_CHAR: return DB_CHAR;
3068     case DB_SHORT: return DB_SHORT;
3069     case DB_INT: return DB_INT;
3070     case DB_LONG: return DB_LONG;
3071     case DB_LONG_LONG: return DB_LONG_LONG;
3072     case DB_FLOAT: return DB_FLOAT;
3073     case DB_DOUBLE: return force_single_g ? DB_FLOAT : DB_DOUBLE;
3074     }
3075     return DB_FLOAT;
3076 }
3077 
3078 /*-------------------------------------------------------------------------
3079  * Function:    hdf2hdf_type
3080  *
3081  * Purpose:     Given a file data type choose an appropriate memory data
3082  *              type.
3083  *
3084  * Return:      Success:        Memory data type which should not be closed
3085  *                              later (well, if you must, but hdf5 will
3086  *                              report an error).
3087  *
3088  *              Failure:        Negative
3089  *
3090  * Programmer:  Robb Matzke
3091  *              Thursday, February 11, 1999
3092  *
3093  * Modifications:
3094  *
3095  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
3096  *   Made it return NATIVE_FLOAT or NATIVE_DOUBLE NOT depending on
3097  *   current force_single_g mode
3098  *
3099  *   Mark C. Miller, Mon Sep 21 15:17:08 PDT 2009
3100  *   Adding support for long long type.
3101  *-------------------------------------------------------------------------
3102  */
3103 PRIVATE hid_t
hdf2hdf_type(hid_t ftype)3104 hdf2hdf_type(hid_t ftype)
3105 {
3106     hid_t       mtype=-1;
3107 
3108     switch (H5Tget_class(ftype)) {
3109     case H5T_INTEGER:
3110         if (sizeof(char)>=H5Tget_size(ftype)) {
3111             mtype = H5T_NATIVE_UCHAR;
3112         } else if (sizeof(short)>=H5Tget_size(ftype)) {
3113             mtype = H5T_NATIVE_SHORT;
3114         } else if (sizeof(int)>=H5Tget_size(ftype)) {
3115             mtype = H5T_NATIVE_INT;
3116         } else if (sizeof(long)>=H5Tget_size(ftype)) {
3117             mtype = H5T_NATIVE_LONG;
3118         } else {
3119             mtype = H5T_NATIVE_LLONG;
3120         }
3121         break;
3122     case H5T_FLOAT:
3123         if (sizeof(double)!=sizeof(float) && sizeof(float)>=H5Tget_size(ftype)) {
3124             mtype = H5T_NATIVE_FLOAT;
3125         } else if (sizeof(double)>=H5Tget_size(ftype)) {
3126             mtype = H5T_NATIVE_DOUBLE;
3127         } else {
3128             mtype = H5T_NATIVE_FLOAT;
3129         }
3130         break;
3131     default:
3132         break;
3133     }
3134     return mtype;
3135 }
3136 
3137 /*-------------------------------------------------------------------------
3138  * Function:    db_hdf5_set_compression
3139  *
3140  * Purpose:     Set the HDF5 compression properties.
3141  *
3142  * Bugs:
3143  *
3144  * Return:      Success:        0
3145  *
3146  *              Failure:        -1
3147  *
3148  * Programmer:  Thomas R. Treadway, Tue Feb 27 15:27:11 PST 2007
3149  *
3150  * Modifications:
3151  *
3152  *   Mark C. Miller, Thu Jul 17 15:00:46 PDT 2008
3153  *   Added globals for minimum compression ratio and error mode.
3154  *   Added support for HZIP and FPZIP. Added flags to control whether
3155  *   HZIP compression filter gets added or not.
3156  *-------------------------------------------------------------------------
3157  */
3158 PRIVATE int
db_hdf5_set_compression(int flags)3159 db_hdf5_set_compression(int flags)
3160 {
3161     static char *me = "db_hdf5_set_compression";
3162     char *ptr;
3163     char chararray[32];
3164     char *check;
3165     int level, block, nfilters;
3166     int nbits, prec;
3167     int have_gzip, have_szip, have_fpzip, have_hzip, i;
3168     H5Z_filter_t filtn;
3169     unsigned int filter_config_flags;
3170 /* Check what filters already exist */
3171     have_gzip = FALSE;
3172     have_szip = FALSE;
3173     have_fpzip = FALSE;
3174     have_hzip = FALSE;
3175     if ((nfilters = H5Pget_nfilters(P_ckcrprops))<0)
3176     {
3177        db_perror("H5Pget_nfilters", E_CALLFAIL, me);
3178        return (-1);
3179     }
3180     for (i=0; i<nfilters; i++) {
3181 #if defined H5_USE_16_API || (H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8)
3182             filtn = H5Pget_filter(P_ckcrprops,(unsigned)i,0,0,0,0,0);
3183 #else
3184             filtn = H5Pget_filter(P_ckcrprops,(unsigned)i,0,0,0,0,0,NULL);
3185 #endif
3186         if (H5Z_FILTER_DEFLATE==filtn)
3187             have_gzip = TRUE;
3188         if (H5Z_FILTER_SZIP==filtn)
3189             have_szip = TRUE;
3190         if (DB_HDF5_FPZIP_ID==filtn)
3191             have_fpzip = TRUE;
3192         if (DB_HDF5_HZIP_ID==filtn)
3193             have_hzip = TRUE;
3194     }
3195 /* Handle some global compression parameters */
3196     if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3197        "ERRMODE=")) != (char *)NULL)
3198     {
3199         (void)strncpy(chararray, ptr+8, 4);
3200         chararray[4] = '\0';
3201         if (strcmp(chararray, "FALL") == 0)
3202             SILO_Globals.compressionErrmode = COMPRESSION_ERRMODE_FALLBACK;
3203         else if (strcmp(chararray, "FAIL") == 0)
3204             SILO_Globals.compressionErrmode = COMPRESSION_ERRMODE_FAIL;
3205         else
3206         {
3207             db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3208             return (-1);
3209         }
3210     }
3211     if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3212        "MINRATIO=")) != (char *)NULL)
3213     {
3214         float mcr;
3215         (void)strncpy(chararray, ptr+9, 5);
3216         mcr = (float) strtod(chararray, &check);
3217         if (mcr > 1.0)
3218             SILO_Globals.compressionMinratio = mcr;
3219         else
3220         {
3221             db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3222             return (-1);
3223         }
3224     }
3225 
3226 /* Select the compression algorthm */
3227     if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3228        "METHOD=GZIP")) != (char *)NULL)
3229     {
3230        if (have_gzip == FALSE)
3231        {
3232           if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3233              "LEVEL=")) != (char *)NULL)
3234           {
3235              (void)strncpy(chararray, ptr+6, 1);
3236              level = (int) strtol(chararray, &check, 10);
3237              if ((chararray != check) && (level >= 0) && (level <=9))
3238              {
3239                 if (H5Pset_shuffle(P_ckcrprops)<0 ||
3240                     H5Pset_deflate(P_ckcrprops, level)<0)
3241                 {
3242                    db_perror("H5Pset_deflate", E_CALLFAIL, me);
3243                    return (-1);
3244                 }
3245              }
3246              else
3247              {
3248                 db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3249                 return (-1);
3250              }
3251           }
3252           else
3253           {
3254              if (H5Pset_shuffle(P_ckcrprops)<0 ||
3255                  H5Pset_deflate(P_ckcrprops, 1)<0)
3256              {
3257                 db_perror("H5Pset_deflate", E_CALLFAIL, me);
3258                 return (-1);
3259              }
3260           }
3261        }  /* if (have_gzip == FALSE) */
3262     }
3263 #ifdef H5_HAVE_FILTER_SZIP
3264     else if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3265        "METHOD=SZIP"))!=(char *)NULL)
3266     {
3267        if (have_szip == FALSE)
3268        {
3269           filtn = H5Z_FILTER_SZIP;
3270           if (H5Zget_filter_info(filtn, &filter_config_flags)<0)
3271           {
3272              db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3273              return (-1);
3274           }
3275           if ((filter_config_flags &
3276           (H5Z_FILTER_CONFIG_ENCODE_ENABLED|H5Z_FILTER_CONFIG_DECODE_ENABLED))==
3277           (H5Z_FILTER_CONFIG_ENCODE_ENABLED|H5Z_FILTER_CONFIG_DECODE_ENABLED))
3278           {
3279              if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3280                 "BLOCK=")) != (char *)NULL)
3281              {
3282                 (void)strncpy(chararray, ptr+6, 2);
3283                 block = (int) strtol(chararray, &check, 10);
3284                 if ((chararray != check) && (block >= 0) && (block <=32))
3285                 {
3286                    if (strstr(SILO_Globals.compressionParams,
3287                       "MASK=EC") != NULL)
3288                    {
3289                       if (H5Pset_shuffle(P_ckcrprops)<0 ||
3290                           H5Pset_szip(P_ckcrprops, H5_SZIP_EC_OPTION_MASK,block)<0)
3291                       {
3292                          db_perror("H5Pset_szip", E_CALLFAIL, me);
3293                          return (-1);
3294                       }
3295                    }
3296                    else if(strstr(SILO_Globals.compressionParams,
3297                       "MASK=NN")!=NULL)
3298                    {
3299                       if (H5Pset_shuffle(P_ckcrprops)<0 ||
3300                           H5Pset_szip(P_ckcrprops, H5_SZIP_NN_OPTION_MASK,block)<0)
3301                       {
3302                          db_perror("H5Pset_szip", E_CALLFAIL, me);
3303                          return (-1);
3304                       }
3305                    }
3306                    else
3307                    {
3308                       if (H5Pset_shuffle(P_ckcrprops)<0 ||
3309                           H5Pset_szip(P_ckcrprops, H5_SZIP_NN_OPTION_MASK, block)<0)
3310                       {
3311                          db_perror("H5Pset_szip", E_CALLFAIL, me);
3312                          return (-1);
3313                       }
3314                    }
3315                 }
3316                 else
3317                 {
3318                    db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3319                    return (-1);
3320                 }
3321              }
3322              else
3323              {
3324                 if (H5Pset_shuffle(P_ckcrprops)<0 ||
3325                     H5Pset_szip(P_ckcrprops, H5_SZIP_NN_OPTION_MASK, 4)<0)
3326                 {
3327                    db_perror("H5Pset_szip", E_CALLFAIL, me);
3328                    return (-1);
3329                 }
3330              }
3331           }  /* if ((filter_config_flags & */
3332        }  /* if (have_szip == FALSE) */
3333     }
3334 #endif
3335 #ifdef HAVE_HZIP
3336     else if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3337        "METHOD=HZIP")) != (char *)NULL)
3338     {
3339        if (have_hzip == FALSE && (flags & ALLOW_MESH_COMPRESSION))
3340        {
3341            if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3342               "CODEC=")) != (char *)NULL)
3343            {
3344               (void)strncpy(chararray, ptr+6, 4);
3345               chararray[4] = '\0';
3346 #ifdef HAVE_LIBZ
3347               if (strcmp(chararray, "zlib") == 0)
3348               {
3349                   db_hdf5_hzip_params.codec = HZM_CODEC_ZLIB;
3350                   db_hdf5_hzip_params.params = &hzm_codec_zlib;
3351               }
3352               else
3353 #endif
3354               if (strcmp(chararray, "base") == 0)
3355               {
3356                   db_hdf5_hzip_params.codec = HZM_CODEC_BASE;
3357                   db_hdf5_hzip_params.params = &hzm_codec_base;
3358               }
3359               else
3360               {
3361                   db_perror("hzip codec not recongized", E_COMPRESSION, me);
3362                   return (-1);
3363               }
3364            }
3365            if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3366               "BITS=")) != (char *)NULL)
3367            {
3368               (void)strncpy(chararray, ptr+5, 2);
3369               nbits = (int) strtol(chararray, &check, 10);
3370               if ((chararray != check) && (nbits >= 0) && (nbits <=64))
3371               {
3372 #ifdef HAVE_LIBZ
3373                   if (db_hdf5_hzip_params.codec == HZM_CODEC_ZLIB)
3374                       ((struct HZMCODECzlib *) db_hdf5_hzip_params.params)->bits = nbits;
3375                   else
3376 #endif
3377                   if (db_hdf5_hzip_params.codec == HZM_CODEC_BASE)
3378                       ((struct HZMCODECbase *) db_hdf5_hzip_params.params)->bits = nbits;
3379               }
3380               else
3381               {
3382                  db_perror("invalid nbits for hzip", E_COMPRESSION, me);
3383                  return (-1);
3384               }
3385            }
3386 
3387            if (H5Pset_filter(P_ckcrprops, DB_HDF5_HZIP_ID,
3388                    SILO_Globals.compressionErrmode == COMPRESSION_ERRMODE_FALLBACK ?
3389                        H5Z_FLAG_OPTIONAL : H5Z_FLAG_MANDATORY, 0, 0)<0)
3390            {
3391                db_perror("hzip filter setup", E_CALLFAIL, me);
3392                return (-1);
3393            }
3394        }
3395     }
3396 #endif
3397 #ifdef HAVE_FPZIP
3398     else if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3399        "METHOD=FPZIP")) != (char *)NULL)
3400     {
3401        if (have_fpzip == FALSE)
3402        {
3403           if ((ptr=(char *)strstr(SILO_Globals.compressionParams,
3404              "LOSS=")) != (char *)NULL)
3405           {
3406              (void)strncpy(chararray, ptr+5, 2);
3407              prec = (int) strtol(chararray, &check, 10);
3408              if ((chararray != check) && (prec >= 0) && (prec <=3))
3409              {
3410                 db_hdf5_fpzip_params.loss = prec;
3411              }
3412              else
3413              {
3414                 db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3415                 return (-1);
3416              }
3417           }
3418 
3419           if (H5Pset_filter(P_ckcrprops, DB_HDF5_FPZIP_ID,
3420                    SILO_Globals.compressionErrmode == COMPRESSION_ERRMODE_FALLBACK ?
3421                        H5Z_FLAG_OPTIONAL : H5Z_FLAG_MANDATORY, 0, 0)<0)
3422           {
3423               db_perror("H5Pset_filter", E_CALLFAIL, me);
3424               return (-1);
3425           }
3426        }
3427     }
3428 #endif
3429     else
3430     {
3431        db_perror(SILO_Globals.compressionParams, E_COMPRESSION, me);
3432        return (-1);
3433     }
3434     return 0;
3435 }
3436 
3437 /*-------------------------------------------------------------------------
3438  * Function:    db_hdf5_set_properties
3439  *
3440  * Purpose:     Set the HDF5 properties.
3441  *
3442  * Bugs:
3443  *
3444  * Return:      Success:        0
3445  *
3446  *              Failure:        -1
3447  *
3448  * Programmer:  Thomas R. Treadway, Tue Mar  6 14:23:50 PST 2007
3449  *
3450  * Modifications:
3451  *
3452  *
3453  *-------------------------------------------------------------------------
3454  */
3455 PRIVATE int
db_hdf5_set_properties(int rank,hsize_t size[])3456 db_hdf5_set_properties(int rank, hsize_t size[])
3457 {
3458     static char *me = "db_hdf5_set_properties";
3459     P_crprops = H5P_DEFAULT;
3460     if (SILO_Globals.enableChecksums &&
3461         !SILO_Globals.compressionParams)
3462     {
3463         H5Pset_chunk(P_ckcrprops, rank, size);
3464         P_crprops = P_ckcrprops;
3465     }
3466     else if (SILO_Globals.enableChecksums &&
3467         SILO_Globals.compressionParams)
3468     {
3469         H5Pset_chunk(P_ckcrprops, rank, size);
3470         if (db_hdf5_set_compression(0)<0) {
3471             db_perror("db_hdf5_set_compression", E_CALLFAIL, me);
3472             return(-1);
3473         }
3474         P_crprops = P_ckcrprops;
3475     }
3476     else if (SILO_Globals.compressionParams)
3477     {
3478         H5Pset_chunk(P_ckcrprops, rank, size);
3479         if (db_hdf5_set_compression(0)<0) {
3480             db_perror("db_hdf5_set_compression", E_CALLFAIL, me);
3481             return(-1);
3482         }
3483         P_crprops = P_ckcrprops;
3484     }
3485     return 0;
3486 }
3487 /*-------------------------------------------------------------------------
3488  * Function:    db_hdf5_get_comp_var
3489  *
3490  * Purpose:     Given a file handle and varname containing at least one
3491  *              underscore, attempts to get size and, optionally, read
3492  *              the corresponding HDF5 datatype name and member
3493  *              name pair, if it exists, formed by splitting the given
3494  *              varname at the underscore character. If multiple splits
3495  *              could possibly match with an HDF5 datatype name and member
3496  *              name pair in the file, only the first found is returned.
3497  *
3498  *              This function is necessary to support the old pdb-ish way
3499  *              of permitting a Silo client to request raw data arrays
3500  *              for the component of an object by the naming convention
3501  *              "<objname>_<compname>"
3502  *
3503  * Return:      If a valid split exists:                1
3504  *
3505  *              If a valid split does not exist:        0
3506  *
3507  * Programmer:  Mark C. Miller
3508  *              October 11, 2005
3509  *
3510  *-------------------------------------------------------------------------
3511  */
3512 PRIVATE int
db_hdf5_get_comp_var(hid_t fileid,char const * name,hsize_t * nelmts,size_t * elsize,hid_t * datatype,void ** buf)3513 db_hdf5_get_comp_var(hid_t fileid, char const *name, hsize_t *nelmts,
3514     size_t *elsize, hid_t *datatype, void **buf)
3515 {
3516     hid_t type_id = -1, stypeid = -1, attr = -1, comptype = -1, memtype = -1;
3517     int membno = -1;
3518     int retval = 0;
3519     hsize_t numvals = 0;
3520     size_t valsize = 0;
3521 
3522     /* loop trying different typename, member name combinations */
3523     char *tmpname = STRDUP(name);
3524     char *p = strrchr(tmpname, '_');
3525     char *type_name, *memname;
3526     while (p != 0 && *p != '\0')
3527     {
3528         char *tmpp = p;
3529         *p = '\0';
3530         type_name = tmpname;
3531         memname = p+1;
3532 
3533         stypeid = attr = type_id = -1;
3534         if ((type_id=H5Topen(fileid, type_name))>=0 &&
3535             (attr=H5Aopen_name(type_id, "silo"))>=0 &&
3536             (stypeid=H5Aget_type(attr))>=0 &&
3537             (membno=H5Tget_member_index(stypeid, memname))>=0)
3538             retval = 1;
3539 
3540         if (retval == 1) break;
3541 
3542         if (attr != -1) H5Aclose(attr);
3543         if (stypeid != -1) H5Tclose(stypeid);
3544         if (type_id != -1) H5Tclose(type_id);
3545 
3546         p = strrchr(tmpname, '_');
3547         *tmpp = '_';
3548     }
3549 
3550     if (retval == 1)
3551     {
3552         hid_t mbtype = H5Tget_member_type(stypeid, membno);
3553         H5T_class_t mbclass = H5Tget_class(mbtype);
3554 
3555         switch (mbclass) {
3556             case H5T_INTEGER:
3557                 numvals = 1;
3558                 comptype = H5T_NATIVE_INT;
3559                 break;
3560             case H5T_FLOAT:
3561                 numvals = 1;
3562                 comptype = H5T_NATIVE_FLOAT;
3563                 break;
3564             case H5T_ARRAY:
3565                 {
3566                     int i, ndims, size[3], len = 1;
3567                     comptype = db_hdf5_get_cmemb(stypeid, membno, &ndims, size);
3568                     for (i = 0; i < ndims; i++)
3569                         len *= size[i];
3570                     numvals = len;
3571                     break;
3572                 }
3573             case H5T_STRING:
3574                 numvals = 1;
3575                 comptype = T_str256; /* it may be an indirect dataset */
3576                 break;
3577             default:
3578                 numvals = 0;
3579                 break;
3580         }
3581 
3582         /* note, a comptype of T_str256 means either that the component
3583            contains the name of a dataset (indirect) case which we will
3584            need to read or the component is some other 256 character
3585            string */
3586 
3587         /* read the component data only if caller requested it */
3588         if ((numvals && buf) || comptype == T_str256)
3589         {
3590             char tmp[256];
3591             int buf_was_allocated = 0;
3592 
3593             valsize = H5Tget_size(comptype);
3594 
3595             if (comptype != T_str256 && *buf == 0)
3596             {
3597                 *buf = malloc(*nelmts * *elsize);
3598                 buf_was_allocated = 1;
3599             }
3600 
3601             /* create a component type with just one member,
3602                the one we're interested in */
3603             memtype = H5Tcreate(H5T_COMPOUND, H5Tget_size(comptype));
3604             H5Tinsert(memtype, H5Tget_member_name(stypeid, membno), 0, comptype);
3605 
3606             /* read attribute for the silo object data */
3607             H5Aread(attr, memtype, comptype==T_str256?tmp:*buf);
3608             H5Tclose(memtype);
3609 
3610             /* do the indirection if necessary */
3611             if (comptype == T_str256 &&
3612                 strncmp(tmp,"/.silo/#",8) == 0) /* indirect case */
3613             {
3614                 hid_t d, fspace, ftype, mtype;
3615 
3616                 d = H5Dopen(fileid, tmp);
3617                 fspace = H5Dget_space(d);
3618                 numvals = H5Sget_simple_extent_npoints(fspace);
3619                 ftype = H5Dget_type(d);
3620                 mtype = hdf2hdf_type(ftype);
3621                 valsize = H5Tget_size(mtype);
3622                 comptype = mtype;
3623                 if (buf)
3624                 {
3625                     if (*buf == 0)
3626                     {
3627                         *buf = malloc(numvals*H5Tget_size(mtype));
3628                         buf_was_allocated = 1;
3629                     }
3630                     else if (buf_was_allocated)
3631                     {
3632                         *buf = realloc(*buf, numvals*H5Tget_size(mtype));
3633                     }
3634 
3635                     P_rdprops = H5P_DEFAULT;
3636                     if (!SILO_Globals.enableChecksums)
3637                         P_rdprops = P_ckrdprops;
3638 
3639                     if (H5Dread(d, mtype, H5S_ALL, H5S_ALL, P_rdprops, *buf)<0) {
3640                         hdf5_to_silo_error(name, "db_hdf5_get_comp_var");
3641                         if (buf_was_allocated)
3642                         {
3643                             free(*buf);
3644                             *buf = 0;
3645                         }
3646                         retval = 0;
3647                     }
3648                 }
3649                 H5Tclose(ftype);
3650                 H5Dclose(d);
3651                 H5Sclose(fspace);
3652             }
3653             else if (comptype == T_str256) /* other string case */
3654             {
3655                 if (buf)
3656                 {
3657                     int n = strlen(tmp)+1;
3658                     if (*buf == 0)
3659                     {
3660                         *buf = malloc(n);
3661                     }
3662                     else if (buf_was_allocated)
3663                     {
3664                         *buf = realloc(*buf, n);
3665                     }
3666                     strncpy((char *)(*buf), tmp, n);
3667                     valsize = n;
3668                 }
3669             }
3670             else
3671             {
3672                 /* any other case, the component's data will have already
3673                    been read in to *buf in the H5Aread call, above */
3674             }
3675         }
3676 
3677         if (retval == 1)
3678         {
3679             if (nelmts)
3680                 *nelmts = numvals;
3681             if (elsize)
3682                 *elsize = valsize;
3683             if (datatype)
3684                 *datatype = comptype;
3685         }
3686     }
3687 
3688     if (attr != -1)    H5Aclose(attr);
3689     if (stypeid != -1) H5Tclose(stypeid);
3690     if (type_id != -1)  H5Tclose(type_id);
3691 
3692     FREE(tmpname);
3693     return retval;
3694 }
3695 
3696 /*-------------------------------------------------------------------------
3697  * Function:    load_toc
3698  *
3699  * Purpose:     Add an object to the table of contents
3700  *
3701  * Return:      Success:        0
3702  *
3703  *              Failure:        -1
3704  *
3705  * Programmer:  Robb Matzke
3706  *              Thursday, February 11, 1999
3707  *
3708  * Modifications:
3709  *
3710  *   Mark C. Miller, Tue Feb  1 13:48:33 PST 2005
3711  *   Made it deal with case of QUAD_RECT or QUAD_CURV
3712  *
3713  *-------------------------------------------------------------------------
3714  */
3715 PRIVATE herr_t
load_toc(hid_t grp,char const * name,void * _toc)3716 load_toc(hid_t grp, char const *name, void *_toc)
3717 {
3718     DBtoc               *toc = (DBtoc*)_toc;
3719     H5G_stat_t          sb;
3720     DBObjectType        objtype = DB_INVALID_OBJECT;
3721     int                 n, *nvals=NULL, _objtype;
3722     char                ***names=NULL;
3723     hid_t               obj=-1, attr=-1;
3724 
3725     if (H5Gget_objinfo(grp, name, TRUE, &sb)<0) return -1;
3726     switch (sb.type) {
3727     case H5G_GROUP:
3728         /*
3729          * Any group which has a `..' entry is a silo directory. The `..'
3730          * names do not appear in the silo table of contents.
3731          */
3732         if (!strcmp(name, "..") || (obj=H5Gopen(grp, name))<0) break;
3733         H5E_BEGIN_TRY {
3734             if (H5Gget_objinfo(obj, "..", FALSE, NULL)>=0) objtype = DB_DIR;
3735         } H5E_END_TRY;
3736         H5Gclose(obj);
3737         break;
3738 
3739     case H5G_TYPE:
3740         if ((obj=H5Topen(grp, name))<0) break;
3741         if ((attr=H5Aopen_name(obj, "silo_type"))<0) break;
3742         if (H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0) break;
3743         objtype = (DBObjectType)_objtype;
3744         H5Aclose(attr);
3745         H5Tclose(obj);
3746         break;
3747 
3748     case H5G_DATASET:
3749         objtype = DB_VARIABLE;
3750         break;
3751 
3752     default:
3753         /*ignore*/
3754         break;
3755     }
3756 
3757     /* What table of contents field does this object belong to? */
3758     switch (objtype) {
3759     case DB_INVALID_OBJECT:
3760         break;
3761     case DB_QUADMESH:
3762     case DB_QUAD_RECT:
3763     case DB_QUAD_CURV:
3764         names = &(toc->qmesh_names);
3765         nvals = &(toc->nqmesh);
3766         break;
3767     case DB_QUADVAR:
3768         names = &(toc->qvar_names);
3769         nvals = &(toc->nqvar);
3770         break;
3771     case DB_CSGMESH:
3772         names = &(toc->csgmesh_names);
3773         nvals = &(toc->ncsgmesh);
3774         break;
3775     case DB_CSGVAR:
3776         names = &(toc->csgvar_names);
3777         nvals = &(toc->ncsgvar);
3778         break;
3779     case DB_UCDMESH:
3780         names = &(toc->ucdmesh_names);
3781         nvals = &(toc->nucdmesh);
3782         break;
3783     case DB_UCDVAR:
3784         names = &(toc->ucdvar_names);
3785         nvals = &(toc->nucdvar);
3786         break;
3787     case DB_MULTIMESH:
3788         names = &(toc->multimesh_names);
3789         nvals = &(toc->nmultimesh);
3790         break;
3791     case DB_MULTIMESHADJ:
3792         names = &(toc->multimeshadj_names);
3793         nvals = &(toc->nmultimeshadj);
3794         break;
3795     case DB_MULTIVAR:
3796         names = &(toc->multivar_names);
3797         nvals = &(toc->nmultivar);
3798         break;
3799     case DB_MULTIMAT:
3800         names = &(toc->multimat_names);
3801         nvals = &(toc->nmultimat);
3802         break;
3803     case DB_MULTIMATSPECIES:
3804         names = &(toc->multimatspecies_names);
3805         nvals = &(toc->nmultimatspecies);
3806         break;
3807     case DB_MATERIAL:
3808         names = &(toc->mat_names);
3809         nvals = &(toc->nmat);
3810         break;
3811     case DB_MATSPECIES:
3812         names = &(toc->matspecies_names);
3813         nvals = &(toc->nmatspecies);
3814         break;
3815     case DB_CURVE:
3816         names = &(toc->curve_names);
3817         nvals = &(toc->ncurve);
3818         break;
3819     case DB_DEFVARS:
3820         names = &(toc->defvars_names);
3821         nvals = &(toc->ndefvars);
3822         break;
3823     case DB_POINTMESH:
3824         names = &(toc->ptmesh_names);
3825         nvals = &(toc->nptmesh);
3826         break;
3827     case DB_POINTVAR:
3828         names = &(toc->ptvar_names);
3829         nvals = &(toc->nptvar);
3830         break;
3831     case DB_ARRAY:
3832         names = &(toc->array_names);
3833         nvals = &(toc->narray);
3834         break;
3835     case DB_DIR:
3836         names = &(toc->dir_names);
3837         nvals = &(toc->ndir);
3838         break;
3839     case DB_VARIABLE:
3840         names = &(toc->var_names);
3841         nvals = &(toc->nvar);
3842         break;
3843     case DB_MRGTREE:
3844         names = &(toc->mrgtree_names);
3845         nvals = &(toc->nmrgtree);
3846         break;
3847     case DB_GROUPELMAP:
3848         names = &(toc->groupelmap_names);
3849         nvals = &(toc->ngroupelmap);
3850         break;
3851     case DB_MRGVAR:
3852         names = &(toc->mrgvar_names);
3853         nvals = &(toc->nmrgvar);
3854         break;
3855     case DB_USERDEF:  /*fall through*/
3856     case DB_FACELIST: /*fall through*/
3857     case DB_EDGELIST: /*fall through*/
3858     case DB_ZONELIST:
3859     case DB_PHZONELIST:
3860     case DB_CSGZONELIST:
3861         names = &(toc->obj_names);
3862         nvals = &(toc->nobj);
3863         break;
3864     }
3865 
3866     /* Append to table of contents */
3867     if (names && nvals) {
3868         n = (*nvals)++;
3869         *names = (char **)realloc(*names, *nvals*sizeof(char*));
3870         (*names)[n] = STRDUP(name);
3871     }
3872 
3873     return 0;
3874 }
3875 
3876 /*-------------------------------------------------------------------------
3877  * Function:    find_objno
3878  *
3879  * Purpose:     Determines if the specified object has the same object ID as
3880  *              what is stored in comp->objno and if so copies NAME to
3881  *              comp->name.
3882  *
3883  * Return:      Success:        1 if objno's are the same
3884  *
3885  *              Failure:        0
3886  *
3887  * Programmer:  Robb Matzke
3888  *              Thursday, February 11, 1999
3889  *
3890  * Modifications:
3891  *
3892  *-------------------------------------------------------------------------
3893  */
3894 PRIVATE herr_t
find_objno(hid_t grp,char const * name,void * _comp)3895 find_objno(hid_t grp, char const *name, void *_comp)
3896 {
3897     silo_hdf5_comp_t    *comp = (silo_hdf5_comp_t*)_comp;
3898     H5G_stat_t          sb;
3899 
3900     if (H5Gget_objinfo(grp, name, TRUE, &sb)<0) return -1;
3901     if (sb.objno[0]!=comp->objno[0] || sb.objno[1]!=comp->objno[1]) return 0;
3902     comp->name = STRDUP(name);
3903     return 1;
3904 }
3905 
3906 /*-------------------------------------------------------------------------
3907  * Function:    db_hdf5_handle_ctdt
3908  *
3909  * Purpose:     Handle special logic for cycle, time and dtime optins.
3910  *
3911  * Programmer:  Mark C. Miller, Thu Feb  4 08:58:10 PST 2010
3912  *
3913  * Modifications:
3914  *
3915  *  Mark C. Miller, Sat Feb  6 09:54:37 PST 2010
3916  *  In hopes that H5Lexists might be faster than attempting to open a
3917  *  dataset, added that as initial test for existance.
3918  *-------------------------------------------------------------------------
3919  */
3920 PRIVATE void
db_hdf5_handle_ctdt(DBfile_hdf5 * dbfile,int ts,float t,int dts,double dt,int c)3921 db_hdf5_handle_ctdt(DBfile_hdf5 *dbfile, int ts, float t, int dts, double dt, int c)
3922 {
3923     int set[3];
3924     void *buf[3];
3925     char *names[] = {"time","dtime","cycle"};
3926     int types[] = {DB_FLOAT, DB_DOUBLE, DB_INT};
3927     hid_t space = -1;
3928     int i;
3929 
3930     set[0] = ts;
3931     buf[0] = (void*)&t;
3932     set[1] = dts;
3933     buf[1] = (void*)&dt;
3934     set[2] = 1;
3935     buf[2] = (void*)&c;
3936 
3937     H5E_BEGIN_TRY
3938     {
3939         for (i = 0; i < 3; i++)
3940         {
3941             hid_t dset, mtype, ftype;
3942             const hsize_t one = 1;
3943             htri_t h5lexists = -1;
3944 
3945             if (!set[i]) continue;
3946 
3947 #if HDF5_VERSION_GE(1,8,0)
3948             if ((h5lexists = H5Lexists(dbfile->cwg, names[i], H5P_DEFAULT)) == TRUE)
3949                 continue;
3950 #endif
3951             if (h5lexists != FALSE)
3952             {
3953                 dset = H5Dopen(dbfile->cwg, names[i]);
3954                 if (!(dset<0))
3955                 {
3956                     H5Dclose(dset);
3957                     continue;
3958                 }
3959             }
3960 
3961             mtype = silom2hdfm_type(types[i]);
3962             ftype = silof2hdff_type(dbfile, types[i]);
3963             if (space == -1)
3964                 space = H5Screate_simple(1, &one, &one);
3965             dset = H5Dcreate(dbfile->cwg, names[i], ftype, space, H5P_DEFAULT);
3966             H5Dwrite(dset, mtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf[i]);
3967             H5Dclose(dset);
3968         }
3969 
3970         if (space != -1)
3971             H5Sclose(space);
3972 
3973     }
3974     H5E_END_TRY;
3975 }
3976 
3977 /*-------------------------------------------------------------------------
3978  * Function:    db_hdf5_compname
3979  *
3980  * Purpose:     Returns a new name relative to the link directory. The name
3981  *              is generated by reading the `nlinks' attribute of the link
3982  *              directory, incrementing it, creating a file name, and saving
3983  *              it back to the file.
3984  *
3985  * Return:      Success:        0, A new link name not more than 8 characters
3986  *                              long counting the null terminator is returned
3987  *                              through the NAME argument.
3988  *
3989  *              Failure:        -1
3990  *
3991  * Programmer:  Robb Matzke
3992  *              Tuesday, March 23, 1999
3993  *
3994  * Modifications:
3995  *
3996  *-------------------------------------------------------------------------
3997  */
3998 PRIVATE int
db_hdf5_compname(DBfile_hdf5 * dbfile,char name[8])3999 db_hdf5_compname(DBfile_hdf5 *dbfile, char name[8]/*out*/)
4000 {
4001     static char *me = "db_hdf5_compname";
4002     hid_t       attr=-1;
4003     int         nlinks;
4004 
4005     PROTECT {
4006         /* Open or create the `nlinks' attribute of the link group */
4007         H5E_BEGIN_TRY {
4008             attr = H5Aopen_name(dbfile->link, "nlinks");
4009         } H5E_END_TRY;
4010         if (attr<0 && (attr=H5Acreate(dbfile->link, "nlinks", H5T_NATIVE_INT,
4011                                       SCALAR, H5P_DEFAULT))<0) {
4012             db_perror("nlinks attribute", E_CALLFAIL, me);
4013             UNWIND();
4014         }
4015 
4016         /* Increment the nlinks value */
4017         if (H5Aread(attr, H5T_NATIVE_INT, &nlinks)<0) {
4018             db_perror("nlinks attribute", E_CALLFAIL, me);
4019             UNWIND();
4020         }
4021 
4022         nlinks++;
4023         if (nlinks > 999999) {
4024             db_perror("exceeded maximum number of nlinks", E_CALLFAIL, me);
4025             UNWIND();
4026         }
4027 
4028         if (H5Awrite(attr, H5T_NATIVE_INT, &nlinks)<0) {
4029             db_perror("nlinks attribute", E_CALLFAIL, me);
4030             UNWIND();
4031         }
4032         H5Aclose(attr);
4033 
4034         /* Create a name */
4035         sprintf(name, "#%06d", nlinks);
4036 
4037     } CLEANUP {
4038         H5E_BEGIN_TRY {
4039             H5Aclose(attr);
4040         } H5E_END_TRY;
4041     } END_PROTECT;
4042 
4043     return 0;
4044 }
4045 
4046 /*-------------------------------------------------------------------------
4047  * Function:    db_hdf5_compwrz
4048  *
4049  * Purpose:     Creates a new dataset in the link group.
4050  *
4051  * Return:      Success:        >=0
4052  *
4053  *              Failure:        -1
4054  *
4055  * Programmer:  Robb Matzke
4056  *              Tuesday, March 23, 1999
4057  *
4058  * Modifications:
4059  *
4060  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
4061  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
4062  *
4063  *   Mark C. Miller, Thu Sep  8 12:54:39 PDT 2005
4064  *   Made it permit buf to be NULL in which case it will only create the
4065  *   dataset but not attempt to write to it. Also, made it return hid_t of
4066  *   created dataset.
4067  *
4068  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
4069  *   Added support for friendly hdf5 dataset names (as soft links)
4070  *
4071  *   Mark C. Miller, Tue Jul 15 22:37:31 PDT 2008
4072  *   Added 'z' to name and compressionFlags argument to provide control
4073  *   over mesh-level compresion algorithms. The older (non-z) method
4074  *   remains as a stub that simply calls this one with zero for flags.
4075  *
4076  *   Mark C. Miller, Thu Nov  5 16:15:00 PST 2009
4077  *   Added support for hard links for friendly names too.
4078  *
4079  *   Mark C. Miller, Thu Feb  4 11:24:24 PST 2010
4080  *   Removed logic specific to support cycle, time and time.
4081  *   Mark C. Miller, Wed Jul 14 20:49:21 PDT 2010
4082  *
4083  *   Added logic to support a different kind of 'friendly-names' mode
4084  *   where no datasets are put in the 'LINKGRP' and are instead put
4085  *   'next to' the objects they bind with. The intention is to eliminate
4086  *   the one, very, very large '/.silo' group.
4087  *-------------------------------------------------------------------------
4088  */
4089 PRIVATE int
db_hdf5_compwrz(DBfile_hdf5 * dbfile,int dtype,int rank,int const _size[],void const * buf,char * name,char const * fname,int compressionFlags)4090 db_hdf5_compwrz(DBfile_hdf5 *dbfile, int dtype, int rank, int const _size[],
4091                void const *buf, char *name/*in,out*/, char const *fname,
4092                int compressionFlags)
4093 {
4094     static char *me = "db_hdf5_compwr";
4095     hid_t       dset=-1, mtype=-1, ftype=-1, space=-1;
4096     int         i, nels;
4097     hsize_t     size[8];
4098     int         alloc = 0;
4099 
4100     if (rank < 0)
4101     {
4102         rank = -rank;
4103         alloc = 1;
4104     }
4105 
4106     /* Not an error if there is no data */
4107     for (i=0, nels=1; i<rank; i++) nels *= _size[i];
4108     if ((!buf || !nels) && !alloc) {
4109         *name = '\0';
4110         return 0;
4111     }
4112 
4113     PROTECT {
4114         /* Obtain a unique name for the dataset or use the name supplied */
4115         if (!*name) {
4116             strcpy(name, LINKGRP);
4117             if (db_hdf5_compname(dbfile, ENDOF(name)/*out*/)<0) {
4118                 db_perror("compname", E_CALLFAIL, me);
4119                 UNWIND();
4120             }
4121         }
4122 
4123         /* Obtain the memory and file types for the dataset */
4124         if ((mtype=silom2hdfm_type(dtype))<0 ||
4125             (ftype=silof2hdff_type(dbfile, dtype))<0) {
4126             db_perror(name, E_CALLFAIL, me);
4127             UNWIND();
4128         }
4129 
4130         /* Create the dataset and write data */
4131         assert(rank>0 && (size_t)rank<=NELMTS(size));
4132         for (i=0; i<rank; i++) size[i] = _size[i];
4133         if ((space=H5Screate_simple(rank, size, size))<0) {
4134             db_perror(name, E_CALLFAIL, me);
4135             UNWIND();
4136         }
4137 
4138         if (db_hdf5_set_properties(rank, size) < 0 ) {
4139             db_perror("db_hdf5_set_properties", E_CALLFAIL, me);
4140             UNWIND();
4141         }
4142         if (SILO_Globals.compressionParams && compressionFlags)
4143         {
4144             if (db_hdf5_set_compression(compressionFlags)<0)
4145             {
4146                 db_perror("db_hdf5_set_compression", E_CALLFAIL, me);
4147                 UNWIND();
4148             }
4149         }
4150 
4151         if (SILO_Globals.enableFriendlyHDF5Names == 2)
4152         {
4153             if (fname)
4154             {
4155                 if ((dset=H5Dcreate(dbfile->cwg, fname, ftype, space, P_crprops))<0) {
4156                     db_perror(name, E_CALLFAIL, me);
4157                     UNWIND();
4158                 }
4159                 strcpy(name, fname);
4160             }
4161             else
4162             {
4163                 if ((dset=H5Dcreate(dbfile->link, name, ftype, space, P_crprops))<0) {
4164                     db_perror(name, E_CALLFAIL, me);
4165                     UNWIND();
4166                 }
4167             }
4168         }
4169         else
4170         {
4171             if ((dset=H5Dcreate(dbfile->link, name, ftype, space, P_crprops))<0) {
4172                 db_perror(name, E_CALLFAIL, me);
4173                 UNWIND();
4174             }
4175             if (fname && SILO_Globals.enableFriendlyHDF5Names == 1)
4176                 H5Glink(dbfile->cwg, H5G_LINK_SOFT, name, fname);
4177         }
4178 
4179         if (buf && H5Dwrite(dset, mtype, space, space, H5P_DEFAULT, buf)<0) {
4180             hdf5_to_silo_error(name, "db_hdf5_compwrz");
4181             UNWIND();
4182         }
4183 
4184         /* Release resources */
4185         H5Dclose(dset);
4186         H5Sclose(space);
4187 
4188         /* remove any mesh specific filters if we have 'em */
4189         if (SILO_Globals.compressionParams && compressionFlags)
4190         {
4191             int i;
4192             for (i=0; i<H5Pget_nfilters(P_crprops); i++)
4193             {
4194 #if defined H5_USE_16_API || (H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8)
4195                 if (H5Pget_filter(P_crprops,(unsigned)i,0,0,0,0,0) == DB_HDF5_HZIP_ID)
4196 #else
4197                 if (H5Pget_filter(P_crprops,(unsigned)i,0,0,0,0,0,NULL) == DB_HDF5_HZIP_ID)
4198 #endif
4199                 {
4200                     H5Premove_filter(P_crprops, DB_HDF5_HZIP_ID);
4201                     break;
4202                 }
4203             }
4204         }
4205 
4206     } CLEANUP {
4207         H5E_BEGIN_TRY {
4208             H5Dclose(dset);
4209             H5Sclose(space);
4210         } H5E_END_TRY;
4211     } END_PROTECT;
4212     return dset;
4213 }
4214 
4215 /*-------------------------------------------------------------------------
4216  * Function:    db_hdf5_compwr
4217  *
4218  * Purpose:     Creates a new dataset in the link group without compression.
4219  *
4220  * Return:      Success:        >=0
4221  *
4222  *              Failure:        -1
4223  *
4224  * Created: Mark C. Miller, Thu Jul 17 15:03:55 PDT 2008
4225  *-------------------------------------------------------------------------
4226  */
4227 PRIVATE int
db_hdf5_compwr(DBfile_hdf5 * dbfile,int dtype,int rank,int const _size[],void const * buf,char * name,char const * fname)4228 db_hdf5_compwr(DBfile_hdf5 *dbfile, int dtype, int rank, int const _size[],
4229                void const *buf, char *name/*in,out*/, char const *fname)
4230 {
4231     return db_hdf5_compwrz(dbfile, dtype, rank, _size, buf, name, fname, 0);
4232 }
4233 
4234 /*-------------------------------------------------------------------------
4235  * Function:    db_hdf5_compckz
4236  *
4237  * Purpose:     Check if a dataset is compressed with HZIP
4238  *
4239  * Return:      Success:        >=0
4240  *
4241  *              Failure:        -1
4242  *
4243  * Created: Mark C. Miller, Thu Jul 17 15:03:55 PDT 2008
4244  *-------------------------------------------------------------------------
4245  */
4246 PRIVATE int
db_hdf5_compckz(DBfile_hdf5 * dbfile,char * name)4247 db_hdf5_compckz(DBfile_hdf5 *dbfile, char *name)
4248 {
4249     int retval = 0;
4250     int i;
4251     hid_t d = -1, plist = -1;
4252     static char *me = "db_hdf5_compzkz";
4253 
4254     PROTECT {
4255         if (name && *name) {
4256             if ((d=H5Dopen(dbfile->cwg, name))<0) {
4257                 db_perror(name, E_NOTFOUND, me);
4258                 UNWIND();
4259             }
4260             if ((plist=H5Dget_create_plist(d))<0) {
4261                 db_perror(name, E_CALLFAIL, me);
4262                 UNWIND();
4263             }
4264 
4265             for (i=0; i<H5Pget_nfilters(plist); i++)
4266             {
4267                 char name[256];
4268 #if defined H5_USE_16_API || (H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8)
4269                 H5Pget_filter(plist,(unsigned)i,0,0,0,sizeof(name),name);
4270 #else
4271                 H5Pget_filter(plist,(unsigned)i,0,0,0,sizeof(name),name,NULL);
4272 #endif
4273                 if (strstr(name, "Lindstrom-hzip"))
4274                 {
4275                     retval = 1;
4276                     break;
4277                 }
4278             }
4279             H5Dclose(d);
4280             H5Pclose(plist);
4281         }
4282     } CLEANUP {
4283         if (d != -1) H5Dclose(d);
4284         if (plist != -1) H5Pclose(plist);
4285     } END_PROTECT;
4286 
4287     return retval;
4288 }
4289 
4290 /*-------------------------------------------------------------------------
4291  * Function:    db_hdf5_comprd
4292  *
4293  * Purpose:     Reads a dataset from the file into memory.
4294  *
4295  * Return:      Success:        Pointer to dataset values.
4296  *
4297  *              Failure:        NULL
4298  *
4299  * Programmer:  Robb Matzke
4300  *              Wednesday, March 31, 1999
4301  *
4302  * Modifications:
4303  *              Robb Matzke, 1999-10-13
4304  *              Uses the current working directory instead of the root
4305  *              directory.
4306  *-------------------------------------------------------------------------
4307  */
4308 PRIVATE void *
db_hdf5_comprd(DBfile_hdf5 * dbfile,char * name,int ignore_force_single)4309 db_hdf5_comprd(DBfile_hdf5 *dbfile, char *name, int ignore_force_single)
4310 {
4311     static char *me = "db_hdf5_comprd";
4312     void        *buf = NULL;
4313     hid_t       d=-1, fspace=-1, ftype=-1, mtype=-1;
4314     int         i, nelmts;
4315     void       *retval = NULL;
4316 
4317     PROTECT {
4318         if (name && *name) {
4319             if ((d=H5Dopen(dbfile->cwg, name))<0) {
4320                 db_perror(name, E_NOTFOUND, me);
4321                 UNWIND();
4322             }
4323             if ((fspace=H5Dget_space(d))<0 || (ftype=H5Dget_type(d))<0) {
4324                 db_perror(name, E_CALLFAIL, me);
4325                 UNWIND();
4326             }
4327             nelmts = H5Sget_simple_extent_npoints(fspace);
4328 
4329             /* Choose a memory type based on the file type */
4330             mtype = hdf2hdf_type(ftype);
4331 
4332             /* if we decided on a memory type of double but
4333              * we are forcing single precision, then select
4334              * a memory type of float */
4335             if (mtype == H5T_NATIVE_DOUBLE &&
4336                 force_single_g && !ignore_force_single)
4337                 mtype = H5T_NATIVE_FLOAT;
4338 
4339             /* Read the data */
4340             if (NULL==(buf=malloc(nelmts*H5Tget_size(mtype)))) {
4341                 db_perror(name, E_NOMEM, me);
4342                 UNWIND();
4343             }
4344 
4345             P_rdprops = H5P_DEFAULT;
4346             if (!SILO_Globals.enableChecksums)
4347                 P_rdprops = P_ckrdprops;
4348 
4349             if (H5Dread(d, mtype, H5S_ALL, H5S_ALL, P_rdprops, buf)<0) {
4350                 hdf5_to_silo_error(name, me);
4351                 UNWIND();
4352             }
4353 
4354             /* Free resources */
4355             H5Dclose(d);
4356             H5Tclose(ftype);
4357             H5Sclose(fspace);
4358 
4359             /* Setup return value */
4360             retval = buf;
4361 
4362             /* Convert to float if necessary */
4363             /* With newer versions of HDF5, this could have been done
4364              * automatically in the H5Dread call, above by selecting
4365              * the appropriate memory type. However, the current version
4366              * of HDF5 does not support conversion from integral types
4367              * to float (or double) */
4368             if (force_single_g && !ignore_force_single &&
4369                 mtype != H5T_NATIVE_FLOAT)
4370             {
4371                 float *newbuf;
4372 
4373                 /* allocate a new buffer */
4374                 if (NULL==(newbuf=(float*)malloc(nelmts*sizeof(float)))) {
4375                     db_perror(name, E_NOMEM, me);
4376                     UNWIND();
4377                 }
4378 
4379                 /* do the conversion */
4380                 if      (mtype == H5T_NATIVE_UCHAR)
4381                 {
4382                     char *cbuf = (char *) buf;
4383                     for (i = 0; i < nelmts; i++)
4384                         newbuf[i] = (float)(cbuf[i]);
4385                 }
4386                 else if (mtype == H5T_NATIVE_SHORT)
4387                 {
4388                     short *sbuf = (short *) buf;
4389                     for (i = 0; i < nelmts; i++)
4390                         newbuf[i] = (float)(sbuf[i]);
4391                 }
4392                 else if (mtype == H5T_NATIVE_INT)
4393                 {
4394                     int *ibuf = (int *) buf;
4395                     for (i = 0; i < nelmts; i++)
4396                         newbuf[i] = (float)(ibuf[i]);
4397                 }
4398                 else if (mtype == H5T_NATIVE_LONG)
4399                 {
4400                     long *lbuf = (long *) buf;
4401                     for (i = 0; i < nelmts; i++)
4402                         newbuf[i] = (float)(lbuf[i]);
4403                 }
4404                 else if (mtype == H5T_NATIVE_LLONG)
4405                 {
4406                     long long *lbuf = (long long *) buf;
4407                     for (i = 0; i < nelmts; i++)
4408                         newbuf[i] = (float)(lbuf[i]);
4409                 }
4410 
4411                 /* Free old buffer and setup return value */
4412                 free(buf);
4413                 retval = newbuf;
4414             }
4415         }
4416     } CLEANUP {
4417         H5E_BEGIN_TRY {
4418             H5Dclose(d);
4419             H5Tclose(ftype);
4420             H5Sclose(fspace);
4421         } H5E_END_TRY;
4422         FREE(buf);
4423     } END_PROTECT;
4424 
4425     return retval;
4426 }
4427 
4428 /*-------------------------------------------------------------------------
4429  * Function:    db_hdf5_fullname
4430  *
4431  * Purpose:     Given the current working directory name, the parent object
4432  *              name as passed by the Silo library client and the child
4433  *              object name as stored in the parent object, determine the
4434  *              absolute, full path name of the child object.
4435  *
4436  * Return:      Success:     fully resolved full path name of child object
4437  *
4438  *              Failure:     0
4439  *-------------------------------------------------------------------------
4440  */
4441 PRIVATE char *
db_hdf5_resolvename(DBfile * _dbfile,char const * parent_objname,char const * child_objname)4442 db_hdf5_resolvename(DBfile *_dbfile,
4443                     char const *parent_objname,
4444                     char const *child_objname)
4445 {
4446     static char cwgname[4096];
4447     static char result[4096];
4448     char *parent_objdirname = 0;
4449     char *parent_fullname = 0;
4450     char *child_fullname = 0;
4451 
4452     db_hdf5_GetDir(_dbfile, cwgname);
4453     parent_objdirname = db_dirname(parent_objname);
4454     if (parent_objdirname)
4455         parent_fullname = db_join_path(cwgname, parent_objdirname);
4456     if (parent_fullname)
4457         child_fullname = db_join_path(parent_fullname, child_objname);
4458     if (child_fullname)
4459         strcpy(result, child_fullname);
4460     else
4461         result[0] = '\0';
4462     if (parent_objdirname) free(parent_objdirname);
4463     if (parent_fullname) free(parent_fullname);
4464     if (child_fullname) free(child_fullname);
4465     return result;
4466 }
4467 
4468 /*-------------------------------------------------------------------------
4469  * Function:    db_hdf5_fullname
4470  *
4471  * Purpose:     Given a name return the corresponding absolute name. If NAME
4472  *              is the empty string then the FULL output value will also be
4473  *              the empty string.
4474  *
4475  * Return:      Success:        0, full name returned through FULL argument.
4476  *
4477  *              Failure:        -1
4478  *
4479  * Programmer:  Robb Matzke
4480  *              Tuesday, March 23, 1999
4481  *
4482  * Modifications:
4483  *
4484  *-------------------------------------------------------------------------
4485  */
4486 PRIVATE int
db_hdf5_fullname(DBfile_hdf5 * dbfile,char * name,char * full)4487 db_hdf5_fullname(DBfile_hdf5 *dbfile, char *name, char *full/*out*/)
4488 {
4489     if (!name || !*name) {
4490         *full = '\0';
4491     } else if ('/'==*name) {
4492         strcpy(full, name);
4493     } else {
4494         db_hdf5_GetDir((DBfile*)dbfile, full);
4495         if (strcmp(full, "/")) strcat(full, "/");
4496         strcat(full, name);
4497     }
4498     return 0;
4499 }
4500 
4501 /*-------------------------------------------------------------------------
4502  * Function:    db_hdf5_hdrwr
4503  *
4504  * Purpose:     Writes BUF as the `silo' attribute of an object.  If the
4505  *              object does not exist then it is created as a named data type
4506  *              (because a named data type has less overhead than an empty
4507  *              dataset in hdf5).
4508  *
4509  * Return:      Success:        0
4510  *
4511  *              Failure:        -1
4512  *
4513  * Programmer:  Robb Matzke
4514  *              Tuesday, March 23, 1999
4515  *
4516  * Modifications:
4517  *
4518  *-------------------------------------------------------------------------
4519  */
4520 PRIVATE int
db_hdf5_hdrwr(DBfile_hdf5 * dbfile,char * name,hid_t mtype,hid_t ftype,void * buf,DBObjectType objtype)4521 db_hdf5_hdrwr(DBfile_hdf5 *dbfile, char *name, hid_t mtype, hid_t ftype,
4522               void *buf, DBObjectType objtype)
4523 {
4524     static char *me = "db_hdf5_hdrwr";
4525     hid_t       obj=-1, attr=-1;
4526     int         _objtype = (int)objtype;
4527     int         created = FALSE;
4528 
4529     PROTECT {
4530         /* Open an existing object or create a named type */
4531         H5E_BEGIN_TRY {
4532             obj = H5Topen(dbfile->cwg, name);
4533         } H5E_END_TRY;
4534         if (obj<0) {
4535             obj = H5Tcopy(H5T_NATIVE_INT);
4536             if (H5Tcommit(dbfile->cwg, name, obj)<0) {
4537                 db_perror(name, E_CALLFAIL, me);
4538                 UNWIND();
4539             }
4540             created = TRUE;
4541         }
4542 
4543         /* Open or create the `silo' attribute */
4544         if (created) {
4545             attr = -1;
4546         } else {
4547             H5E_BEGIN_TRY {
4548                 attr = H5Aopen_name(obj, "silo");
4549             } H5E_END_TRY;
4550         }
4551         if (attr<0 && (attr=H5Acreate(obj, "silo", ftype, SCALAR,
4552                                       H5P_DEFAULT))<0) {
4553             db_perror(name, E_CALLFAIL, me);
4554             UNWIND();
4555         }
4556 
4557         /* Write data to the attribute */
4558         if (H5Awrite(attr, mtype, buf)<0) {
4559             db_perror(name, E_CALLFAIL, me);
4560             UNWIND();
4561         }
4562         H5Aclose(attr);
4563 
4564         /* Open or create the `silo_type' attribute */
4565         if (created) {
4566             attr = -1;
4567         } else {
4568             H5E_BEGIN_TRY {
4569                 attr = H5Aopen_name(obj, "silo_type");
4570             } H5E_END_TRY;
4571         }
4572         if (attr<0 && (attr=H5Acreate(obj, "silo_type", H5T_NATIVE_INT, SCALAR,
4573                                       H5P_DEFAULT))<0) {
4574             db_perror(name, E_CALLFAIL, me);
4575             UNWIND();
4576         }
4577         if (H5Awrite(attr, H5T_NATIVE_INT, &_objtype)<0) {
4578             db_perror(name, E_CALLFAIL, me);
4579             UNWIND();
4580         }
4581         H5Aclose(attr);
4582         H5Tclose(obj);
4583 
4584     } CLEANUP {
4585         H5E_BEGIN_TRY {
4586             H5Aclose(attr);
4587             H5Tclose(obj);
4588         } H5E_END_TRY;
4589     } END_PROTECT;
4590     return 0;
4591 }
4592 
4593 
4594 /*-------------------------------------------------------------------------
4595  * Function:    db_hdf5_ForceSingle
4596  *
4597  * Purpose:     If STATUS is non-zero then all floating point raw data values
4598  *              transferred between the application and the silo API will be
4599  *              of type `float'; otherwise type `double' is assumed.
4600  *
4601  * Return:      Success:        0
4602  *
4603  *              Failure:        never fails
4604  *
4605  * Programmer:  Robb Matzke
4606  *              Monday, March 22, 1999
4607  *
4608  * Modifications:
4609  *
4610  *-------------------------------------------------------------------------
4611  */
4612 INTERNAL int
db_hdf5_ForceSingle(int status)4613 db_hdf5_ForceSingle(int status)
4614 {
4615     force_single_g = status;
4616     return 0;
4617 }
4618 
4619 /*-------------------------------------------------------------------------
4620  * Function:    db_hdf5_process_file_options
4621  *
4622  * Purpose:     Laboriously digest a file options set and set up correct
4623  *              HDF5 vfd behavior.
4624  *
4625  * Return:      The constructed file access properties list hid_t
4626  *
4627  * Programmer:  Mark C. Miller
4628  *              Febuary, 2010
4629  *
4630  * Modifications:
4631  *
4632  *  Mark C. Miller, Wed Jul 14 20:52:19 PDT 2010
4633  *  Moved default silo settings to macro constants in H5FDsilo.h.
4634  *  Added support for direct I/O to silo vfd.
4635  *
4636  *  Mark C. Miller, Wed Aug  4 16:06:41 PDT 2010
4637  *  Added conditional compilation logic for silo fapl for HDF5 1.8.4 or
4638  *  greater.
4639  *-------------------------------------------------------------------------
4640  */
4641 PRIVATE hid_t
db_hdf5_process_file_options(int opts_set_id,int mode)4642 db_hdf5_process_file_options(int opts_set_id, int mode)
4643 {
4644     static char *me = "db_hdf5_process_file_options";
4645     hid_t retval = H5Pcreate(H5P_FILE_ACCESS);
4646     herr_t h5status = 0;
4647 
4648     /* This property effects how HDF5 deals with objects that are left
4649        open when the file containing them is closed. The SEMI setting
4650        means that HDF5 will flag it is an error. The STRONG setting
4651        means that HDF5 will attempt to close any option objects
4652        automatically. That can wind up hiding coding errors in this
4653        Silo plugin, so we do that only when user has requested that
4654        either top or no errors are reported. */
4655     if (SILO_Globals._db_err_level_drvr == DB_ALL)
4656         h5status |= H5Pset_fclose_degree(retval, H5F_CLOSE_SEMI);
4657     else
4658         h5status |= H5Pset_fclose_degree(retval, H5F_CLOSE_STRONG);
4659 
4660     /* Disable chunk caching */
4661     H5Pset_cache(retval, 0, 0, 0, 0);
4662 
4663     /* Handle cases where we are running on Windows. If a client
4664        request anything other than the default driver, we issue
4665        a warning message and continue only on windows (default) vfd. */
4666 #if !defined(_WIN32)
4667 #warning REMOVED WINDOWS SPECIFIC CHECK
4668 #endif
4669 #if 0
4670 #if defined(_WIN32)
4671     if (opts_set_id != DB_FILE_OPTS_H5_DEFAULT_DEFAULT &&
4672         opts_set_id < NUM_DEFAULT_FILE_OPTIONS_SETS)
4673     {
4674         H5Pclose(retval);
4675         return db_perror("Non-default HDF5 VFD specified on Windows.", E_CALLFAIL, me);
4676     }
4677 #endif
4678 #endif
4679 
4680     switch (opts_set_id)
4681     {
4682         /* Winds up using whatever the default vfd defined by HDF5 library is. */
4683         case DB_FILE_OPTS_H5_DEFAULT_DEFAULT:
4684             break;
4685 
4686         case DB_FILE_OPTS_H5_DEFAULT_SILO:
4687 #if HDF5_VERSION_GE(1,8,4)
4688             h5status |= H5Pset_fapl_silo(retval);
4689 #else
4690             H5Pclose(retval);
4691             return db_perror("Silo block VFD >= HDF5 1.8.4", E_NOTENABLEDINBUILD, me);
4692 #endif
4693             break;
4694 
4695         /* default HDF5 sec2 driver */
4696         case DB_FILE_OPTS_H5_DEFAULT_SEC2:
4697             h5status |= H5Pset_fapl_sec2(retval);
4698             break;
4699 
4700         /* default HDF5 stdio driver */
4701         case DB_FILE_OPTS_H5_DEFAULT_STDIO:
4702             h5status |= H5Pset_fapl_stdio(retval);
4703             /* I tried also having option to set buffer size. But, you need
4704                a file handle that has NOT had any I/O occur on it yet and
4705                HDF5 can't do that */
4706             break;
4707 
4708         /* default HDF5 core driver 1 Meg inc & backing store */
4709         case DB_FILE_OPTS_H5_DEFAULT_CORE:
4710             h5status |= H5Pset_fapl_core(retval, (1<<20), TRUE);
4711             break;
4712 
4713         /* default HDF5 log driver. Should NOT do any actual I/O. */
4714         case DB_FILE_OPTS_H5_DEFAULT_LOG:
4715             h5status |= H5Pset_fapl_log(retval, "silo_hdf5_log.out",
4716                 H5FD_LOG_LOC_IO|H5FD_LOG_NUM_IO|
4717                 H5FD_LOG_TIME_IO|H5FD_LOG_ALLOC, 0);
4718             break;
4719 
4720         /* default HDF5 split file driver. */
4721         case DB_FILE_OPTS_H5_DEFAULT_SPLIT:
4722         {
4723             hid_t meta_fapl = db_hdf5_process_file_options(DB_FILE_OPTS_H5_DEFAULT_CORE, mode);
4724             hid_t raw_fapl = db_hdf5_process_file_options(DB_FILE_OPTS_H5_DEFAULT_DEFAULT, mode);
4725             h5status |= H5Pset_fapl_split(retval, "", meta_fapl, "-raw", raw_fapl);
4726             H5Pclose(meta_fapl);
4727             H5Pclose(raw_fapl);
4728             break;
4729         }
4730 
4731         /* default HDF5 direct driver. */
4732         case DB_FILE_OPTS_H5_DEFAULT_DIRECT:
4733         {
4734 #ifdef H5_HAVE_DIRECT
4735             int const fourkb = (1<<12);
4736             h5status |= H5Pset_fapl_direct(retval, fourkb, fourkb, fourkb*256);
4737             h5status |= H5Pset_alignment(retval, fourkb/2, fourkb);
4738 #else
4739             H5Pclose(retval);
4740             return db_perror("HDF5 Direct VFD", E_NOTENABLEDINBUILD, me);
4741 #endif
4742             break;
4743         }
4744 
4745         /* default HDF5 family driver w/1Gig (2^30) members. */
4746         case DB_FILE_OPTS_H5_DEFAULT_FAMILY:
4747         {
4748             hid_t memb_fapl = db_hdf5_process_file_options(DB_FILE_OPTS_H5_DEFAULT_DEFAULT, mode);
4749             h5status |= H5Pset_fapl_family(retval, (1<<30), memb_fapl);
4750             H5Pclose(memb_fapl);
4751             break;
4752         }
4753 
4754         /* default HDF5 mpi drivers */
4755         case DB_FILE_OPTS_H5_DEFAULT_MPIP:
4756         {
4757 #ifdef H5_HAVE_PARALLEL
4758             h5status |= H5Pset_fapl_mpiposix(retval, MPI_COMM_SELF, TRUE);
4759 #else
4760             H5Pclose(retval);
4761             return db_perror("HDF5 MPI VFD", E_NOTENABLEDINBUILD, me);
4762 #endif
4763             break;
4764         }
4765 
4766         case DB_FILE_OPTS_H5_DEFAULT_MPIO:
4767         {
4768 #ifdef H5_HAVE_PARALLEL
4769             MPI_Info info;
4770             MPI_Info_create(&info);
4771             h5status |= H5Pset_fapl_mpio(retval, MPI_COMM_SELF, info);
4772             MPI_Info_free(&info);
4773 #else
4774             H5Pclose(retval);
4775             return db_perror("HDF5 MPI VFD", E_NOTENABLEDINBUILD, me);
4776 #endif
4777             break;
4778         }
4779 
4780         /* More complex cases where parameters specified by user
4781            registered options sets. */
4782         default:
4783         {
4784             int _opts_set_id = opts_set_id - NUM_DEFAULT_FILE_OPTIONS_SETS;
4785             DBoptlist const *opts;
4786             void *p; int vfd = DB_H5VFD_DEFAULT;
4787 
4788             if (_opts_set_id >= MAX_FILE_OPTIONS_SETS ||
4789                 (opts = SILO_Globals.fileOptionsSets[_opts_set_id]) == 0)
4790             {
4791                 H5Pclose(retval);
4792                 return db_perror("Bad file options set index", E_CALLFAIL, me);
4793             }
4794 
4795             /* get the vfd specification */
4796             if ((p = DBGetOption(opts, DBOPT_H5_VFD)))
4797             {
4798                 vfd = *((int*)p);
4799             }
4800             else if ((p = DBGetOption(opts, DBOPT_H5_USER_DRIVER_ID)))
4801             {
4802                 int new_driver_id = *((int*)p);
4803                 p = DBGetOption(opts, DBOPT_H5_USER_DRIVER_INFO);
4804                 h5status |= H5Pset_driver(retval, new_driver_id, p);
4805             }
4806 
4807 #if !defined(_WIN32)
4808 #warning REMOVED WINDOWS SPECIFIC CHECK
4809 #endif
4810 #if 0
4811 #if defined(_WIN32)
4812             if (vfd != DB_H5VFD_DEFAULT)
4813             {
4814                 db_perror("Non-default HDF5 VFD specified on Windows.", E_CALLFAIL, me);
4815                 vfd = DB_H5VFD_DEFAULT;
4816             }
4817 #endif
4818 #endif
4819 
4820             switch (vfd)
4821             {
4822                 case DB_H5VFD_DEFAULT:
4823                     break;
4824                 case DB_H5VFD_SEC2:
4825                     h5status |= H5Pset_fapl_sec2(retval);
4826                     break;
4827                 case DB_H5VFD_STDIO:
4828                     h5status |= H5Pset_fapl_stdio(retval);
4829                     break;
4830                 case DB_H5VFD_SILO:
4831                 {
4832 #if HDF5_VERSION_GE(1,8,4)
4833                     hsize_t block_size = H5FD_SILO_DEFAULT_BLOCK_SIZE;
4834                     int block_count = H5FD_SILO_DEFAULT_BLOCK_COUNT;
4835                     int log_stats = H5FD_SILO_DEFAULT_LOG_STATS;
4836                     int use_direct = H5FD_SILO_DEFAULT_USE_DIRECT;
4837 
4838                     if ((p = DBGetOption(opts, DBOPT_H5_SILO_BLOCK_SIZE)))
4839                         block_size = (hsize_t) (*((int*) p));
4840                     if ((p = DBGetOption(opts, DBOPT_H5_SILO_BLOCK_COUNT)))
4841                         block_count = *((int*) p);
4842                     if ((p = DBGetOption(opts, DBOPT_H5_SILO_LOG_STATS)))
4843                         log_stats = *((int*) p);
4844                     if ((p = DBGetOption(opts, DBOPT_H5_SILO_USE_DIRECT)))
4845                         use_direct = *((int*) p);
4846 
4847                     h5status |= H5Pset_fapl_silo(retval);
4848                     h5status |= H5Pset_silo_block_size_and_count(retval, block_size, block_count);
4849                     h5status |= H5Pset_silo_log_stats(retval, log_stats);
4850                     h5status |= H5Pset_silo_use_direct(retval, use_direct);
4851 #else
4852                     H5Pclose(retval);
4853                     return db_perror("Silo block VFD >= HDF5 1.8.4", E_NOTENABLEDINBUILD, me);
4854 #endif
4855                     break;
4856                 }
4857                 case DB_H5VFD_LOG:
4858                 {
4859                     int bufsize = 0;
4860                     int flags = H5FD_LOG_LOC_IO|H5FD_LOG_NUM_IO|H5FD_LOG_TIME_IO|H5FD_LOG_ALLOC;
4861                     char *logname = "silo_hdf5_log.out";
4862 
4863                     if ((p = DBGetOption(opts, DBOPT_H5_LOG_NAME)))
4864                         logname = (char*) p;
4865 
4866                     if ((p = DBGetOption(opts, DBOPT_H5_LOG_BUF_SIZE)))
4867                     {
4868                         bufsize = *((int*) p);
4869                         flags = H5FD_LOG_ALL;
4870                     }
4871 
4872                     h5status |= H5Pset_fapl_log(retval, logname, flags, bufsize);
4873                     break;
4874                 }
4875                 case DB_H5VFD_CORE:
4876                 case DB_H5VFD_FIC:
4877                 {
4878                     int inc = 1<<20; /* default of 1 Meg */
4879                     hbool_t bs = TRUE; /* default back store on */
4880 
4881                     /* get core allocation inc */
4882                     if ((p = DBGetOption(opts, DBOPT_H5_CORE_ALLOC_INC)))
4883                         inc = *((int*)p);
4884 
4885                     /* get backing store flag */
4886                     if ((p = DBGetOption(opts, DBOPT_H5_CORE_NO_BACK_STORE)))
4887                         bs = FALSE;
4888 
4889                     h5status |= H5Pset_fapl_core(retval, inc, bs);
4890 
4891                     /* Set up the file image too */
4892                     if (vfd == DB_H5VFD_FIC)
4893                     {
4894 #if HDF5_VERSION_GE(1,8,9)
4895                         H5FD_file_image_callbacks_t callbacks = {&image_malloc, &image_memcpy,
4896                                                                  &image_realloc, &image_free,
4897                                                                  &udata_copy, &udata_free,
4898                                                                  (void *)NULL};
4899                         db_hdf5_H5LT_file_image_ud_t *udata;
4900 
4901                         /* no possible default values can be specified for FIC */
4902                         int size = -1;
4903                         void *buf = 0;
4904 
4905                         /* cannot use backing store in this case */
4906                         h5status |= H5Pset_fapl_core(retval, inc, FALSE);
4907 
4908                         /* get file image size */
4909                         if ((p = DBGetOption(opts, DBOPT_H5_FIC_SIZE)))
4910                             size = *((int*)p);
4911                         else
4912                         {
4913                             H5Pclose(retval);
4914                             return db_perror("To use DB_H5VFD_FIC, you must specific DBOPT_H5_FIC_SIZE", E_BADARGS, me);
4915                         }
4916 
4917                         /* get file image buffer pointer */
4918                         if ((p = DBGetOption(opts, DBOPT_H5_FIC_BUF)))
4919                             buf = (void*)p;
4920                         else
4921                         {
4922                             H5Pclose(retval);
4923                             return db_perror("To use DB_H5VFD_FIC, you must specific DBOPT_H5_FIC_BUF", E_BADARGS, me);
4924                         }
4925 
4926                         /* Allocate buffer to communicate user data to callbacks */
4927                         if (NULL == (udata = (db_hdf5_H5LT_file_image_ud_t *)malloc(sizeof(db_hdf5_H5LT_file_image_ud_t))))
4928                         {
4929                             H5Pclose(retval);
4930                             return db_perror("Unable to allocate udata for FIC VFD", E_CALLFAIL, me);
4931                         }
4932 
4933                         /* Initialize udata with info about app buffer containing file image  and flags */
4934                         udata->app_image_ptr = buf;
4935                         udata->app_image_size = size;
4936                         udata->fapl_image_ptr = NULL;
4937                         udata->fapl_image_size = 0;
4938                         udata->fapl_ref_count = 0;
4939                         udata->vfd_image_ptr = NULL;
4940                         udata->vfd_image_size = 0;
4941                         udata->vfd_ref_count = 0;
4942                         udata->flags = db_hdf5_H5LT_FILE_IMAGE_DONT_COPY;
4943                         udata->ref_count = 1; /* corresponding to the first FAPL */
4944 
4945                         /* copy address of udata into callbacks */
4946                         callbacks.udata = (void *)udata;
4947 
4948                         /* Set file image callbacks */
4949                         h5status |= H5Pset_file_image_callbacks(retval, &callbacks);
4950 
4951                         /* Assign file image in user buffer to FAPL */
4952                         h5status |= H5Pset_file_image(retval, buf, (size_t)size);
4953 #else
4954                         H5Pclose(retval);
4955                         return db_perror("DB_H5VFD_FIC >= HDF5 1.8.9", E_NOTENABLEDINBUILD, me);
4956 #endif
4957                     }
4958 
4959                     break;
4960                 }
4961                 case DB_H5VFD_DIRECT:
4962                 {
4963 #ifdef H5_HAVE_DIRECT
4964                     int direct_block_size = (1<<12); /* 4 kilobytes (lustre default) */
4965                     int direct_alignment, direct_cbuf_size;
4966                     int align_min, align_val;
4967 
4968                     /* get direct block size */
4969                     if ((p = DBGetOption(opts, DBOPT_H5_DIRECT_BLOCK_SIZE)))
4970                         direct_block_size = *((int*)p);
4971 
4972                     /* get direct alignment */
4973                     if ((p = DBGetOption(opts, DBOPT_H5_DIRECT_MEM_ALIGN)))
4974                         direct_alignment = *((int*)p);
4975                     else
4976                         direct_alignment = direct_block_size;
4977 
4978                     /* get direct buffer size */
4979                     if ((p = DBGetOption(opts, DBOPT_H5_DIRECT_BUF_SIZE)))
4980                         direct_cbuf_size = *((int*)p);
4981                     else
4982                         direct_cbuf_size = direct_block_size * 256;
4983 
4984                     /* get overall alignment threshold */
4985                     if ((p = DBGetOption(opts, DBOPT_H5_ALIGN_MIN)))
4986                         align_min = *((int*)p);
4987                     else
4988                         align_min = direct_block_size / 2;
4989 
4990                     /* get overall alignment value */
4991                     if ((p = DBGetOption(opts, DBOPT_H5_ALIGN_VAL)))
4992                         align_val = *((int*)p);
4993                     else
4994                         align_val = direct_block_size;
4995 
4996                     h5status |= H5Pset_fapl_direct(retval, direct_alignment, direct_block_size, direct_cbuf_size);
4997                     h5status |= H5Pset_alignment(retval, align_min, align_val);
4998 #else
4999                     H5Pclose(retval);
5000                     return db_perror("HDF5 Direct VFD", E_NOTENABLEDINBUILD, me);
5001 #endif
5002                     break;
5003 
5004                 }
5005                 case DB_H5VFD_SPLIT:
5006                 {
5007                     int meta_opts_set_id = DB_FILE_OPTS_H5_DEFAULT_CORE;
5008                     int raw_opts_set_id = DB_FILE_OPTS_H5_DEFAULT_DEFAULT;
5009                     char *mext = "", *rext = "-raw";
5010                     hid_t meta_fapl = -1, raw_fapl = -1;
5011 
5012                     /* get meta opts_set_id */
5013                     if ((p = DBGetOption(opts, DBOPT_H5_META_FILE_OPTS)))
5014                         meta_opts_set_id = *((int*)p);
5015 
5016                     /* get meta fapl from opts_set_id */
5017                     meta_fapl = db_hdf5_process_file_options(meta_opts_set_id, mode);
5018 
5019                     /* get meta extension */
5020                     if ((p = DBGetOption(opts, DBOPT_H5_META_EXTENSION)))
5021                         mext = (char *) p;
5022 
5023                     /* get raw opts_set_id */
5024                     if ((p = DBGetOption(opts, DBOPT_H5_RAW_FILE_OPTS)))
5025                         raw_opts_set_id = *((int*)p);
5026 
5027                     /* get raw fapl from opts_set_id */
5028                     raw_fapl = db_hdf5_process_file_options(raw_opts_set_id, mode);
5029 
5030                     /* get raw extension */
5031                     if ((p = DBGetOption(opts, DBOPT_H5_RAW_EXTENSION)))
5032                         rext = (char *) p;
5033 
5034                     /* make sure the exentions are not identical */
5035                     if (!strcmp(mext, rext))
5036                     {
5037                         H5Pclose(retval);
5038                         return db_perror("meta & raw extensions must be different", E_CALLFAIL, me);
5039                     }
5040 
5041                     h5status |= H5Pset_fapl_split(retval, mext, meta_fapl, rext, raw_fapl);
5042                     H5Pclose(meta_fapl);
5043                     H5Pclose(raw_fapl);
5044                     break;
5045                 }
5046                 case DB_H5VFD_MPIO:
5047                 case DB_H5VFD_MPIP:
5048                 {
5049 #ifdef H5_HAVE_PARALLEL
5050                     MPI_Comm mpi_comm = MPI_COMM_SELF;
5051                     MPI_Info mpi_info;
5052                     int created_info = 0;
5053                     hbool_t use_gpfs_hints = TRUE;
5054 
5055                     /* get the communicator */
5056                     if ((p = DBGetOption(opts, DBOPT_H5_MPIO_COMM)))
5057                         mpi_comm = *((MPI_Comm *)p);
5058 
5059                     /* get the info */
5060                     if ((p = DBGetOption(opts, DBOPT_H5_MPIO_INFO)))
5061                         mpi_info = *((MPI_Info *)p);
5062                     else
5063                     {
5064                         MPI_Info_create(&mpi_info);
5065                         created_info = 1;
5066                     }
5067 
5068                     /* get use_gpfs_hints flag */
5069                     if ((p = DBGetOption(opts, DBOPT_H5_MPIP_NO_GPFS_HINTS)))
5070                         use_gpfs_hints = FALSE;
5071 
5072                     if (vfd == DB_H5VFD_MPIO)
5073                     {
5074                         h5status |= H5Pset_fapl_mpio(retval, mpi_comm, mpi_info);
5075                         if (created_info) MPI_Info_free(&mpi_info);
5076                     }
5077                     else
5078                     {
5079                         h5status |= H5Pset_fapl_mpiposix(retval, mpi_comm, use_gpfs_hints);
5080                     }
5081 #else
5082                     H5Pclose(retval);
5083                     return db_perror("HDF5 MPI VFD", E_NOTENABLEDINBUILD, me);
5084 #endif
5085                     break;
5086                 }
5087                 case DB_H5VFD_FAMILY:
5088                 {
5089                     int memb_size = (1<<30); /* 1 gigabyte */
5090                     int memb_opts_set_id = DB_FILE_OPTS_H5_DEFAULT_DEFAULT;
5091                     hid_t memb_fapl;
5092 
5093                     /* get size of files in family */
5094                     if ((p = DBGetOption(opts, DBOPT_H5_FAM_SIZE)))
5095                         memb_size = *((int*)p);
5096 
5097                     /* get underlying family fapl */
5098                     if ((p = DBGetOption(opts, DBOPT_H5_FAM_FILE_OPTS)))
5099                         memb_opts_set_id = *((int*)p);
5100 
5101                     memb_fapl = db_hdf5_process_file_options(memb_opts_set_id, mode);
5102                     h5status |= H5Pset_fapl_family(retval, memb_size, memb_fapl);
5103                     H5Pclose(memb_fapl);
5104                 }
5105             }
5106 
5107             /* handle overall alignment requests */
5108             if ((p = DBGetOption(opts, DBOPT_H5_ALIGN_MIN)))
5109             {
5110                 int align_min = *((int*)p);
5111                 int align_val = align_min * 2;
5112 
5113                 /* get overall alignment value */
5114                 if ((p = DBGetOption(opts, DBOPT_H5_ALIGN_VAL)))
5115                     align_val = *((int*)p);
5116 
5117                 h5status |= H5Pset_alignment(retval, align_min, align_val);
5118             }
5119 
5120             /* handle meta block size */
5121             if ((p = DBGetOption(opts, DBOPT_H5_META_BLOCK_SIZE)))
5122             {
5123                 int size = *((int*)p);
5124                 h5status |= H5Pset_meta_block_size(retval, size);
5125             }
5126 
5127             /* handle raw block size */
5128             if ((p = DBGetOption(opts, DBOPT_H5_SMALL_RAW_SIZE)))
5129             {
5130                 int size = *((int*)p);
5131                 h5status |= H5Pset_small_data_block_size(retval, size);
5132             }
5133 
5134             /* handle sieve buffer size */
5135             if ((p = DBGetOption(opts, DBOPT_H5_SIEVE_BUF_SIZE)))
5136             {
5137                 int size = *((int*)p);
5138                 h5status |= H5Pset_sieve_buf_size(retval, size);
5139             }
5140 
5141             /* handle cache settings */
5142             if ((p = DBGetOption(opts, DBOPT_H5_CACHE_NELMTS)))
5143             {
5144                 int nelmts = *((int*)p);
5145                 int nbytes = nelmts * sizeof(double);
5146                 double policy = 1.0;
5147 
5148                 /* get size in bytes */
5149                 if ((p = DBGetOption(opts, DBOPT_H5_CACHE_NBYTES)))
5150                     nbytes = *((int*)p);
5151 
5152                 /* get pre-emption policy */
5153                 if ((p = DBGetOption(opts, DBOPT_H5_CACHE_POLICY)))
5154                     policy = *((double*)p);
5155 
5156                 h5status |= H5Pset_cache(retval, 0, nelmts, nbytes, policy);
5157             }
5158         }
5159     }
5160 
5161     if (h5status < 0)
5162     {
5163         H5Pclose(retval);
5164         return db_perror("Problem setting HDF5 VFD options", E_CALLFAIL, me);
5165     }
5166 
5167     return retval;
5168 }
5169 
5170 /*-------------------------------------------------------------------------
5171  * Function:    db_hdf5_file_accprops
5172  *
5173  * Purpose:     Create file access property lists
5174  *
5175  * Programmer:  Mark C. Miller, Aug 1, 2006
5176  *
5177  * Notes: The least significant 4 bits in the 'driver' argument passed to
5178  * an open or create call are stripped off and the value shifted 4 to the
5179  * right to produce the 'subtype' that is passed into driver's open or
5180  * create implementations. So, the 'subtype' arriving here is a 28 bit
5181  * number.
5182  *
5183  * Modifications:
5184  *   Mark C. Miller, Thu Feb 11 09:38:32 PST 2010
5185  *   Added support for split vfd. Changed how allocation inc for core
5186  *   and split vfd's is handled. Changed int values in case to symbolics.
5187  *-------------------------------------------------------------------------
5188  */
5189 PRIVATE hid_t
db_hdf5_file_accprops(int subtype,int mode)5190 db_hdf5_file_accprops(int subtype, int mode)
5191 {
5192     int opts_set_id = subtype & 0x0000003F;
5193     return db_hdf5_process_file_options(opts_set_id, mode);
5194 }
5195 
5196 /*-------------------------------------------------------------------------
5197  * Function:    db_hdf5_finish_open
5198  *
5199  * Purpose:     Completes opening of a Silo/HDF5 file.
5200  *
5201  * Return:      Success:        0
5202  *
5203  *              Failure:        -1
5204  *
5205  * Programmer:  Robb Matzke
5206  *              Friday, March 26, 1999
5207  *
5208  * Modifications:
5209  *
5210  *   Mark C. Miller, Tue Feb  3 09:48:23 PST 2009
5211  *   Changed dbfile arg from public DBfile* to private DBfile_hdf5*
5212  *   Changed return type from int to DBfile*
5213  *   Removed PROTECT/UNWIND/END_PROTECT and replaced UNWIND() calls with
5214  *   return silo_db_close(). This is because UNWIND was causing it to
5215  *   NOT correctly handle the case in which the given filename was NOT
5216  *   an HDF5 file and properly RETURNing NULL when necessary.
5217  *-------------------------------------------------------------------------
5218  */
5219 PRIVATE DBfile*
db_hdf5_finish_open(DBfile_hdf5 * dbfile)5220 db_hdf5_finish_open(DBfile_hdf5 *dbfile)
5221 {
5222     static char *me = "db_hdf5_finish_open";
5223     hid_t       cwg=-1, link=-1, attr=-1;
5224     int         tmp, target=DB_LOCAL;
5225 
5226     /* Open "/" as current working group */
5227     if ((cwg=H5Gopen(dbfile->fid, "/"))<0) {
5228         db_perror("root group", E_CALLFAIL, me);
5229         return silo_db_close((DBfile*) dbfile);
5230     }
5231 
5232     /*
5233      * Open the link directory. If it doesn't exist then create one (it
5234      * might not exist in old SAMI files).
5235      */
5236     H5E_BEGIN_TRY {
5237         link = H5Gopen(dbfile->fid, LINKGRP);
5238     } H5E_END_TRY;
5239     if (link<0 && (link=H5Gcreate(dbfile->fid, LINKGRP, 0))<0) {
5240         db_perror("link group", E_CALLFAIL, me);
5241         return silo_db_close((DBfile*) dbfile);
5242     }
5243 
5244     /*
5245      * Read the targetting information from the `target' attribute
5246      * of the link group if there is one, otherwise assume DB_LOCAL
5247      */
5248     H5E_BEGIN_TRY {
5249         attr = H5Aopen_name(link, "target");
5250     } H5E_END_TRY;
5251     if (attr>=0 &&
5252         H5Aread(attr, H5T_NATIVE_INT, &tmp)>=0 &&
5253         H5Aclose(attr)>=0) {
5254         target = tmp;
5255     }
5256 
5257     /*
5258      * Initialize the file struct. Use the same target architecture that
5259      * was specified when the file was created.
5260      */
5261     dbfile->cwg = cwg;
5262     dbfile->link = link;
5263     db_hdf5_InitCallbacks(dbfile, target);
5264 
5265     return (DBfile*) dbfile;
5266 }
5267 
5268 /*-------------------------------------------------------------------------
5269  * Function:    db_hdf5_finish_create
5270  *
5271  * Purpose:     Finish creating a file.
5272  *
5273  * Return:      Success:        0
5274  *
5275  *              Failure:        -1
5276  *
5277  * Programmer:  Robb Matzke
5278  *              Friday, March 26, 1999
5279  *
5280  * Modifications:
5281  *   Robb Matzke, 1999-08-17
5282  *   The file information string is written as a variable in the
5283  *   file instead of as a comment on the root group.
5284  *
5285  *   Mark C. Miller, Tue Feb  3 09:48:23 PST 2009
5286  *   Changed dbfile arg from public DBfile* to private DBfile_hdf5*
5287  *   Changed return type from int to DBfile*
5288  *   Removed PROTECT/UNWIND/END_PROTECT and replaced UNWIND() calls with
5289  *   return silo_db_close(). This is because UNWIND was causing it to
5290  *   NOT correctly handle the case in which the given filename was NOT
5291  *   an HDF5 file and properly RETURNing NULL when necessary.
5292  *
5293  *   Mark C. Miller, Mon Jun 28 20:19:35 PDT 2010
5294  *   Added logic to handle HDF5 header/lib version numbers separately.
5295  *
5296  *   Mark C. Miller, Thu Aug 30 17:44:56 PDT 2012
5297  *   Added new, internal, db_hdf5_WriteCKZ method to enable caller to
5298  *   indicate if filters should be turned off. This is useful for disabling
5299  *   compression or checksuming for tiny metadata datasets such as hdf5
5300  *   library info.
5301  *-------------------------------------------------------------------------
5302  */
5303 PRIVATE DBfile*
db_hdf5_finish_create(DBfile_hdf5 * dbfile,int target,char const * finfo)5304 db_hdf5_finish_create(DBfile_hdf5 *dbfile, int target, char const *finfo)
5305 {
5306     static char *me = "db_hdf5_finish_create";
5307     hid_t       attr=-1;
5308     int         size;
5309     char        hdf5VString[64];
5310     unsigned    majno, minno, relno;
5311     const       int nofilters = 1;
5312 
5313     /* Open root group as CWG */
5314     if ((dbfile->cwg=H5Gopen(dbfile->fid, "/"))<0) {
5315         db_perror("root group", E_CALLFAIL, me);
5316         return silo_db_close((DBfile*) dbfile);
5317     }
5318 
5319     /* Create the link group */
5320     if ((dbfile->link=H5Gcreate(dbfile->fid, LINKGRP, 0))<0) {
5321         db_perror("link group", E_CALLFAIL, me);
5322         return silo_db_close((DBfile*) dbfile);
5323     }
5324 
5325     /* Callbacks */
5326     db_hdf5_InitCallbacks(dbfile, target);
5327 
5328     /*
5329      * Write the target architecture into the `target' attribute of the
5330      * link group so we can retrieve it later when the file is reopened.
5331      */
5332     if ((attr=H5Acreate(dbfile->link, "target", dbfile->T_int, SCALAR,
5333                         H5P_DEFAULT))<0 ||
5334         H5Awrite(attr, H5T_NATIVE_INT, &target)<0 ||
5335         H5Aclose(attr)<0) {
5336         db_perror("targetinfo", E_CALLFAIL, me);
5337         return silo_db_close((DBfile*) dbfile);
5338     }
5339 
5340     if (finfo) {
5341         /* Write file info as a variable in the file */
5342         size = strlen(finfo)+1;
5343         if (db_hdf5_WriteCKZ((DBfile*)dbfile, "_fileinfo", (void*)finfo, &size, 1, DB_CHAR, nofilters)<0) {
5344             db_perror("fileinfo", E_CALLFAIL, me);
5345             return silo_db_close((DBfile*) dbfile);
5346         }
5347     }
5348 
5349     /*
5350      * Write HDF5 library version information to the file
5351      */
5352     H5get_libversion(&majno, &minno, &relno);
5353     if (majno != H5_VERS_MAJOR || minno != H5_VERS_MINOR || relno != H5_VERS_RELEASE)
5354     {
5355         /* Since headers and libs don't match, write information about headers first */
5356         sprintf(hdf5VString, "hdf5-%d.%d.%d%s%s", H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE,
5357             strlen(H5_VERS_SUBRELEASE) ? "-" : "", H5_VERS_SUBRELEASE);
5358         size = strlen(hdf5VString)+1;
5359         if (db_hdf5_WriteCKZ((DBfile*)dbfile, "_hdf5incinfo", hdf5VString, &size, 1, DB_CHAR, nofilters)<0) {
5360             db_perror("_hdf5incinfo", E_CALLFAIL, me);
5361             return silo_db_close((DBfile*) dbfile);
5362         }
5363     }
5364 
5365     sprintf(hdf5VString, "hdf5-%d.%d.%d", majno, minno, relno);
5366     size = strlen(hdf5VString)+1;
5367     if (db_hdf5_WriteCKZ((DBfile*)dbfile, "_hdf5libinfo", hdf5VString, &size, 1, DB_CHAR, nofilters)<0) {
5368         db_perror("_hdf5libinfo", E_CALLFAIL, me);
5369         return silo_db_close((DBfile*) dbfile);
5370     }
5371 
5372     return (DBfile*) dbfile;
5373 }
5374 
5375 /*-------------------------------------------------------------------------
5376  * Function:    db_hdf5_initiate_close
5377  *
5378  * Purpose:     Start closing the file.
5379  *
5380  * Return:      Success:        0
5381  *
5382  *              Failure:        -1
5383  *
5384  * Programmer:  Robb Matzke
5385  *              Friday, March 26, 1999
5386  *
5387  * Modifications:
5388  *
5389  *   Mark C. Miller, Wed Jul 14 20:53:33 PDT 2010
5390  *   Added logic to check for open objects and try to print their names.
5391  *-------------------------------------------------------------------------
5392  */
5393 PRIVATE int
db_hdf5_initiate_close(DBfile * _dbfile)5394 db_hdf5_initiate_close(DBfile *_dbfile)
5395 {
5396     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
5397     static char *me = "db_hdf5_initiate_close";
5398     int i;
5399 
5400     /* Close all datasets in the circular buffer */
5401     for (i=0; i<NDSETTAB; i++) {
5402         FREE(dbfile->dsettab[i]);
5403         dbfile->dsettab[i] = NULL;
5404     }
5405     dbfile->dsettab_ins = dbfile->dsettab_rem = 0;
5406 
5407     /* Close current working group and link group */
5408     if (H5Gclose(dbfile->cwg)<0 || H5Gclose(dbfile->link)<0) {
5409         return db_perror("closing", E_CALLFAIL, me);
5410     }
5411     dbfile->cwg = -1;
5412     dbfile->link = -1;
5413 
5414     if (dbfile->cwg_name)
5415         free(dbfile->cwg_name);
5416     dbfile->cwg_name = NULL;
5417 
5418     /* Check for any open objects in this file */
5419 #if HDF5_VERSION_GE(1,6,0)
5420     if (SILO_Globals._db_err_level_drvr == DB_ALL)
5421     {
5422         const unsigned int obj_flags = H5F_OBJ_LOCAL | H5F_OBJ_DATASET |
5423             H5F_OBJ_GROUP | H5F_OBJ_DATATYPE | H5F_OBJ_ATTR;
5424 
5425         int noo = H5Fget_obj_count(dbfile->fid, obj_flags);
5426         if (noo > 0)
5427         {
5428             int n;
5429             char msg[4096];
5430             hid_t *ooids = (hid_t *) malloc(noo * sizeof(hid_t));
5431             sprintf(msg, "Internal Silo error: %d objects left open in file: ", noo);
5432 #if HDF5_VERSION_GE(1,6,5)
5433             H5Fget_obj_ids(dbfile->fid, obj_flags, noo, ooids);
5434 #else
5435             H5Fget_obj_ids(dbfile->fid, obj_flags, noo, ooids);
5436 #endif
5437             n = strlen(msg);
5438             for (i = 0; i < noo && n < sizeof(msg); i++)
5439             {
5440                 char name[256], tmp[256];
5441                 H5Iget_name(ooids[i], name, sizeof(name));
5442                 sprintf(tmp, "\"%.235s\" (id=%d), ", name, ooids[i]);
5443                 if ((strlen(msg) + strlen(tmp) + 1) >= sizeof(msg))
5444                     break;
5445                 strcat(msg, tmp);
5446                 n += strlen(tmp);
5447             }
5448             free(ooids);
5449 
5450             return db_perror(dbfile->pub.name, E_CALLFAIL, msg);
5451         }
5452     }
5453 #endif
5454 
5455     // Tell HDF5 to garbage collect (whatever it can)
5456     H5garbage_collect();
5457 
5458     return 0;
5459 }
5460 
5461 /*-------------------------------------------------------------------------
5462  * Function:    db_hdf5_Open
5463  *
5464  * Purpose:     Opens an hdf5 file that already exists.
5465  *
5466  * Return:      Success:        Ptr to the file struct
5467  *
5468  *              Failure:        NULL, db_errno set.
5469  *
5470  * Programmer:  Robb Matzke
5471  *              Tuesday, February  9, 1999
5472  *
5473  * Modifications:
5474  *
5475  *   Mark C. Miller, Tue Feb  1 18:13:28 PST 2005
5476  *   Added call to H5Eset_auto(). Open can be called outside of init
5477  *
5478  *   Mark C. Miller, Tue Feb  3 09:48:23 PST 2009
5479  *   Removed PROTECT/UNWIND/END_PROTECT and replaced UNWIND() calls with
5480  *   return silo_db_close(). This is because UNWIND was causing it to
5481  *   NOT correctly handle the case in which the given filename was NOT
5482  *   an HDF5 file and properly RETURNing NULL when necessary.
5483  *
5484  *   Mark C. Miller, Wed Feb 25 09:37:10 PST 2009
5485  *   Changed error code for failure to open to indicate better error
5486  *   message.
5487  *
5488  *   Mark C. Miller, Thu Feb 11 09:37:41 PST 2010
5489  *   Added logic to set HDF5's error output based on Silo's settings.
5490  *-------------------------------------------------------------------------
5491  */
5492 INTERNAL DBfile *
db_hdf5_Open(char const * name,int mode,int opts_set_id)5493 db_hdf5_Open(char const *name, int mode, int opts_set_id)
5494 {
5495     DBfile_hdf5 *dbfile=NULL;
5496     hid_t       fid=-1, faprops=-1;
5497     hid_t      *fidp = 0;
5498     unsigned    hmode;
5499     static char *me = "db_hdf5_Open";
5500 
5501     if (SILO_Globals._db_err_level_drvr == DB_ALL)
5502         H5Eset_auto((H5E_auto1_t) H5Eprint1, stderr);
5503     else
5504         H5Eset_auto(NULL, NULL);
5505 
5506     /* File access mode */
5507     if (DB_READ==mode) {
5508         hmode = H5F_ACC_RDONLY;
5509     } else if (DB_APPEND==mode) {
5510         hmode = H5F_ACC_RDWR;
5511     } else {
5512         db_perror("mode", E_INTERNAL, me);
5513         return NULL;
5514     }
5515 
5516     faprops = db_hdf5_file_accprops(opts_set_id, mode);
5517 
5518     /* Open existing hdf5 file */
5519     if ((fid=H5Fopen(name, hmode, faprops))<0) {
5520         H5Pclose(faprops);
5521         db_perror(name, E_DRVRCANTOPEN, me);
5522         return NULL;
5523     }
5524 
5525     H5Pclose(faprops);
5526 
5527     /* Create silo file struct */
5528     if (NULL==(dbfile=(DBfile_hdf5*)calloc(1, sizeof(DBfile_hdf5)))) {
5529         db_perror(name, E_NOMEM, me);
5530         return NULL;
5531     }
5532     dbfile->pub.name = STRDUP(name);
5533     dbfile->pub.type = DB_HDF5;
5534     dbfile->pub.Grab = FALSE;
5535     fidp = (hid_t *) malloc(sizeof(hid_t));
5536     *fidp = fid;
5537     dbfile->pub.GrabId = (void*) fidp;
5538     dbfile->fid = fid;
5539     return db_hdf5_finish_open(dbfile);
5540 }
5541 
5542 /*-------------------------------------------------------------------------
5543  * Function:    db_hdf5_Create
5544  *
5545  * Purpose:     Creates an hdf5 file and begins the process of writing mesh
5546  *              and mesh-related data into that file.
5547  *
5548  *              The `target' is always assumed to be the local architecture.
5549  *
5550  * Return:      Success:        Pointer to a new file
5551  *
5552  *              Failure:        NULL
5553  *
5554  * Programmer:  Robb Matzke
5555  *              Tuesday, February  9, 1999
5556  *
5557  * Modifications:
5558  *
5559  *   Mark C. Miller, Tue Feb  1 18:13:28 PST 2005
5560  *   Added call to H5Eset_auto(). Create can be called outside of init
5561  *
5562  *   Mark C. Miller, Tue Feb  3 09:48:23 PST 2009
5563  *   Removed PROTECT/UNWIND/END_PROTECT and replaced UNWIND() calls with
5564  *   return silo_db_close(). This is because UNWIND was causing it to
5565  *   NOT correctly handle the case in which the given filename was NOT
5566  *   an HDF5 file and properly RETURNing NULL when necessary.
5567  *
5568  *   Mark C. Miller, Thu Feb 11 09:37:41 PST 2010
5569  *   Added logic to set HDF5's error output based on Silo's settings.
5570  *-------------------------------------------------------------------------
5571  */
5572 INTERNAL DBfile *
db_hdf5_Create(char const * name,int mode,int target,int opts_set_id,char const * finfo)5573 db_hdf5_Create(char const *name, int mode, int target, int opts_set_id, char const *finfo)
5574 {
5575     DBfile_hdf5 *dbfile=NULL;
5576     hid_t       fid=-1, faprops=-1;
5577     hid_t      *fidp = 0;
5578     static char *me = "db_hdf5_Create";
5579 
5580     /* Turn off error messages from the hdf5 library */
5581     if (SILO_Globals._db_err_level_drvr == DB_ALL)
5582         H5Eset_auto((H5E_auto1_t) H5Eprint1, stderr);
5583     else
5584         H5Eset_auto(NULL, NULL);
5585 
5586     faprops = db_hdf5_file_accprops(opts_set_id, mode);
5587 
5588         /* Create or open hdf5 file */
5589     if (DB_CLOBBER==mode) {
5590         /* If we ever use checksumming (which requires chunked datasets),
5591          * HDF5's BTree's will effect storage overhead. Since Silo really
5592          * doesn't support growing/shrinking datasets, we just use a value
5593          * of '1' for istore_k */
5594         hid_t fcprops = H5Pcreate(H5P_FILE_CREATE);
5595         H5Pset_istore_k(fcprops, 1);
5596         fid = H5Fcreate(name, H5F_ACC_TRUNC, fcprops, faprops);
5597         H5Pclose(fcprops);
5598         H5Glink(fid, H5G_LINK_HARD, "/", ".."); /*don't care if fails*/
5599     } else if (DB_NOCLOBBER==mode) {
5600         fid = H5Fopen(name, H5F_ACC_RDWR, faprops);
5601     } else {
5602         H5Pclose(faprops);
5603         db_perror("mode", E_BADARGS, me);
5604         return NULL;
5605     }
5606     if (fid<0) {
5607         H5Pclose(faprops);
5608         db_perror(name, E_NOFILE, me);
5609         return NULL;
5610     }
5611 
5612     H5Pclose(faprops);
5613 
5614     /* Create silo file struct */
5615     if (NULL==(dbfile=(DBfile_hdf5 *)calloc(1, sizeof(DBfile_hdf5)))) {
5616         db_perror(name, E_NOMEM, me);
5617         return NULL;
5618     }
5619     dbfile->pub.name = STRDUP(name);
5620     dbfile->pub.type = DB_HDF5;
5621     dbfile->pub.Grab = FALSE;
5622     fidp = (hid_t *) malloc(sizeof(hid_t));
5623     *fidp = fid;
5624     dbfile->pub.GrabId = (void*) fidp;
5625     dbfile->fid = fid;
5626     return db_hdf5_finish_create(dbfile, target, finfo);
5627 }
5628 
5629 /*-------------------------------------------------------------------------
5630  * Function:    db_hdf5_Close
5631  *
5632  * Purpose:     Closes an hdf5 file and frees memory associated with the
5633  *              file.
5634  *
5635  * Return:      Success:        0
5636  *
5637  *              Failure:        -1
5638  *
5639  * Programmer:  Robb Matzke
5640  *              Thursday, February 11, 1999
5641  *
5642  * Modifications:
5643  *   Mark C. Miller, Thu Jul 17 15:05:16 PDT 2008
5644  *   Added call to FreeNodelists for this file.
5645  *
5646  *   Mark C. Miller, Tue Feb  3 09:52:51 PST 2009
5647  *   Moved code to free pub.GrabId and set Grab related entries to zero to
5648  *   silo_db_close() function and then added a call to that function here.
5649  *-------------------------------------------------------------------------
5650  */
5651 SILO_CALLBACK int
db_hdf5_Close(DBfile * _dbfile)5652 db_hdf5_Close(DBfile *_dbfile)
5653 {
5654     int retval = 0;
5655     DBfile_hdf5    *dbfile = (DBfile_hdf5*)_dbfile;
5656     static char *me = "db_hdf5_Close";
5657 
5658     if (dbfile) {
5659 
5660         PROTECT {
5661 
5662             FreeNodelists(dbfile, 0);
5663 
5664             /* Free the private parts of the file */
5665             if (db_hdf5_initiate_close((DBfile*)dbfile)<0 ||
5666                 H5Fclose(dbfile->fid)<0)
5667             {
5668                 db_perror(dbfile->pub.name, E_CALLFAIL, me);
5669                 UNWIND();
5670             }
5671             dbfile->fid = -1;
5672 
5673             /* Free the public parts of the file */
5674             silo_db_close(_dbfile);
5675 
5676         } CLEANUP {
5677             retval = -1;
5678             dbfile->fid = -1;
5679             silo_db_close(_dbfile);
5680         } END_PROTECT;
5681     }
5682 
5683     /* work-around leaks in HDF5, version 1.8.4 only */
5684 #if HDF5_VERSION_GE(1,8,4) && !HDF5_VERSION_GE(1,8,5)
5685     if (db_num_registered_files() == 0)
5686     {
5687         T_str_stype_set = 0;
5688         H5close();
5689     }
5690 #endif
5691 
5692     return retval;
5693 }
5694 
5695 /*-------------------------------------------------------------------------
5696  * Function:    db_hdf5_Filters
5697  *
5698  * Purpose:     Output the name of this device driver to the specified stream.
5699  *
5700  * Return:      Success:        0
5701  *
5702  *              Failure:        never fails
5703  *
5704  * Programmer:  Robb Matzke
5705  *              Wednesday, March 17, 1999
5706  *
5707  * Modifications:
5708  *
5709  *-------------------------------------------------------------------------
5710  */
5711 /*ARGSUSED*/
5712 SILO_CALLBACK int
db_hdf5_Filters(DBfile * _dbfile,FILE * stream)5713 db_hdf5_Filters(DBfile *_dbfile, FILE *stream)
5714 {
5715     fprintf(stream, "HDF5 Device Driver\n");
5716     return 0;
5717 }
5718 
5719 /*-------------------------------------------------------------------------
5720  * Function:    db_hdf5_MkDir
5721  *
5722  * Purpose:     Create a new directory.
5723  *
5724  * Return:      Success:        0
5725  *
5726  *              Failure:        -1
5727  *
5728  * Programmer:  Robb Matzke
5729  *              Wednesday, February 10, 1999
5730  *
5731  * Modifications:
5732  *              Robb Matzke, 1999-10-13
5733  *              Uses the current working group instead of the root group when
5734  *              adding the `..' entry.
5735  *-------------------------------------------------------------------------
5736  */
5737 SILO_CALLBACK int
db_hdf5_MkDir(DBfile * _dbfile,char const * name)5738 db_hdf5_MkDir(DBfile *_dbfile, char const *name)
5739 {
5740     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
5741     static char *me = "db_hdf5_MkDir";
5742     char        *dotdot = NULL,  *parent=NULL, *t=NULL;
5743     hid_t       grp = -1;
5744 
5745     PROTECT {
5746         /* Create the new group */
5747         if ((grp=H5Gcreate(dbfile->cwg, name, 0))<0) {
5748             db_perror(name, E_CALLFAIL, me);
5749             UNWIND();
5750         }
5751 
5752         /* What is the name of the parent directory of the new directory? */
5753         parent = STRDUP(name);
5754         t = parent+strlen(parent);
5755         while (t>parent && '/'==t[-1]) *(--t) = '\0';   /*trailing slashes*/
5756         while (t>parent && '/'!=t[-1]) *(--t) = '\0';   /*last component*/
5757         if (!*parent) strcpy(parent, '/'==*name?"/":".");
5758 
5759         /* What is the name of the `..' entry? */
5760         dotdot = (char *)malloc(strlen(name)+4);
5761         strcpy(dotdot, name);
5762         strcat(dotdot, "/..");
5763 
5764         /* Make the `..' point to the parent */
5765         if (H5Glink(dbfile->cwg, H5G_LINK_HARD, parent, dotdot)<0) {
5766             db_perror(dotdot, E_CALLFAIL, me);
5767             UNWIND();
5768         }
5769 
5770         /* Close everything */
5771         H5Gclose(grp);
5772         free(dotdot);
5773         free(parent);
5774 
5775     } CLEANUP {
5776         H5E_BEGIN_TRY {
5777             H5Gclose(grp);
5778         } H5E_END_TRY;
5779         if (dotdot) free(dotdot);
5780         if (parent) free(parent);
5781     } END_PROTECT;
5782 
5783     return 0;
5784 }
5785 
5786 /*-------------------------------------------------------------------------
5787  * Function:    db_hdf5_SetDir
5788  *
5789  * Purpose:     Set the current working directory.
5790  *
5791  * Return:      Success:        0
5792  *
5793  *              Failure:        -1
5794  *
5795  * Programmer:  Robb Matzke
5796  *              Wednesday, February 10, 1999
5797  *
5798  * Modifications:
5799  *
5800  *   Mark C. Miller, Thu Nov  5 10:55:46 PST 2009
5801  *   Added some 'hidden' logic to support view of contents of /.silo dir
5802  *   from browser. Its 'hidden' because I have no intention of letting
5803  *   users know about it.
5804  *-------------------------------------------------------------------------
5805  */
5806 SILO_CALLBACK int
db_hdf5_SetDir(DBfile * _dbfile,char const * name)5807 db_hdf5_SetDir(DBfile *_dbfile, char const *name)
5808 {
5809     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
5810     static char *me = "db_hdf5_SetDir";
5811     hid_t       newdir = -1;
5812 
5813     PROTECT {
5814         if ((newdir=H5Gopen(dbfile->cwg, name))<0 ||
5815             (strcmp(name,"/.silo")!=0 &&
5816             H5Gget_objinfo(newdir, "..", FALSE, NULL)<0)) {
5817             db_perror(name, E_NOTFOUND, me);
5818             UNWIND();
5819         }
5820 
5821         H5Gclose(dbfile->cwg);
5822         dbfile->cwg = newdir;
5823 
5824         if (dbfile->cwg_name) {
5825             char *new_cwg_name = db_absoluteOf_path(dbfile->cwg_name, name);
5826             free(dbfile->cwg_name);
5827             dbfile->cwg_name = new_cwg_name;
5828         }
5829     } CLEANUP {
5830         H5E_BEGIN_TRY {
5831             H5Gclose(newdir);
5832         } H5E_END_TRY;
5833     } END_PROTECT;
5834 
5835     return 0;
5836 }
5837 
5838 /*-------------------------------------------------------------------------
5839  * Function:    db_hdf5_GetDir
5840  *
5841  * Purpose:     Writes the absolute name of the current working directory
5842  *              into the NAME argument without checking for overflow (if NAME
5843  *              is not large enough then a core dump is likely).
5844  *
5845  *              The name is computed by following the `..' entries out of
5846  *              each directory and then looking for the entry in the parent
5847  *              that matches the object id of the current directory.
5848  *
5849  * Return:      Success:        0
5850  *
5851  *              Failure:        -1
5852  *
5853  * Programmer:  Robb Matzke
5854  *              Thursday, February 11, 1999
5855  *
5856  * Modifications:
5857  *
5858  *-------------------------------------------------------------------------
5859  */
5860 SILO_CALLBACK int
db_hdf5_GetDir(DBfile * _dbfile,char * name)5861 db_hdf5_GetDir(DBfile *_dbfile, char *name/*out*/)
5862 {
5863     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
5864     static char *me = "db_hdf5_GetDir";
5865     hid_t       cwg = -1, parent = -1;
5866     H5G_stat_t  cur_sb, par_sb;
5867     int         i, ncomps=0;
5868     silo_hdf5_comp_t    comp[100];
5869 
5870     /* Return quickly if name is cached. But, confirm the name first. */
5871     if (dbfile->cwg_name) {
5872         H5G_stat_t sb;
5873         herr_t status;
5874         H5E_BEGIN_TRY {
5875             status = H5Gget_objinfo(dbfile->cwg, dbfile->cwg_name, TRUE, &sb);
5876         } H5E_END_TRY;
5877         if (status>=0)
5878         {
5879             strcpy(name, dbfile->cwg_name);
5880             return 0;
5881         }
5882     }
5883 
5884     memset(comp, 0, sizeof comp);
5885     PROTECT {
5886         cwg = H5Gopen(dbfile->cwg, ".");
5887         if (H5Gget_objinfo(cwg, ".", TRUE, &cur_sb)<0) {
5888             db_perror("stat(\".\")", E_CALLFAIL, me);
5889             UNWIND();
5890         }
5891 
5892         while ((size_t)ncomps<NELMTS(comp)) {
5893             /*
5894              * Get info about parent. If parent object ID is the same as
5895              * current group object ID then we must be at the root.
5896              */
5897             if (H5Gget_objinfo(cwg, "..", TRUE, &par_sb)<0) {
5898                 db_perror("stat(\"..\")", E_CALLFAIL, me);
5899                 UNWIND();
5900             }
5901             if (cur_sb.objno[0]==par_sb.objno[0] &&
5902                 cur_sb.objno[1]==par_sb.objno[1]) break;
5903 
5904             /*
5905              * Iterate over entries in parent to find first name that has the
5906              * same object ID as the current group and use that as the
5907              * component of the name
5908              */
5909             if ((parent=H5Gopen(cwg, ".."))<0) {
5910                 db_perror("no `..' entry", E_NOTFOUND, me);
5911                 UNWIND();
5912             }
5913             comp[ncomps].objno[0] = cur_sb.objno[0];
5914             comp[ncomps].objno[1] = cur_sb.objno[1];
5915             if (H5Giterate(parent, ".", NULL, find_objno, comp+ncomps)<=0) {
5916                 db_perror("inconsistent directory structure", E_CALLFAIL, me);
5917                 UNWIND();
5918             }
5919 
5920             /* Move upward in the directory try */
5921             H5Gclose(cwg);
5922             cwg = parent;
5923             parent = -1;
5924             cur_sb = par_sb;
5925             ncomps++;
5926         }
5927 
5928         /* Build the name */
5929         if (0==ncomps) {
5930             strcpy(name, "/");
5931         } else {
5932             name[0] = '\0';
5933             for (i=ncomps-1; i>=0; --i) {
5934                 strcat(name, "/");
5935                 strcat(name, comp[i].name);
5936                 free(comp[i].name);
5937             }
5938         }
5939 
5940         /* Close everything */
5941         H5Gclose(cwg);
5942         if (parent>=0) H5Gclose(parent);
5943 
5944         /* Cache the name for later */
5945         if (dbfile->cwg_name)
5946             free(dbfile->cwg_name);
5947         dbfile->cwg_name = strdup(name);
5948 
5949     } CLEANUP {
5950         H5E_BEGIN_TRY {
5951             H5Gclose(cwg);
5952             H5Gclose(parent);
5953         } H5E_END_TRY;
5954         for (i=0; i<=ncomps && (size_t)i<NELMTS(comp); i++) {
5955             if (comp->name) free(comp->name);
5956         }
5957     } END_PROTECT;
5958 
5959     return 0;
5960 }
5961 
5962 /*-------------------------------------------------------------------------
5963  * Function:    copy_dir
5964  *
5965  * Purpose:     Support, recursive function, for CpDir using HDF5's
5966  *              H5Giterate method.
5967  *
5968  * Return:      Success:        0
5969  *
5970  *              Failure:        -1
5971  *
5972  * Programmer:  Mark C. Miller, Wed Aug  6 18:29:53 PDT 2008
5973  *
5974  *-------------------------------------------------------------------------
5975  */
5976 typedef struct copy_dir_data_t {
5977     DBfile *dstFile;
5978 } copy_dir_data_t;
5979 
5980 static herr_t
copy_dir(hid_t grp,char const * name,void * op_data)5981 copy_dir(hid_t grp, char const *name, void *op_data)
5982 {
5983     static char         *me = "copy_dir";
5984 #if HDF5_VERSION_GE(1,8,0)
5985     H5G_stat_t          sb;
5986     hid_t               obj;
5987     int                 objtype = -1;
5988     copy_dir_data_t *cp_data = (copy_dir_data_t *)op_data;
5989     DBfile_hdf5 *dstfile = (DBfile_hdf5*)cp_data->dstFile;
5990 
5991     if (H5Gget_objinfo(grp, name, TRUE, &sb)<0) return -1;
5992     switch (sb.type) {
5993     case H5G_GROUP:
5994         /*
5995          * Any group which has a `..' entry is a silo directory. The `..'
5996          * names do not appear in the silo table of contents.
5997          */
5998         if (!strcmp(name, "..") || (obj=H5Gopen(grp, name))<0) break;
5999         H5E_BEGIN_TRY {
6000             if (H5Gget_objinfo(obj, "..", FALSE, NULL)>=0) objtype = DB_DIR;
6001         } H5E_END_TRY;
6002         H5Gclose(obj);
6003 
6004         if (objtype == DB_DIR)
6005         {
6006             db_hdf5_MkDir(cp_data->dstFile, (char*) name);
6007             db_hdf5_SetDir(cp_data->dstFile, (char*) name);
6008 
6009             /* recurse on the members of this group */
6010             H5Giterate(grp, name, 0, copy_dir, op_data);
6011 
6012             db_hdf5_SetDir(cp_data->dstFile, "..");
6013         }
6014 
6015         break;
6016 
6017     case H5G_TYPE:
6018     {
6019         hid_t       o=-1, attr=-1, atype=-1, s1024=-1;
6020         char        *file_value=NULL, *mem_value=NULL, *bkg=NULL;
6021         DBObjectType objtype;
6022         int         _objtype, nmembs, i;
6023         DBobject    *obj=NULL;
6024         size_t      asize, nelmts, msize;
6025 
6026         /* Open the object as a named data type */
6027         if ((o=H5Topen(grp, name))<0) {
6028             db_perror(name, E_NOTFOUND, me);
6029             UNWIND();
6030         }
6031 
6032         /* Open the `silo_type' attribute and read it */
6033         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
6034             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
6035             H5Aclose(attr)<0) {
6036             db_perror(name, E_CALLFAIL, me);
6037             UNWIND();
6038         }
6039         objtype = (DBObjectType)_objtype;
6040 
6041         /*
6042          * Open the `silo' attribute (all silo objects have one), retrieve
6043          * its data type (a single-level H5T_COMPOUND type), and read the
6044          * attribute.
6045          */
6046         if ((attr=H5Aopen_name(o, "silo"))<0 ||
6047             (atype=H5Aget_type(attr))<0) {
6048             db_perror(name, E_CALLFAIL, me);
6049             UNWIND();
6050         }
6051         asize = H5Tget_size(atype);
6052         msize = MAX(asize, 3*1024);
6053         if (NULL==(file_value=(char *)malloc(asize)) ||
6054             NULL==(mem_value=(char *)malloc(msize)) ||
6055             NULL==(bkg=(char *)malloc(msize))) {
6056             db_perror(name, E_NOMEM, me);
6057             UNWIND();
6058         }
6059         if (H5Aread(attr, atype, file_value)<0) {
6060             db_perror(name, E_CALLFAIL, me);
6061             UNWIND();
6062         }
6063         nmembs = H5Tget_nmembers(atype);
6064 
6065         s1024 = H5Tcopy(H5T_C_S1);
6066         H5Tset_size(s1024, 1024);
6067         for (i=0; i<nmembs; i++) {
6068             int ndims, j, memb_size[4];
6069             hid_t member_type = db_hdf5_get_cmemb(atype, i, &ndims, memb_size);
6070 
6071             if (H5Tget_class(member_type) == H5T_STRING)
6072             {
6073                 /* build up an in-memory rep that is akin to a struct
6074                  * with just this one member */
6075                 char *memname = H5Tget_member_name(atype, i);
6076                 size_t offset = H5Tget_member_offset(atype, i);
6077                 hid_t mtype = H5Tcreate(H5T_COMPOUND, msize);
6078                 for (nelmts=1, j=0; j<ndims; j++) nelmts *= memb_size[j];
6079                 db_hdf5_put_cmemb(mtype, memname, 0, ndims, memb_size, s1024);
6080 
6081                 /* use hdf5's type conversion func to extract this one member's
6082                    data into 'mem_value' */
6083                 memcpy(mem_value, file_value, H5Tget_size(atype));
6084                 H5Tconvert(atype, mtype, 1, mem_value, bkg, H5P_DEFAULT);
6085 
6086                 /* if its one of the special datasets, copy it and update
6087                    the attribute to refer to the copy in the new file */
6088                 if (strncmp(mem_value, "/.silo/#", 8) == 0)
6089                 {
6090                     /* get unique name for this dataset in dst file */
6091                     char cname[8];
6092                     db_hdf5_compname(dstfile, cname);
6093 
6094                     /* copy this dataset to /.silo dir in dst file */
6095                     H5Ocopy(grp, mem_value, dstfile->link, cname, H5P_DEFAULT, H5P_DEFAULT);
6096 
6097                     /* update this attribute's entry with name for this dataset */
6098                     sprintf(file_value+offset, "%s%s", LINKGRP, cname);
6099                 }
6100 
6101                 free(memname);
6102                 H5Tclose(mtype);
6103             }
6104 
6105             /* Release member resources */
6106             H5Tclose(member_type);
6107         }
6108 
6109         /* write the header for this silo object */
6110         db_hdf5_hdrwr(dstfile, (char *)name, atype, atype, file_value, objtype);
6111 
6112         /* Cleanup */
6113         H5Tclose(atype);
6114         H5Tclose(s1024);
6115         H5Aclose(attr);
6116         H5Tclose(o);
6117         free(file_value);
6118         free(mem_value);
6119         free(bkg);
6120 
6121         break;
6122     }
6123 
6124     case H5G_DATASET:
6125         H5Ocopy(grp, name, dstfile->cwg, name, H5P_DEFAULT, H5P_DEFAULT);
6126         break;
6127 
6128     default:
6129         /*ignore*/
6130         break;
6131     }
6132     return 0;
6133 #else
6134     return db_perror("H5O API for copy", E_NOTENABLEDINBUILD, me);
6135 #endif
6136 }
6137 
6138 /*-------------------------------------------------------------------------
6139  * Function:    db_hdf5_CpDir
6140  *
6141  * Purpose:     Copy a directory hierarchy from one file to another.
6142  *
6143  * Return:      Success:        0
6144  *
6145  *              Failure:        -1
6146  *
6147  * Programmer:  Mark C. Miller, Wed Aug  6 18:29:53 PDT 2008
6148  *
6149  * Modifications:
6150  *   Mark C. Miller, Thu Feb  4 20:02:53 PST 2010
6151  *   Removed unused variable and function call referencing it.
6152  *-------------------------------------------------------------------------
6153  */
6154 SILO_CALLBACK int
db_hdf5_CpDir(DBfile * _dbfile,char const * srcDir,DBfile * dstFile,char const * dstDir)6155 db_hdf5_CpDir(DBfile *_dbfile, char const *srcDir,
6156     DBfile *dstFile, char const *dstDir)
6157 {
6158     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
6159     DBfile_hdf5 *dstfile = (DBfile_hdf5*)dstFile;
6160     static char *me = "db_hdf5_CpDir";
6161     copy_dir_data_t cp_data;
6162     char dstcwg[256], srccwg[256];
6163 
6164     srccwg[0] = '\0';
6165     dstcwg[0] = '\0';
6166 
6167 #if !HDF5_VERSION_GE(1,8,0)
6168     db_perror("Requires HDF5-1.8 or later", E_CALLFAIL, me);
6169     return -1;
6170 #endif
6171 
6172     PROTECT {
6173 
6174         /* Save current dirs for both src and dst files */
6175         db_hdf5_GetDir(_dbfile, srccwg);
6176         db_hdf5_GetDir(dstFile, dstcwg);
6177 
6178         /* Next, make destination directory and cd into it */
6179         db_hdf5_MkDir(dstFile, (char*)dstDir);
6180         db_hdf5_SetDir(dstFile, (char*)dstDir);
6181 
6182         /* Enter the recursion to make copy the directory */
6183         cp_data.dstFile = dstFile;
6184         H5Giterate(dbfile->cwg, srcDir, 0, copy_dir, &cp_data);
6185 
6186         /* Restore current dirs for src and dst files */
6187         db_hdf5_SetDir(_dbfile, srccwg);
6188         db_hdf5_SetDir(dstFile, dstcwg);
6189 
6190     } CLEANUP {
6191         H5E_BEGIN_TRY {
6192             if (srccwg[0] != '\0')
6193                 db_hdf5_SetDir(_dbfile, srccwg);
6194             if (dstcwg[0] != '\0')
6195                 db_hdf5_SetDir(dstFile, dstcwg);
6196         } H5E_END_TRY;
6197     } END_PROTECT;
6198 
6199     return 0;
6200 }
6201 
6202 /*-------------------------------------------------------------------------
6203  * Function:    db_hdf5_NewToc
6204  *
6205  * Purpose:     Destroy the previous table of contents and replace it with a
6206  *              new table of contents for the current working directory.
6207  *
6208  * Return:      Success:        0
6209  *
6210  *              Failure:        -1
6211  *
6212  * Programmer:  Robb Matzke
6213  *              Thursday, February 11, 1999
6214  *
6215  * Modifications:
6216  *
6217  *-------------------------------------------------------------------------
6218  */
6219 SILO_CALLBACK int
db_hdf5_NewToc(DBfile * _dbfile)6220 db_hdf5_NewToc(DBfile *_dbfile)
6221 {
6222     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
6223     DBtoc       *toc=NULL;
6224 
6225     db_FreeToc(_dbfile);
6226     dbfile->pub.toc = toc = db_AllocToc();
6227 
6228     if (H5Giterate(dbfile->cwg, ".", NULL, load_toc, toc)<0) return -1;
6229     return 0;
6230 }
6231 
6232 /*-------------------------------------------------------------------------
6233  * Function:    db_hdf5_GetComponentType
6234  *
6235  * Purpose:     Return the data type of the component
6236  *
6237  * Programmer:  Mark C. Miller
6238  *              Wednesday, April 20, 2005
6239  *-------------------------------------------------------------------------
6240  */
6241 SILO_CALLBACK int
db_hdf5_GetComponentType(DBfile * _dbfile,char const * objname,char const * compname)6242 db_hdf5_GetComponentType(DBfile *_dbfile, char const *objname, char const *compname)
6243 {
6244     int datatype = DB_NOTYPE;
6245     db_hdf5_GetComponentStuff(_dbfile, objname, compname, &datatype);
6246     return datatype;
6247 }
6248 
6249 /*-------------------------------------------------------------------------
6250  * Function:    db_hdf5_GetComponent
6251  *
6252  * Purpose:     Reads the component COMPNAME of object OBJNAME, allocates
6253  *              memory and copies the value into it to return.
6254  *
6255  * Warning:     The names of components in an object in an HDF5 file may not
6256  *              be the same as the names of components in a PDB file.
6257  *
6258  * Programmer:  Mark C. Miller
6259  *              Wednesday, April 20, 2005
6260  *-------------------------------------------------------------------------
6261  */
6262 SILO_CALLBACK void *
db_hdf5_GetComponent(DBfile * _dbfile,char const * objname,char const * compname)6263 db_hdf5_GetComponent(DBfile *_dbfile, char const *objname, char const *compname)
6264 {
6265     return db_hdf5_GetComponentStuff(_dbfile, objname, compname, 0);
6266 }
6267 
6268 /*-------------------------------------------------------------------------
6269  * Function:    db_hdf5_GetComponentStuff
6270  *
6271  * Purpose:     Reads the component COMPNAME of object OBJNAME, allocates
6272  *              memory and copies the value into it to return.
6273  *
6274  * Warning:     The names of components in an object in an HDF5 file may not
6275  *              be the same as the names of components in a PDB file.
6276  *
6277  * Return:      Success:        Pointer to allocated memory which contains
6278  *                              the component value. Floating-point
6279  *                              components are returned in either single or
6280  *                              double precision according to the
6281  *                              DBForceSingle() setting.
6282  *
6283  *              Failure:        NULL
6284  *
6285  * Programmer:  Robb Matzke
6286  *              Tuesday, August 17, 1999
6287  *
6288  * Modifications:
6289  *
6290  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
6291  *   This routine had assumed that any string-valued data member was
6292  *   specifying the name of a dataset to read. That is not always true.
6293  *   I modified it to attempt to read a dataset of the given name or
6294  *   just return the string.
6295  *
6296  *   Mark C. Miller, Wed Apr 20 15:09:41 PDT 2005
6297  *   Renamed from db_hdf5_GetComponent. Added just_get_dataype argument
6298  *   and logic to just return data type when requested and avoid
6299  *   actual read of data
6300  *
6301  *   Mark C. Miller, Wed Jan 21 16:03:02 PST 2009
6302  *   Added logic to deal with components that are vectors of tuples
6303  *   but where DBGetObject flattens these tuples into groups of related
6304  *   scalars with digits appended to their names. This fixes a problem
6305  *   in silex displaying these vector-based components.
6306  *
6307  *   Mark C. Miller, Tue Apr 28 15:57:43 PDT 2009
6308  *   Added missing statement to set mnofname = 0 after free'ing it.
6309  *
6310  *   Mark C. Miller, Tue Oct  6 10:24:01 PDT 2009
6311  *   Removed call to free(mnofname) and set it to zero. Added logic
6312  *   to free it just prior to STRDUP'ing it.
6313  *-------------------------------------------------------------------------
6314  */
6315 SILO_CALLBACK void *
db_hdf5_GetComponentStuff(DBfile * _dbfile,char const * objname,char const * compname,int * just_get_datatype)6316 db_hdf5_GetComponentStuff(DBfile *_dbfile, char const *objname, char const *compname,
6317     int *just_get_datatype)
6318 {
6319     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
6320     static char *me = "db_hdf5_GetComponent";
6321     hid_t       o=-1, attr=-1, atype=-1, ftype=-1, mtype=-1, dset=-1;
6322     int         datatype, mno, n, ndims, i, dim[3], mult, complen, mnof=-1, mnofidx=-1;
6323     char        *mnofname=0;
6324     void        *retval=NULL;
6325 
6326     PROTECT {
6327         /* Open the object as a named data type */
6328         if ((o=H5Topen(dbfile->cwg, objname))<0) {
6329             db_perror(objname, E_NOTFOUND, me);
6330             UNWIND();
6331         }
6332 
6333         /*
6334          * Open the `silo' attribute (all silo objects have one), and
6335          * retrieve its data type (a single-level H5T_COMPOUND type).
6336          */
6337         if ((attr=H5Aopen_name(o, "silo"))<0 ||
6338             (atype=H5Aget_type(attr))<0) {
6339             db_perror(objname, E_CALLFAIL, me);
6340             UNWIND();
6341         }
6342 
6343         /* Scan through the compound type to find the requested component. */
6344         n = H5Tget_nmembers(atype);
6345         for (mno=0; mno<n; mno++) {
6346             char *memb_name = H5Tget_member_name(atype, mno);
6347             if (memb_name && !strcmp(memb_name, compname)) {
6348                 free(memb_name);
6349                 break;
6350             }
6351 
6352             /* If we didn't get a match but the last char is a digit, then
6353                it might be a funky component named by adding a digit to an
6354                existing component name by a preceding DBGetObject() call */
6355             complen = strlen(compname);
6356             while (57 >= compname[complen-1] && compname[complen-1] >= 48)
6357                 complen--;
6358             if (57 >= compname[complen] && compname[complen] >= 48)
6359             {
6360                 if (memb_name && !strncmp(memb_name, compname, complen))
6361                 {
6362                     mnof = mno;
6363                     errno = 0;
6364                     mnofidx = strtol(&compname[complen], 0, 0) - 1;
6365                     if (errno != 0) mnofidx = -1;
6366                     if (mnofname) free(mnofname);
6367                     mnofname = STRDUP(memb_name);
6368                 }
6369             }
6370             if (memb_name) free(memb_name);
6371         }
6372         if (mno>=n) {
6373             if (mnof == -1)
6374             {
6375                 db_perror(compname, E_NOTFOUND, me);
6376                 UNWIND();
6377             }
6378             mno = mnof;
6379         }
6380 
6381         /* Get the datatype and multiplicity for the component */
6382         if ((ftype=db_hdf5_get_cmemb(atype, mno, &ndims, dim))<0) {
6383             db_perror(compname, E_CALLFAIL, me);
6384             UNWIND();
6385         }
6386 
6387         if (H5T_STRING==H5Tget_class(ftype)) {
6388 
6389             if (just_get_datatype == 0)
6390             {
6391                 /*
6392                  * A string is usually a pointer to some other dataset. So, try
6393                  * read that dataset instead.
6394                  */
6395                 char dataset_name[] =
6396                     {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6397                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6398                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6399                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6400                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6401                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6402                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6403                      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
6404 
6405                 /* Read the dataset name from the attribute */
6406                 if ((H5Tget_size(ftype)+1<sizeof dataset_name) &&
6407                     (mtype=H5Tcreate(H5T_COMPOUND, H5Tget_size(ftype)))>=0 &&
6408                     db_hdf5_put_cmemb(mtype, compname, 0, 0, NULL, ftype)>=0 &&
6409                     H5Aread(attr, mtype, dataset_name)>=0) {
6410                     if ((dset=H5Dopen(dbfile->cwg, dataset_name))>=0) {
6411                         retval = db_hdf5_comprd(dbfile, dataset_name, 1);
6412                         H5Dclose(dset);
6413                     }
6414                     else {
6415                         retval = STRDUP(dataset_name);
6416                     }
6417                 }
6418             }
6419             else
6420             {
6421                 *just_get_datatype = DB_VARIABLE;
6422             }
6423         }
6424         else
6425         {
6426             /* Read a single component of the compound attribute */
6427             if ((datatype=hdf2silo_type(ftype))<0) {
6428                 db_perror(compname, E_CALLFAIL, me);
6429                 UNWIND();
6430             }
6431 
6432             if (just_get_datatype == 0)
6433             {
6434                 for (i=0, mult=1; i<ndims; i++) mult *= dim[i];
6435 
6436                 /* Allocate the return value */
6437                 if (NULL==(retval=calloc(mult, db_GetMachDataSize(datatype)))) {
6438                     db_perror(compname, E_CALLFAIL, me);
6439                     UNWIND();
6440                 }
6441 
6442                 /* Build the hdf5 data type to read */
6443                 mtype = H5Tcreate(H5T_COMPOUND, mult * db_GetMachDataSize(datatype));
6444                 if (mnof != -1 && mnofidx != -1 && mnofname != 0)
6445                     db_hdf5_put_cmemb(mtype, mnofname, 0, ndims, dim, hdf2hdf_type(ftype));
6446                 else
6447                     db_hdf5_put_cmemb(mtype, compname, 0, ndims, dim, hdf2hdf_type(ftype));
6448 
6449                 /* Read the data into the output buffer */
6450                 if (H5Aread(attr, mtype, retval)<0) {
6451                     db_perror(compname, E_CALLFAIL, me);
6452                     UNWIND();
6453                 }
6454 
6455                 /* Handle the case where we got a match on member name modulo trailing
6456                    digits (which really represent an index into the member) */
6457                 if (mnof != -1 && mnofidx != -1 && mnofname != 0)
6458                 {
6459                     void *newretval;
6460                     char *pretval = (char *) retval + mnofidx * db_GetMachDataSize(datatype);
6461                     if (NULL==(newretval=calloc(1, db_GetMachDataSize(datatype)))) {
6462                         db_perror(mnofname, E_CALLFAIL, me);
6463                         UNWIND();
6464                     }
6465                     memcpy(newretval, pretval, db_GetMachDataSize(datatype));
6466                     free(retval);
6467                     retval = newretval;
6468                 }
6469             }
6470             else
6471             {
6472                 *just_get_datatype = datatype;
6473             }
6474         }
6475 
6476         /* Release objects */
6477         if (mnofname) free(mnofname);
6478         H5Tclose(o);
6479         H5Aclose(attr);
6480         H5Tclose(atype);
6481         H5Tclose(ftype);
6482         if (mtype != -1) H5Tclose(mtype);
6483     } CLEANUP {
6484         /* Release objects */
6485         if (retval) {
6486             free(retval);
6487             retval = NULL;
6488         }
6489         if (mnofname) free(mnofname);
6490         H5E_BEGIN_TRY {
6491             H5Tclose(o);
6492             H5Aclose(attr);
6493             H5Tclose(atype);
6494             H5Tclose(ftype);
6495             H5Tclose(mtype);
6496         } H5E_END_TRY;
6497     } END_PROTECT;
6498 
6499     return retval;
6500 }
6501 
6502 /*-------------------------------------------------------------------------
6503  * Function:    db_hdf5_GetComponentNames
6504  *
6505  * Purpose:     Returns the component names for the specified object. The
6506  *              COMP_NAMES and FILE_NAMES output arguments will point to
6507  *              an array of pointers to names. Each name as well as the
6508  *              two arrays will be allocated with `malloc'.  This is
6509  *              essentially the same as DBGetObject().
6510  *
6511  * Return:      Success:        Number of components found for the
6512  *                              specified object.
6513  *
6514  *              Failure:        zero
6515  *
6516  * Programmer:  Robb Matzke, 2001-02-06
6517  *
6518  * Modifications:
6519  *-------------------------------------------------------------------------
6520  */
6521 SILO_CALLBACK int
db_hdf5_GetComponentNames(DBfile * _dbfile,char const * objname,char *** comp_names,char *** file_names)6522 db_hdf5_GetComponentNames(DBfile *_dbfile, char const *objname, char ***comp_names,
6523                           char ***file_names)
6524 {
6525     DBobject    *obj;
6526     int         n;
6527 
6528     if (NULL==(obj=db_hdf5_GetObject(_dbfile, objname))) return 0;
6529     if (comp_names) {
6530         *comp_names = obj->comp_names;
6531     } else {
6532         free(obj->comp_names);
6533         obj->comp_names = 0;
6534     }
6535     if (file_names) {
6536         *file_names = obj->pdb_names;
6537     } else {
6538         free(obj->pdb_names);
6539         obj->pdb_names = 0;
6540     }
6541     n = obj->ncomponents;
6542     obj->ncomponents = 0;
6543     DBFreeObject(obj);
6544     return n;
6545 }
6546 
6547 /*-------------------------------------------------------------------------
6548  * Function:    db_hdf5_WriteObject
6549  *
6550  * Purpose:     Write/overwrite a DBobject into the given file.
6551 
6552  *
6553  * Return:      Success:        Non-negative
6554  *
6555  *              Failure:        -1
6556  *
6557  * Programmer:  Robb Matzke, 2001-02-05
6558  *
6559  * Modifications:
6560  *
6561  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
6562  *   I made it support writing a DBZonelist object. I also fixed an
6563  *   off-by-one error in indexing of string valued component names
6564  *
6565  *   Mark C. Miller, Wed Jan 13 14:21:50 PST 2010
6566  *   Added condition of flags!=OVERWRITE before erroring on non-user
6567  *   defined objects. A user could be using browser to OVERWRITE a
6568  *   standard Silo object.
6569  *-------------------------------------------------------------------------
6570  */
6571 SILO_CALLBACK int
db_hdf5_WriteObject(DBfile * _dbfile,DBobject const * obj,int flags)6572 db_hdf5_WriteObject(DBfile *_dbfile,    /*File to write into */
6573                     DBobject const *obj,/*Object description to write out */
6574                     int flags)          /*1=>free associated memory */
6575 {
6576     DBfile_hdf5         *dbfile=(DBfile_hdf5*)_dbfile;
6577     static char         *me="db_hdf5_WriteObject";
6578     size_t              msize=0, fsize=0, moffset=0, foffset=0;
6579     unsigned char       *object=NULL;
6580     hid_t               mtype=-1, ftype=-1;
6581     int                 i;
6582 
6583     PROTECT {
6584         /* If flags is set then delete any existing object by the same
6585          * name, ignoring failures. */
6586         if (flags) {
6587             H5E_BEGIN_TRY {
6588                 H5Gunlink(dbfile->cwg, obj->name);
6589             } H5E_END_TRY;
6590         }
6591 
6592         /* How much memory do we need? Align all components */
6593         for (i=0, msize=fsize=0; i<obj->ncomponents; i++) {
6594             if (!strncmp(obj->pdb_names[i], "'<i>", 4)) {
6595                 msize = ALIGN(msize, sizeof(int)) + sizeof(int);
6596                 fsize += H5Tget_size(dbfile->T_int);
6597             } else if (!strncmp(obj->pdb_names[i], "'<f>", 4)) {
6598                 msize = ALIGN(msize, sizeof(float)) + sizeof(float);
6599                 fsize += H5Tget_size(dbfile->T_float);
6600             } else if (!strncmp(obj->pdb_names[i], "'<d>", 4)) {
6601                 msize = ALIGN(msize, sizeof(double)) + sizeof(double);
6602                 fsize += H5Tget_size(dbfile->T_double);
6603             } else if (!strncmp(obj->pdb_names[i], "'<s>", 4)) {
6604                 msize += strlen(obj->pdb_names[i]+4);
6605                 fsize += strlen(obj->pdb_names[i]+4);
6606             } else if (obj->pdb_names[i][0]=='\'') {
6607                 /* variable has invalid name or we don't handle type */
6608                 db_perror(obj->pdb_names[i], E_INVALIDNAME, me);
6609                 UNWIND();
6610             } else {
6611                 /* Its possible this is a 'special' tiny array 'var' component.
6612                  * So, first, search for it in obj->h5_names and if found, handle
6613                  * it as such */
6614                 int j, off=0, found=0;
6615                 for (j = 0; obj->h5_names[j]; j++)
6616                 {
6617                     off += obj->h5_sizes[j] * db_GetMachDataSize(obj->h5_types[j]);
6618                     if (!strcmp(obj->comp_names[i], obj->h5_names[j]))
6619                     {
6620                         found = 1;
6621                         break;
6622                     }
6623                 }
6624                 if (found)
6625                 {
6626                     switch (obj->h5_types[j])
6627                     {
6628                         case DB_INT:
6629                         {
6630                             int dummy[3];
6631                             hsize_t _size = 3;
6632                             hid_t _f_ary;
6633                             msize = ALIGN(msize, sizeof(dummy)) + sizeof(dummy);
6634 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6635                             _f_ary = H5Tarray_create(dbfile->T_int, 1, &_size, NULL);
6636                             fsize += H5Tget_size(_f_ary);
6637                             H5Tclose(_f_ary);
6638 #else
6639                             fsize += 3*H5Tget_size(dbfile->T_int);
6640 #endif
6641                             break;
6642                         }
6643                         case DB_FLOAT:
6644                         {
6645                             float dummy[3];
6646                             hsize_t _size = 3;
6647                             hid_t _f_ary;
6648                             msize = ALIGN(msize, sizeof(dummy)) + sizeof(dummy);
6649 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6650                             _f_ary = H5Tarray_create(dbfile->T_float, 1, &_size, NULL);
6651                             fsize += H5Tget_size(_f_ary);
6652                             H5Tclose(_f_ary);
6653 #else
6654                             fsize += 3*H5Tget_size(dbfile->T_float);
6655 #endif
6656                             break;
6657                         }
6658                         case DB_DOUBLE:
6659                         {
6660                             double dummy[3];
6661                             hsize_t _size = 3;
6662                             hid_t _f_ary;
6663                             msize = ALIGN(msize, sizeof(dummy)) + sizeof(dummy);
6664 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6665                             _f_ary = H5Tarray_create(dbfile->T_double, 1, &_size, NULL);
6666                             fsize += H5Tget_size(_f_ary);
6667                             H5Tclose(_f_ary);
6668 #else
6669                             fsize += 3*H5Tget_size(dbfile->T_double);
6670 #endif
6671                             break;
6672                         }
6673                         default:
6674                             break;
6675                     }
6676                 }
6677                 else
6678                 {
6679                     /* variable added by DBAddVarComponent() */
6680                     msize += strlen(obj->pdb_names[i]) + 1;
6681                     fsize += strlen(obj->pdb_names[i]) + 1;
6682                 }
6683             }
6684         }
6685 
6686         if (!msize) {
6687             db_perror("Object has zero size", E_BADARGS, me);
6688             UNWIND();
6689         }
6690 
6691         /* Create the object and initialize it */
6692         if (NULL==(object=(unsigned char *)calloc(1, msize))) {
6693             db_perror(NULL, E_NOMEM, me);
6694             UNWIND();
6695         }
6696         if ((mtype=H5Tcreate(H5T_COMPOUND, msize))<0 ||
6697             (ftype=H5Tcreate(H5T_COMPOUND, fsize))<0) {
6698             db_perror("H5Tcreate", E_CALLFAIL, me);
6699             UNWIND();
6700         }
6701         for (i=0, moffset=foffset=0; i<obj->ncomponents; i++) {
6702             if (!strncmp(obj->pdb_names[i], "'<i>", 4)) {
6703                 moffset = ALIGN(moffset, sizeof(int));
6704                 if (H5Tinsert(mtype, obj->comp_names[i], moffset,
6705                               H5T_NATIVE_INT)<0 ||
6706                     H5Tinsert(ftype, obj->comp_names[i], foffset,
6707                               dbfile->T_int)<0) {
6708                     db_perror("H5Tinsert", E_CALLFAIL, me);
6709                     UNWIND();
6710                 }
6711                 *(int*)(object+moffset) = strtol(obj->pdb_names[i]+4, NULL, 0);
6712                 moffset += sizeof(int);
6713                 foffset += H5Tget_size(dbfile->T_int);
6714             } else if (!strncmp(obj->pdb_names[i], "'<f>", 4)) {
6715                 moffset = ALIGN(moffset, sizeof(float));
6716                 if (H5Tinsert(mtype, obj->comp_names[i], moffset,
6717                               H5T_NATIVE_FLOAT)<0 ||
6718                     H5Tinsert(ftype, obj->comp_names[i], foffset,
6719                               dbfile->T_float)<0) {
6720                     db_perror("H5Tinsert", E_CALLFAIL, me);
6721                     UNWIND();
6722                 }
6723                 *(float*)(object+moffset) = strtod(obj->pdb_names[i]+4, NULL);
6724                 moffset += sizeof(float);
6725                 foffset += H5Tget_size(dbfile->T_float);
6726             } else if (!strncmp(obj->pdb_names[i], "'<d>", 4)) {
6727                 moffset = ALIGN(moffset, sizeof(double));
6728                 if (H5Tinsert(mtype, obj->comp_names[i], moffset,
6729                               H5T_NATIVE_DOUBLE)<0 ||
6730                     H5Tinsert(ftype, obj->comp_names[i], foffset,
6731                               dbfile->T_double)<0) {
6732                     db_perror("H5Tinsert", E_CALLFAIL, me);
6733                     UNWIND();
6734                 }
6735                 *(double*)(object+moffset) = strtod(obj->pdb_names[i]+4, NULL);
6736                 moffset += sizeof(double);
6737                 foffset += H5Tget_size(dbfile->T_double);
6738             } else if (!strncmp(obj->pdb_names[i], "'<s>", 4)) {
6739                 size_t len = strlen(obj->pdb_names[i]+4)-1;
6740                 hid_t str_type = H5Tcopy(H5T_C_S1);
6741                 H5Tset_size(str_type, len);
6742                 if (H5Tinsert(mtype, obj->comp_names[i], moffset,
6743                               str_type)<0 ||
6744                     H5Tinsert(ftype, obj->comp_names[i], foffset,
6745                               str_type)<0) {
6746                     db_perror("H5Tinsert", E_CALLFAIL, me);
6747                     UNWIND();
6748                 }
6749                 H5Tclose(str_type);
6750                 strncpy((char*)(object+moffset), obj->pdb_names[i]+4, len);
6751                 object[moffset+len] = '\0'; /*overwrite quote*/
6752                 moffset += len;
6753                 foffset += len;
6754             } else {
6755                 /* Its possible this is a 'special' tiny array 'var' component.
6756                  * So, first, search for it in obj->h5_names and if found, handle
6757                  * it as such */
6758                 int j, found=0;
6759                 for (j = 0; obj->h5_names[j]; j++)
6760                 {
6761                     if (!strcmp(obj->comp_names[i], obj->h5_names[j]))
6762                     {
6763                         found = 1;
6764                         break;
6765                     }
6766                 }
6767                 if (found)
6768                 {
6769                     switch (obj->h5_types[j])
6770                     {
6771                         case DB_INT:
6772                         {
6773                             int dummy[3];
6774                             hid_t _m_ary, _f_ary;
6775                             hsize_t _size = 3;
6776                             moffset = ALIGN(moffset, sizeof(dummy));
6777 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6778                             _m_ary = H5Tarray_create(H5T_NATIVE_INT, 1, &_size, NULL);
6779                             _f_ary = H5Tarray_create(dbfile->T_int, 1, &_size, NULL);
6780                             if (H5Tinsert(mtype, obj->comp_names[i], moffset, _m_ary)<0 ||
6781                                 H5Tinsert(ftype, obj->comp_names[i], foffset, _f_ary)<0) {
6782                                 db_perror("H5Tinsert", E_CALLFAIL, me);
6783                                 UNWIND();
6784                             }
6785                             foffset += H5Tget_size(_f_ary);
6786                             H5Tclose(_f_ary);
6787                             H5Tclose(_m_ary);
6788 #else
6789                             db_perror("Cannot customize standard object", E_CALLFAIL, me);
6790                             UNWIND();
6791 #endif
6792                             memcpy(object+moffset, &obj->h5_vals[obj->h5_offs[j]], sizeof(dummy));
6793                             moffset += sizeof(dummy);
6794                             break;
6795                         }
6796                         case DB_FLOAT:
6797                         {
6798                             float dummy[3];
6799                             hid_t _m_ary, _f_ary;
6800                             hsize_t _size = 3;
6801                             moffset = ALIGN(moffset, sizeof(dummy));
6802 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6803                             _m_ary = H5Tarray_create(H5T_NATIVE_FLOAT, 1, &_size, NULL);
6804                             _f_ary = H5Tarray_create(dbfile->T_float, 1, &_size, NULL);
6805                             if (H5Tinsert(mtype, obj->comp_names[i], moffset, _m_ary)<0 ||
6806                                 H5Tinsert(ftype, obj->comp_names[i], foffset, _f_ary)<0) {
6807                                 db_perror("H5Tinsert", E_CALLFAIL, me);
6808                                 UNWIND();
6809                             }
6810                             foffset += H5Tget_size(_f_ary);
6811                             H5Tclose(_f_ary);
6812                             H5Tclose(_m_ary);
6813 #else
6814                             db_perror("Cannot customize standard object", E_CALLFAIL, me);
6815                             UNWIND();
6816 #endif
6817                             memcpy(object+moffset, &obj->h5_vals[obj->h5_offs[j]], sizeof(dummy));
6818                             moffset += sizeof(dummy);
6819                             break;
6820                         }
6821                         case DB_DOUBLE:
6822                         {
6823                             double dummy[3];
6824                             hid_t _m_ary, _f_ary;
6825                             hsize_t _size = 3;
6826                             moffset = ALIGN(moffset, sizeof(dummy));
6827 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=4
6828                             _m_ary = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, &_size, NULL);
6829                             _f_ary = H5Tarray_create(dbfile->T_double, 1, &_size, NULL);
6830                             if (H5Tinsert(mtype, obj->comp_names[i], moffset, _m_ary)<0 ||
6831                                 H5Tinsert(ftype, obj->comp_names[i], foffset, _f_ary)<0) {
6832                                 db_perror("H5Tinsert", E_CALLFAIL, me);
6833                                 UNWIND();
6834                             }
6835                             foffset += H5Tget_size(_f_ary);
6836                             H5Tclose(_f_ary);
6837                             H5Tclose(_m_ary);
6838 #else
6839                             db_perror("Cannot customize standard object", E_CALLFAIL, me);
6840                             UNWIND();
6841 #endif
6842                             memcpy(object+moffset, &obj->h5_vals[obj->h5_offs[j]], sizeof(dummy));
6843                             moffset += sizeof(dummy);
6844                             break;
6845                         }
6846                     }
6847                 }
6848                 else
6849                 {
6850                     size_t len = strlen(obj->pdb_names[i])+1;
6851                     hid_t str_type = H5Tcopy(H5T_C_S1);
6852                     H5Tset_size(str_type, len);
6853                     if (H5Tinsert(mtype, obj->comp_names[i], moffset,
6854                                   str_type)<0 ||
6855                         H5Tinsert(ftype, obj->comp_names[i], foffset,
6856                               str_type)<0) {
6857                         db_perror("H5Tinsert", E_CALLFAIL, me);
6858                         UNWIND();
6859                     }
6860                     H5Tclose(str_type);
6861                     strcpy((char*)(object+moffset), obj->pdb_names[i]);
6862                     moffset += len;
6863                     foffset += len;
6864                 }
6865             }
6866         }
6867 
6868         if (db_hdf5_hdrwr(dbfile, obj->name, mtype, ftype, object,
6869                           (DBObjectType) DBGetObjtypeTag(obj->type))<0) {
6870             UNWIND();
6871         }
6872         H5Tclose(mtype);
6873         H5Tclose(ftype);
6874         if (object) free(object);
6875     } CLEANUP {
6876         H5E_BEGIN_TRY {
6877             H5Tclose(mtype);
6878             H5Tclose(ftype);
6879         } H5E_END_TRY;
6880         if (object) free(object);
6881     } END_PROTECT;
6882     return 0;
6883 }
6884 
6885 /*-------------------------------------------------------------------------
6886  * Function:    db_hdf5_WriteComponent
6887  *
6888  * Purpose:     Add a variable component to the given object structure and
6889  *              write out the associated data.
6890  *
6891  * Return:      Success:        non-negative
6892  *
6893  *              Failure:        -1
6894  *
6895  * Programmer:  Robb Matzke, 2001-02-06
6896  *
6897  * Modifications:
6898  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
6899  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
6900  *-------------------------------------------------------------------------
6901  */
6902 SILO_CALLBACK int
db_hdf5_WriteComponent(DBfile * _dbfile,DBobject * obj,char const * compname,char const * prefix,char const * dataname,void const * data,int rank,long const * _size)6903 db_hdf5_WriteComponent(DBfile *_dbfile, DBobject *obj, char const *compname,
6904                        char const *prefix, char const *dataname, void const *data,
6905                        int rank, long const *_size)
6906 {
6907     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
6908     int         size[32], i, totsize;
6909     char        varname[256];
6910     int         datatype = db_GetDatatypeID(dataname);
6911 
6912     /*
6913      * We have to be careful here to deal with possible customization of
6914      * 'standard' objects. The HDF5 driver handles small arrays of things
6915      * like dimensions, extents, alignment, etc. as 'array' members of
6916      * the attribute 'header' struct. So, we cannot arbitrarily decide to
6917      * write every component we see here to the file. Sometimes, we'll have
6918      * to avert that operation and instead store the data to the DBobject
6919      * struct, temporarily, for eventual write via DBWriteObject
6920      */
6921 
6922     totsize = 1;
6923     for (i=0; i<rank; i++) {
6924         size[i] = _size[i];
6925         totsize *= size[i];
6926     }
6927 
6928     if (totsize == 3)
6929     {
6930         int add_it = 0;
6931         DBObjectType objtype = (DBObjectType) DBGetObjtypeTag(obj->type);
6932 
6933         switch (objtype)
6934         {
6935             case DB_CSGMESH:
6936             {
6937                 add_it |= !strcmp(compname, "min_extents");
6938                 add_it |= !strcmp(compname, "max_extents");
6939                 break;
6940             }
6941             case DB_QUADMESH:
6942             case DB_QUADCURV:
6943             case DB_QUADRECT:
6944             {
6945                 add_it |= !strcmp(compname, "min_extents");
6946                 add_it |= !strcmp(compname, "max_extents");
6947                 add_it |= !strcmp(compname, "dims");
6948                 add_it |= !strcmp(compname, "min_index");
6949                 add_it |= !strcmp(compname, "max_index");
6950                 add_it |= !strcmp(compname, "base_index");
6951                 break;
6952             }
6953             case DB_QUADVAR:
6954             {
6955                 add_it |= !strcmp(compname, "zones");
6956                 add_it |= !strcmp(compname, "align");
6957                 add_it |= !strcmp(compname, "dims");
6958                 add_it |= !strcmp(compname, "min_index");
6959                 add_it |= !strcmp(compname, "max_index");
6960                 break;
6961             }
6962             case DB_UCDMESH:
6963             {
6964                 add_it |= !strcmp(compname, "min_extents");
6965                 add_it |= !strcmp(compname, "max_extents");
6966                 break;
6967             }
6968             case DB_MATERIAL:
6969             case DB_MATSPECIES:
6970             {
6971                 add_it |= !strcmp(compname, "dims");
6972                 break;
6973             }
6974             case DB_POINTMESH:
6975             {
6976                 add_it |= !strcmp(compname, "min_extents");
6977                 add_it |= !strcmp(compname, "max_extents");
6978                 break;
6979             }
6980             default: break;
6981         }
6982 
6983         if (add_it)
6984         {
6985             int i;
6986             for (i = 0; obj->h5_names[i] && i < DB_MAX_H5_OBJ_VALS; i++); /* find first open slot */
6987             if (i >= DB_MAX_H5_OBJ_VALS)
6988                 return db_perror(compname, E_OBJBUFFULL, "db_hdf5_WriteComponent");
6989             obj->h5_names[i] = strdup(compname);
6990             obj->h5_types[i] = datatype;
6991             obj->h5_sizes[i] = totsize;
6992             obj->h5_offs[i] = i==0?0:obj->h5_offs[i-1]+totsize*db_GetMachDataSize(datatype);
6993             if (obj->h5_offs[i] + totsize * db_GetMachDataSize(datatype) > sizeof(obj->h5_vals))
6994                 return db_perror(compname, E_OBJBUFFULL, "db_hdf5_WriteComponent");
6995             memcpy(&obj->h5_vals[obj->h5_offs[i]], data, totsize * db_GetMachDataSize(datatype));
6996             DBAddVarComponent(obj, compname, compname);
6997             return 0;
6998         }
6999     }
7000 
7001     varname[0] = '\0';
7002     db_hdf5_compwr(dbfile, datatype, rank, size, data, varname,
7003         friendly_name(obj->name, compname, 0));
7004     DBAddVarComponent(obj, compname, varname);
7005     return 0;
7006 }
7007 
7008 /*-------------------------------------------------------------------------
7009  * Function:    db_hdf5_InqVarExists
7010  *
7011  * Purpose:     Check whether the variable VARNAME exists.
7012  *
7013  * Return:      Success:        positive if exists, zero otherwise.
7014  *
7015  *              Failure:        -1
7016  *
7017  * Programmer:  Robb Matzke
7018  *              Tuesday, February  9, 1999
7019  *
7020  * Modifications:
7021  *
7022  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
7023  *   I made it return true or false based on existence of named entity
7024  *   only and not that the entity also be a dataset.
7025  *
7026  *-------------------------------------------------------------------------
7027  */
7028 SILO_CALLBACK int
db_hdf5_InqVarExists(DBfile * _dbfile,char const * varname)7029 db_hdf5_InqVarExists (DBfile *_dbfile, char const *varname)
7030 {
7031    DBfile_hdf5  *dbfile = (DBfile_hdf5*)_dbfile;
7032    herr_t       status;
7033    H5G_stat_t   sb;
7034 
7035    /* Check existence */
7036    H5E_BEGIN_TRY {
7037        status = H5Gget_objinfo(dbfile->cwg, varname, TRUE, &sb);
7038    } H5E_END_TRY;
7039    if (status<0)
7040        return FALSE;
7041    else
7042        return TRUE;
7043 }
7044 
7045 /*-------------------------------------------------------------------------
7046  * Function:    db_hdf5_GetVarLength
7047  *
7048  * Purpose:     Returns the number of elements in the specified variable.
7049  *
7050  * Return:      Success:        Number of elements
7051  *
7052  *              Failure:        -1
7053  *
7054  * Programmer:  Robb Matzke
7055  *              Thursday, February 11, 1999
7056  *
7057  * Modifications:
7058  *
7059  *-------------------------------------------------------------------------
7060  */
7061 SILO_CALLBACK int
db_hdf5_GetVarLength(DBfile * _dbfile,char const * name)7062 db_hdf5_GetVarLength(DBfile *_dbfile, char const *name)
7063 {
7064     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7065     static char *me = "db_hdf5_GetVarLength";
7066     hid_t       dset=-1, space=-1;
7067     hsize_t     nelmts=-1;
7068 
7069     PROTECT {
7070         if ((dset=H5Dopen(dbfile->cwg, name))>=0) {
7071             if ((space=H5Dget_space(dset))<0) {
7072                 db_perror(name, E_CALLFAIL, me);
7073                 UNWIND();
7074             }
7075             nelmts = H5Sget_simple_extent_npoints(space);
7076             H5Dclose(dset);
7077             H5Sclose(space);
7078         }
7079         else
7080         {
7081             if (!db_hdf5_get_comp_var(dbfile->cwg, name, &nelmts,
7082                  NULL, NULL, NULL)) {
7083                 db_perror(name, E_CALLFAIL, me);
7084                 UNWIND();
7085             }
7086         }
7087     } CLEANUP {
7088         H5E_BEGIN_TRY {
7089             H5Dclose(dset);
7090             H5Sclose(space);
7091         } H5E_END_TRY;
7092     } END_PROTECT;
7093 
7094     return nelmts;
7095 }
7096 
7097 /*-------------------------------------------------------------------------
7098  * Function:    db_hdf5_GetVarByteLength
7099  *
7100  * Purpose:     Returns the number of bytes needed to store the entire
7101  *              variable in memory.
7102  *
7103  * Return:      Success:        Number of bytes
7104  *
7105  *              Failure:        -1
7106  *
7107  * Programmer:  Robb Matzke
7108  *              Wednesday, March 17, 1999
7109  *
7110  * Modifications:
7111  *
7112  *-------------------------------------------------------------------------
7113  */
7114 SILO_CALLBACK int
db_hdf5_GetVarByteLength(DBfile * _dbfile,char const * name)7115 db_hdf5_GetVarByteLength(DBfile *_dbfile, char const *name)
7116 {
7117     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7118     static char *me = "db_hdf5_GetVarByteLength";
7119     hid_t       dset=-1, ftype=-1, mtype=-1, space=-1;
7120     hsize_t     nbytes_big;
7121     int         nbytes_small=-1;
7122 
7123     PROTECT {
7124         /* Open the dataset */
7125         if ((dset=H5Dopen(dbfile->cwg, name))>=0) {
7126 
7127             /* Get data type and space */
7128             if ((ftype=H5Dget_type(dset))<0 ||
7129                 (mtype=hdf2hdf_type(ftype))<0 ||
7130                 (space=H5Dget_space(dset))<0) {
7131                 db_perror(name, E_CALLFAIL, me);
7132                 UNWIND();
7133             }
7134 
7135             /* Get total size in bytes and check for overflow */
7136             nbytes_big = H5Sget_simple_extent_npoints(space) * H5Tget_size(mtype);
7137             nbytes_small = (int)nbytes_big;
7138             if (nbytes_big!=(hsize_t)nbytes_small) {
7139                 db_perror("overflow", E_INTERNAL, me);
7140                 UNWIND();
7141             }
7142 
7143             /* Release resources */
7144             H5Tclose(ftype);
7145             H5Sclose(space);
7146             H5Dclose(dset);
7147         }
7148         else
7149         {
7150             hsize_t nelmts;
7151             size_t elsize;
7152             if (!db_hdf5_get_comp_var(dbfile->cwg, name, &nelmts,
7153                  &elsize, NULL, NULL)) {
7154                 db_perror(name, E_CALLFAIL, me);
7155                 UNWIND();
7156             }
7157             nbytes_small = (int)(nelmts * elsize);
7158         }
7159     } CLEANUP {
7160         H5E_BEGIN_TRY {
7161             H5Tclose(ftype);
7162             H5Sclose(space);
7163             H5Dclose(dset);
7164         } H5E_END_TRY;
7165     } END_PROTECT;
7166 
7167     return nbytes_small;
7168 }
7169 
7170 /*-------------------------------------------------------------------------
7171  * Function:    db_hdf5_GetVarType
7172  *
7173  * Purpose:     Query the data type of the variable.
7174  *
7175  * Return:      Success:        One of the DB_* constants that describes data
7176  *                              type. The type is chosen to be at least as
7177  *                              large as the type in the file, but using
7178  *                              DB_LONG in cases where there is no native
7179  *                              type which is large enough.
7180  *
7181  *              Failure:        -1
7182  *
7183  * Programmer:  Robb Matzke
7184  *              Sunday, February 14, 1999
7185  *
7186  * Modifications:
7187  *
7188  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
7189  *   I made it return -1 if name or *name is null.
7190  *
7191  *-------------------------------------------------------------------------
7192  */
7193 SILO_CALLBACK int
db_hdf5_GetVarType(DBfile * _dbfile,char const * name)7194 db_hdf5_GetVarType(DBfile *_dbfile, char const *name)
7195 {
7196     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7197     static char *me = "db_hdf5_GetVarType";
7198     hid_t       dset=-1, ftype=-1;
7199     int         silo_type=-1;
7200 
7201     if ((name == 0) || (*name == 0))
7202         return -1;
7203 
7204     PROTECT {
7205         if ((dset=H5Dopen(dbfile->cwg, name))>=0) {
7206             if ((ftype=H5Dget_type(dset))<0) {
7207                 db_perror(name, E_CALLFAIL, me);
7208                 UNWIND();
7209             }
7210             silo_type = hdf2silo_type(ftype);
7211             H5Dclose(dset);
7212             H5Tclose(ftype);
7213         }
7214         else
7215         {
7216             if (!db_hdf5_get_comp_var(dbfile->cwg, name, NULL,
7217                  NULL, &ftype, NULL)) {
7218                 db_perror(name, E_CALLFAIL, me);
7219                 UNWIND();
7220             }
7221             silo_type = hdf2silo_type(ftype);
7222         }
7223     } CLEANUP {
7224         H5E_BEGIN_TRY {
7225             H5Dclose(dset);
7226             H5Tclose(ftype);
7227         } H5E_END_TRY;
7228     } END_PROTECT;
7229 
7230     return silo_type;
7231 }
7232 
7233 /*-------------------------------------------------------------------------
7234  * Function:    db_hdf5_GetVarDims
7235  *
7236  * Purpose:     Obtains the size of the dimensions of some variable.
7237  *
7238  * Return:      Success:        Number of dimensions. At most MAXDIMS values
7239  *                              are copied into the DIMS argument.
7240  *
7241  *              Failure:        -1
7242  *
7243  * Programmer:  Robb Matzke
7244  *              Monday, February 15, 1999
7245  *
7246  * Modifications:
7247  *
7248  *-------------------------------------------------------------------------
7249  */
7250 SILO_CALLBACK int
db_hdf5_GetVarDims(DBfile * _dbfile,char const * name,int maxdims,int * dims)7251 db_hdf5_GetVarDims(DBfile *_dbfile, char const *name, int maxdims, int *dims/*out*/)
7252 {
7253     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7254     static char *me = "db_hdf5_GetVarDims";
7255     hid_t       dset=-1, space=-1;
7256     hsize_t     ds_size[H5S_MAX_RANK];
7257     int         i, ndims=-1;
7258 
7259     PROTECT {
7260         if ((dset=H5Dopen(dbfile->cwg, name))<0) {
7261             db_perror(name, E_NOTFOUND, me);
7262             UNWIND();
7263         }
7264         if ((space=H5Dget_space(dset))<0) {
7265             db_perror(name, E_CALLFAIL, me);
7266             UNWIND();
7267         }
7268         if ((ndims=H5Sget_simple_extent_dims(space, ds_size, NULL))<0) {
7269             db_perror(name, E_CALLFAIL, me);
7270             UNWIND();
7271         }
7272         for (i=0; i<maxdims; i++) dims[i] = ds_size[i];
7273         H5Sclose(space);
7274         H5Dclose(dset);
7275 
7276     } CLEANUP {
7277         H5E_BEGIN_TRY {
7278             H5Sclose(space);
7279             H5Dclose(dset);
7280         } H5E_END_TRY;
7281     } END_PROTECT;
7282 
7283     return ndims;
7284 }
7285 
7286 /*-------------------------------------------------------------------------
7287  * Function:    db_hdf5_GetVar
7288  *
7289  * Purpose:     Same as db_hdf5_ReadVar except it allocates space for the
7290  *              result.
7291  *
7292  * Return:      Success:        Ptr to data read, allocated with malloc()
7293  *
7294  *              Failure:        NULL
7295  *
7296  * Programmer:  Robb Matzke
7297  *              Thursday, February 11, 1999
7298  *
7299  * Modifications:
7300  *
7301  *   Mark C. Miller, Tue Feb 15 14:53:29 PST 2005
7302  *   Forced it to ignore force_single setting
7303  *
7304  *-------------------------------------------------------------------------
7305  */
7306 SILO_CALLBACK void *
db_hdf5_GetVar(DBfile * _dbfile,char const * name)7307 db_hdf5_GetVar(DBfile *_dbfile, char const *name)
7308 {
7309     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7310     static char *me = "db_hdf5_GetVar";
7311     hid_t       dset=-1, ftype=-1, mtype=-1, space=-1;
7312     void        *result=NULL;
7313 
7314     PROTECT {
7315 
7316         /* Get dataset, type, and space */
7317         if ((dset=H5Dopen(dbfile->cwg, name))>=0) {
7318             if ((ftype=H5Dget_type(dset))<0 ||
7319                 (space=H5Dget_space(dset))<0) {
7320                 db_perror(name, E_CALLFAIL, me);
7321                 UNWIND();
7322             }
7323 
7324             /* Choose a memory type based on the file type */
7325             if ((mtype=hdf2hdf_type(ftype))<0) {
7326                 db_perror("data type", E_BADARGS, me);
7327                 UNWIND();
7328             }
7329 
7330             /* Allocate space for the result */
7331             if (NULL==(result=malloc(H5Sget_simple_extent_npoints(space)*
7332                                      H5Tget_size(mtype)))) {
7333                 db_perror(NULL, E_NOMEM, me);
7334                 UNWIND();
7335             }
7336 
7337             P_rdprops = H5P_DEFAULT;
7338             if (!SILO_Globals.enableChecksums)
7339                 P_rdprops = P_ckrdprops;
7340 
7341             /* Read entire variable */
7342             if (H5Dread(dset, mtype, H5S_ALL, H5S_ALL, P_rdprops, result)<0) {
7343                 hdf5_to_silo_error(name, me);
7344                 UNWIND();
7345             }
7346 
7347             /* Close everything */
7348             H5Dclose(dset);
7349             H5Tclose(ftype);
7350             H5Sclose(space);
7351         }
7352         else
7353         {
7354             if (!db_hdf5_get_comp_var(dbfile->cwg, name, NULL,
7355                  NULL, NULL, &result)) {
7356                 db_perror(name, E_CALLFAIL, me);
7357                 UNWIND();
7358             }
7359         }
7360 
7361     } CLEANUP {
7362         H5E_BEGIN_TRY {
7363             H5Dclose(dset);
7364             H5Tclose(ftype);
7365             H5Sclose(space);
7366         } H5E_END_TRY;
7367         if (result) free(result);
7368     } END_PROTECT;
7369 
7370     return result;
7371 }
7372 
7373 /*-------------------------------------------------------------------------
7374  * Function:    db_hdf5_ReadVar
7375  *
7376  * Purpose:     Reads a variable into the given space.
7377  *
7378  * Return:      Success:        0
7379  *
7380  *              Failure:        -1
7381  *
7382  * Programmer:  Robb Matzke
7383  *              Tuesday, February  9, 1999
7384  *
7385  * Modifications:
7386  *
7387  *   Mark C. Miller, Tue Feb 15 14:53:29 PST 2005
7388  *   Forced it to ignore force_single setting
7389  *
7390  *-------------------------------------------------------------------------
7391  */
7392 SILO_CALLBACK int
db_hdf5_ReadVar(DBfile * _dbfile,char const * vname,void * result)7393 db_hdf5_ReadVar(DBfile *_dbfile, char const *vname, void *result)
7394 {
7395    DBfile_hdf5  *dbfile = (DBfile_hdf5*)_dbfile;
7396    static char  *me = "db_hdf5_ReadVar";
7397    hid_t        dset=-1, mtype=-1, ftype=-1;
7398 
7399    PROTECT {
7400 
7401        /* Get dataset and data type */
7402        if ((dset=H5Dopen(dbfile->cwg, vname))>=0) {
7403            if ((ftype=H5Dget_type(dset))<0) {
7404                db_perror(vname, E_CALLFAIL, me);
7405                UNWIND();
7406            }
7407 
7408            /* Memory data type is based on file data type */
7409            if ((mtype=hdf2hdf_type(ftype))<0) {
7410                db_perror("data type", E_BADARGS, me);
7411                UNWIND();
7412            }
7413 
7414            P_rdprops = H5P_DEFAULT;
7415            if (!SILO_Globals.enableChecksums)
7416                P_rdprops = P_ckrdprops;
7417 
7418            /* Read entire variable */
7419            if (H5Dread(dset, mtype, H5S_ALL, H5S_ALL, P_rdprops, result)<0) {
7420                hdf5_to_silo_error(vname, me);
7421                UNWIND();
7422            }
7423 
7424            /* Close everything */
7425            H5Dclose(dset);
7426            H5Tclose(ftype);
7427         }
7428         else
7429         {
7430             if (!db_hdf5_get_comp_var(dbfile->cwg, vname, NULL,
7431                  NULL, NULL, &result)) {
7432                 db_perror(vname, E_CALLFAIL, me);
7433                 UNWIND();
7434             }
7435         }
7436 
7437    } CLEANUP {
7438        H5E_BEGIN_TRY {
7439            H5Dclose(dset);
7440            H5Tclose(ftype);
7441        } H5E_END_TRY;
7442    } END_PROTECT;
7443 
7444    return 0;
7445 }
7446 
7447 /*-------------------------------------------------------------------------
7448  * Function:    db_hdf5_ReadVarSlice
7449  *
7450  * Purpose:     Reads a slice of a variable into the given memory. The slice
7451  *              is described with a multi-dimensional offset, length, and
7452  *              stride and is translated into an HDF5 hyperslab selection.
7453  *
7454  * Return:      Success:        0
7455  *
7456  *              Failure:        -1
7457  *
7458  * Programmer:  Robb Matzke
7459  *              Tuesday, February  9, 1999
7460  *
7461  * Modifications:
7462  *
7463  *-------------------------------------------------------------------------
7464  */
7465 SILO_CALLBACK int
db_hdf5_ReadVarSlice(DBfile * _dbfile,char const * vname,int const * offset,int const * length,int const * stride,int ndims,void * result)7466 db_hdf5_ReadVarSlice(DBfile *_dbfile, char const *vname, int const *offset, int const *length,
7467                      int const *stride, int ndims, void *result)
7468 {
7469    DBfile_hdf5  *dbfile = (DBfile_hdf5*)_dbfile;
7470    static char  *me = "db_hdf5_ReadVarSlice";
7471    hid_t        dset=-1, ftype=-1, mtype=-1, mspace=-1, fspace=-1;
7472    hsize_t      mem_size[H5S_MAX_RANK];
7473 
7474    PROTECT {
7475        /* Get dataset and data type */
7476        if ((dset=H5Dopen(dbfile->cwg, vname))<0) {
7477            db_perror(vname, E_CALLFAIL, me);
7478            UNWIND();
7479        }
7480        if ((ftype=H5Dget_type(dset))<0) {
7481            db_perror(vname, E_CALLFAIL, me);
7482            UNWIND();
7483        }
7484 
7485        /* Memory data type is based on file data type */
7486        if ((mtype=hdf2hdf_type(ftype))<0) {
7487            db_perror("data type", E_BADARGS, me);
7488            UNWIND();
7489        }
7490 
7491        /* Build file selection */
7492        if ((fspace=build_fspace(dset, ndims, offset, length, stride,
7493                                 mem_size))<0) {
7494            db_perror(vname, E_CALLFAIL, me);
7495            UNWIND();
7496        }
7497 
7498        /* Build the memory space */
7499        if ((mspace=H5Screate_simple(ndims, mem_size, NULL))<0) {
7500            db_perror("memory data space", E_CALLFAIL, me);
7501            UNWIND();
7502        }
7503 
7504        P_rdprops = H5P_DEFAULT;
7505        if (!SILO_Globals.enableChecksums)
7506            P_rdprops = P_ckrdprops;
7507 
7508        /* Read the data */
7509        if (H5Dread(dset, mtype, mspace, fspace, P_rdprops, result)<0) {
7510            hdf5_to_silo_error(vname, me);
7511            UNWIND();
7512        }
7513 
7514        /* Close everything */
7515        H5Dclose(dset);
7516        H5Tclose(ftype);
7517        H5Sclose(fspace);
7518        H5Sclose(mspace);
7519 
7520    } CLEANUP {
7521        H5E_BEGIN_TRY {
7522            H5Dclose(dset);
7523            H5Tclose(ftype);
7524            H5Sclose(fspace);
7525            H5Sclose(mspace);
7526        } H5E_END_TRY;
7527    } END_PROTECT;
7528 
7529    return 0;
7530 }
7531 
7532 /*-------------------------------------------------------------------------
7533  * Function:    db_hdf5_Write
7534  *
7535  * Purpose:     Writes a single variable into a file. The variable may
7536  *              already exist, in which case the NDIMS and DIMS must match
7537  *              what has already been defined.
7538  *
7539  * Return:      Success:        0
7540  *
7541  *              Failure:        -1
7542  *
7543  * Programmer:  Robb Matzke
7544  *              Tuesday, February  9, 1999
7545  *
7546  * Modifications:
7547  *
7548  *-------------------------------------------------------------------------
7549  */
7550 SILO_CALLBACK int
db_hdf5_Write(DBfile * _dbfile,char const * vname,void const * var,int const * dims,int ndims,int datatype)7551 db_hdf5_Write(DBfile *_dbfile, char const *vname, void const *var,
7552               int const *dims, int ndims, int datatype)
7553 {
7554     const int nofilters = 0;
7555     return db_hdf5_WriteCKZ(_dbfile, vname, var, dims, ndims, datatype, nofilters);
7556 }
7557 
7558 PRIVATE int
db_hdf5_WriteCKZ(DBfile * _dbfile,char const * vname,void const * var,int const * dims,int ndims,int datatype,int nofilters)7559 db_hdf5_WriteCKZ(DBfile *_dbfile, char const *vname, void const *var,
7560               int const *dims, int ndims, int datatype, int nofilters)
7561 {
7562    DBfile_hdf5  *dbfile = (DBfile_hdf5*)_dbfile;
7563    static char  *me = "db_hdf5_Write";
7564    hid_t        mtype=-1, ftype=-1, space=-1, dset=-1, dset_type=-1;
7565    hsize_t      ds_size[H5S_MAX_RANK];
7566    H5T_class_t  fclass, mclass;
7567    int          i;
7568 
7569    PROTECT {
7570        /* Create the memory and file data type */
7571        if ((mtype=silom2hdfm_type(datatype))<0 ||
7572            (ftype=silof2hdff_type(dbfile, datatype))<0) {
7573            db_perror("datatype", E_BADARGS, me);
7574            UNWIND();
7575        }
7576 
7577        /*
7578         * If the dataset already exists then make sure that the supplied
7579         * NDIMS and DIMS match what's already defined; otherwise create a new
7580         * dataset.
7581         */
7582        H5E_BEGIN_TRY {
7583            dset = H5Dopen(dbfile->cwg, vname);
7584        } H5E_END_TRY;
7585        if (dset>=0) {
7586            space = H5Dget_space(dset);
7587            if (ndims!=H5Sget_simple_extent_ndims(space)) {
7588                db_perror("ndims", E_BADARGS, me);
7589                UNWIND();
7590            }
7591            H5Sget_simple_extent_dims(space, ds_size, NULL);
7592            for (i=0; i<ndims; i++) {
7593                if (ds_size[i]<(hsize_t)dims[i]) {
7594                    db_perror("dims", E_BADARGS, me);
7595                    UNWIND();
7596                }
7597            }
7598 //#warning WHAT IF EXISTING DATASET WAS COMPRESSED
7599        } else {
7600            /* Create memory and file data space (both identical) */
7601            for (i=0; i<ndims; i++) ds_size[i] = dims[i];
7602            if ((space=H5Screate_simple(ndims, ds_size, NULL))<0) {
7603                db_perror("data space", E_CALLFAIL, me);
7604                UNWIND();
7605            }
7606 
7607            if (nofilters == 0)
7608            {
7609                if (db_hdf5_set_properties(ndims, ds_size) < 0 ) {
7610                    db_perror("db_hdf5_set_properties", E_CALLFAIL, me);
7611                    UNWIND();
7612                }
7613 
7614                /* Create dataset if it doesn't already exist */
7615                if ((dset=H5Dcreate(dbfile->cwg, vname, ftype, space, P_crprops))<0) {
7616                    db_perror(vname, E_CALLFAIL, me);
7617                    UNWIND();
7618                }
7619            }
7620            else
7621            {
7622                /* Create dataset if it doesn't already exist */
7623                if ((dset=H5Dcreate(dbfile->cwg, vname, ftype, space, H5P_DEFAULT))<0) {
7624                    db_perror(vname, E_CALLFAIL, me);
7625                    UNWIND();
7626                }
7627            }
7628        }
7629 
7630 #if HDF5_VERSION_GE(1,8,0)
7631        /* Do an additional explicit check for compatibile data types.
7632           This was NOT necessary prior to 1.8. But, 1.8 now permits
7633           writes of int data to float dataset, for example. */
7634        if ((dset_type = H5Dget_type(dset))<0 ||
7635            (fclass = H5Tget_class(dset_type))<0 ||
7636            (mclass = H5Tget_class(mtype))<0) {
7637            db_perror(vname, E_CALLFAIL, me);
7638            UNWIND();
7639        }
7640        if (mclass != fclass) {
7641            db_perror(vname, E_CALLFAIL, me);
7642            UNWIND();
7643        }
7644        H5Tclose(dset_type);
7645 #endif
7646 
7647        /* Write data */
7648        if (H5Dwrite(dset, mtype, space, space, H5P_DEFAULT, var)<0) {
7649            db_perror(vname, E_CALLFAIL, me);
7650            UNWIND();
7651        }
7652 
7653        /* Close everything */
7654        H5Dclose(dset);
7655        H5Sclose(space);
7656    } CLEANUP {
7657        H5E_BEGIN_TRY {
7658            H5Dclose(dset);
7659            H5Sclose(space);
7660            H5Tclose(dset_type);
7661        } H5E_END_TRY;
7662    } END_PROTECT;
7663 
7664    return 0;
7665 }
7666 
7667 /*-------------------------------------------------------------------------
7668  * Function:    db_hdf5_WriteSlice
7669  *
7670  * Purpose:     Similar to db_hdf5_ReadVarSlice() except it writes data
7671  *              instead.
7672  *
7673  * Return:      Success:        0
7674  *
7675  *              Failure:        -1
7676  *
7677  * Programmer:  Robb Matzke
7678  *              Tuesday, February  9, 1999
7679  *
7680  * Modifications:
7681  *
7682  *-------------------------------------------------------------------------
7683  */
7684 SILO_CALLBACK int
db_hdf5_WriteSlice(DBfile * _dbfile,char const * vname,void const * values,int dtype,int const * offset,int const * length,int const * stride,int const * dims,int ndims)7685 db_hdf5_WriteSlice(
7686     DBfile *_dbfile,
7687     char const *vname,
7688     void const *values,
7689     int dtype,
7690     int const *offset,
7691     int const *length,
7692     int const *stride,
7693     int const *dims,
7694     int ndims
7695 )
7696 {
7697    DBfile_hdf5  *dbfile = (DBfile_hdf5*)_dbfile ;
7698    static char  *me = "db_hdf5_WriteSlice" ;
7699    hid_t        mtype=-1, ftype=-1, fspace=-1, mspace=-1, dset=-1;
7700    hsize_t      ds_size[H5S_MAX_RANK];
7701    int          i;
7702 
7703    PROTECT {
7704        if ((mtype=silom2hdfm_type(dtype))<0 ||
7705            (ftype=silof2hdff_type(dbfile, dtype))<0) {
7706            db_perror("datatype", E_BADARGS, me);
7707            UNWIND();
7708        }
7709 
7710        /*
7711         * If the dataset already exists then make sure that the supplied
7712         * NDIMS and DIMS match what's already defined. Otherwise create the
7713         * dataset.
7714         */
7715        H5E_BEGIN_TRY {
7716            dset = H5Dopen(dbfile->cwg, vname);
7717        } H5E_END_TRY;
7718        if (dset>=0) {
7719            fspace = H5Dget_space(dset);
7720            if (ndims!=H5Sget_simple_extent_ndims(fspace)) {
7721                db_perror("ndims", E_BADARGS, me);
7722                UNWIND();
7723            }
7724            H5Sget_simple_extent_dims(fspace, ds_size, NULL);
7725            for (i=0; i<ndims; i++) {
7726                if (ds_size[i]!=(hsize_t)dims[i]) {
7727                    db_perror("dims", E_BADARGS, me);
7728                    UNWIND();
7729                }
7730            }
7731            H5Sclose(fspace);
7732        } else {
7733            for (i=0; i<ndims; i++) ds_size[i] = dims[i];
7734            if ((fspace=H5Screate_simple(ndims, ds_size, NULL))<0) {
7735                db_perror("data space", E_CALLFAIL, me);
7736                UNWIND();
7737            }
7738 
7739            if (db_hdf5_set_properties(ndims, ds_size) < 0 ) {
7740                db_perror("db_hdf5_set_properties", E_CALLFAIL, me);
7741                UNWIND();
7742            }
7743 
7744            if ((dset=H5Dcreate(dbfile->cwg, vname, ftype, fspace,
7745                                P_crprops))<0) {
7746                db_perror(vname, E_CALLFAIL, me);
7747                UNWIND();
7748            }
7749            H5Sclose(fspace);
7750        }
7751 
7752        /*
7753         * Verify that offset and length are compatible with the supplied
7754         * dimensions.
7755         */
7756        for (i=0; i<ndims; i++) {
7757            if (offset[i]<0 || offset[i]>=dims[i]) {
7758                db_perror("offset", E_BADARGS, me);
7759                UNWIND();
7760            }
7761            if (length[i]<=0 || length[i]>dims[i]) {
7762                db_perror("length", E_BADARGS, me);
7763                UNWIND();
7764            }
7765            if (offset[i]+length[i]>dims[i]) {
7766                db_perror("offset+length", E_BADARGS, me);
7767                UNWIND();
7768            }
7769        }
7770 
7771        /* Build the file space selection */
7772        if ((fspace=build_fspace(dset, ndims, offset, length, stride,
7773                                 ds_size/*out*/))<0) {
7774            db_perror(vname, E_CALLFAIL, me);
7775            UNWIND();
7776        }
7777 
7778        /* Build the memory data space */
7779        if ((mspace=H5Screate_simple(ndims, ds_size, NULL))<0) {
7780            db_perror("memory data space", E_CALLFAIL, me);
7781            UNWIND();
7782        }
7783 
7784        /* Write data */
7785        if (H5Dwrite(dset, mtype, mspace, fspace, H5P_DEFAULT, values)<0) {
7786            db_perror(vname, E_CALLFAIL, me);
7787            UNWIND();
7788        }
7789 
7790        /* Close everything */
7791        H5Dclose(dset);
7792        H5Sclose(fspace);
7793        H5Sclose(mspace);
7794    } CLEANUP {
7795        H5E_BEGIN_TRY {
7796            H5Dclose(dset);
7797            H5Sclose(fspace);
7798            H5Sclose(mspace);
7799        } H5E_END_TRY;
7800    } END_PROTECT;
7801 
7802    return 0;
7803 }
7804 
7805 /*-------------------------------------------------------------------------
7806  * Function:    db_hdf5_GetObject
7807  *
7808  * Purpose:     Reads information about a silo object.
7809  *
7810  * Return:      Success:        Ptr to new object.
7811  *
7812  *              Failure:        NULL
7813  *
7814  * Programmer:  Robb Matzke
7815  *              Tuesday, March 23, 1999
7816  *
7817  * Modifications:
7818  *
7819  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
7820  *   I removed the seen_datatype functionality
7821  *
7822  *-------------------------------------------------------------------------
7823  */
7824 SILO_CALLBACK DBobject *
db_hdf5_GetObject(DBfile * _dbfile,char const * name)7825 db_hdf5_GetObject(DBfile *_dbfile, char const *name)
7826 {
7827     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
7828     static char *me = "db_hdf5_GetObject";
7829     hid_t       o=-1, attr=-1, atype=-1, s1024=-1;
7830     char        *file_value=NULL, *mem_value=NULL, *bkg=NULL, bigname[1024];
7831     DBObjectType objtype;
7832     int         _objtype, nmembs, i, j, memb_size[4];
7833     DBobject    *obj=NULL;
7834     size_t      asize, nelmts, msize;
7835 
7836     PROTECT {
7837         /* Open the object as a named data type */
7838         if ((o=H5Topen(dbfile->cwg, name))<0) {
7839             db_perror(name, E_NOTFOUND, me);
7840             UNWIND();
7841         }
7842 
7843         /* Open the `silo_type' attribute and read it */
7844         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
7845             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
7846             H5Aclose(attr)<0) {
7847             db_perror(name, E_CALLFAIL, me);
7848             UNWIND();
7849         }
7850         objtype = (DBObjectType)_objtype;
7851 
7852         /*
7853          * Open the `silo' attribute (all silo objects have one), retrieve
7854          * its data type (a single-level H5T_COMPOUND type), and read the
7855          * attribute.
7856          */
7857         if ((attr=H5Aopen_name(o, "silo"))<0 ||
7858             (atype=H5Aget_type(attr))<0) {
7859             db_perror(name, E_CALLFAIL, me);
7860             UNWIND();
7861         }
7862         asize = H5Tget_size(atype);
7863         msize = MAX(asize, 3*1024);
7864         if (NULL==(file_value=(char *)malloc(asize)) ||
7865             NULL==(mem_value=(char *)malloc(msize)) ||
7866             NULL==(bkg=(char *)malloc(msize))) {
7867             db_perror(name, E_NOMEM, me);
7868             UNWIND();
7869         }
7870         if (H5Aread(attr, atype, file_value)<0) {
7871             db_perror(name, E_CALLFAIL, me);
7872             UNWIND();
7873         }
7874         nmembs = H5Tget_nmembers(atype);
7875 
7876         /* Create the empty DBobject */
7877         if (NULL==(obj=DBMakeObject(name, objtype, 3*nmembs))) {
7878             db_perror(name, E_CALLFAIL, me);
7879             UNWIND();
7880         }
7881 
7882         /* Add members to the DBobject */
7883         s1024 = H5Tcopy(H5T_C_S1);
7884         H5Tset_size(s1024, 1024);
7885         for (i=0; i<nmembs; i++) {
7886             int ndims = 0;
7887             hid_t member_type = db_hdf5_get_cmemb(atype, i, &ndims, memb_size);
7888             char *name = H5Tget_member_name(atype, i);
7889             hid_t mtype = H5Tcreate(H5T_COMPOUND, msize);
7890             for (nelmts=1, j=0; j<ndims; j++) nelmts *= memb_size[j];
7891 
7892             switch (H5Tget_class(member_type)) {
7893             case H5T_INTEGER:
7894                 db_hdf5_put_cmemb(mtype, name, 0, ndims, memb_size,
7895                                   H5T_NATIVE_INT);
7896                 memcpy(mem_value, file_value, H5Tget_size(atype));
7897                 H5Tconvert(atype, mtype, 1, mem_value, bkg, H5P_DEFAULT);
7898                 if (1==nelmts) {
7899                     DBAddIntComponent(obj, name, *((int*)mem_value));
7900                 } else {
7901                     for (j=0; (size_t)j<nelmts; j++) {
7902                         sprintf(bigname, "%s%d", name, j+1);
7903                         DBAddIntComponent(obj, bigname, ((int*)mem_value)[j]);
7904                     }
7905                 }
7906                 break;
7907 
7908             case H5T_FLOAT:
7909                 db_hdf5_put_cmemb(mtype, name, 0, ndims, memb_size,
7910                                   H5T_NATIVE_DOUBLE);
7911                 memcpy(mem_value, file_value, H5Tget_size(atype));
7912                 H5Tconvert(atype, mtype, 1, mem_value, bkg, H5P_DEFAULT);
7913                 if (1==nelmts) {
7914                     DBAddFltComponent(obj, name, *((double*)mem_value));
7915                 } else {
7916                     for (j=0; (size_t)j<nelmts; j++) {
7917                         sprintf(bigname, "%s%d", name, j+1);
7918                         DBAddFltComponent(obj, bigname,
7919                                           ((double*)mem_value)[j]);
7920                     }
7921                 }
7922                 break;
7923 
7924             case H5T_STRING:
7925                 db_hdf5_put_cmemb(mtype, name, 0, ndims, memb_size, s1024);
7926                 memcpy(mem_value, file_value, H5Tget_size(atype));
7927                 H5Tconvert(atype, mtype, 1, mem_value, bkg, H5P_DEFAULT);
7928                 if (1==nelmts) {
7929                     DBAddStrComponent(obj, name, mem_value);
7930                 } else {
7931                     for (j=0; (size_t)j<nelmts; j++) {
7932                         sprintf(bigname, "%s%d", name, j+1);
7933                         DBAddStrComponent(obj, bigname,
7934                                           mem_value+j*1024);
7935                     }
7936                 }
7937                 break;
7938 
7939             default:
7940                 /* Silo doesn't handle other types */
7941                 break;
7942             }
7943 
7944             /* Release member resources */
7945             free(name);
7946             H5Tclose(mtype);
7947             H5Tclose(member_type);
7948         }
7949 
7950         /* Cleanup */
7951         H5Tclose(atype);
7952         H5Tclose(s1024);
7953         H5Aclose(attr);
7954         H5Tclose(o);
7955         free(file_value);
7956         free(mem_value);
7957         free(bkg);
7958 
7959     } CLEANUP {
7960         H5E_BEGIN_TRY {
7961             H5Tclose(atype);
7962             H5Tclose(s1024);
7963             H5Aclose(attr);
7964             H5Tclose(o);
7965         } H5E_END_TRY;
7966         if (file_value) free(file_value);
7967         if (mem_value) free(mem_value);
7968         if (bkg) free(bkg);
7969     } END_PROTECT;
7970 
7971     return obj;
7972 }
7973 
7974 /*-------------------------------------------------------------------------
7975  * Function:    db_hdf5_PutCurve
7976  *
7977  * Purpose:     Put a curve object into the file.
7978  *
7979  * Return:      Success:        0
7980  *
7981  *              Failure:        -1, db_errno set
7982  *
7983  * Programmer:  Robb Matzke
7984  *              Tuesday, March 23, 1999
7985  *
7986  * Modifications:
7987  *
7988  *  Thomas R. Treadway, Fri Jul  7 12:44:38 PDT 2006
7989  *  Added support for DBOPT_REFERENCE in Curves
7990  *
7991  *  Mark C. Miller, Mon Jul 31 17:57:29 PDT 2006
7992  *  Eliminated use of db_hdf5_fullname for xvarname and yvarname
7993  *
7994  *  Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
7995  *  Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
7996  *-------------------------------------------------------------------------
7997  */
7998 SILO_CALLBACK int
db_hdf5_PutCurve(DBfile * _dbfile,char const * name,void const * xvals,void const * yvals,int dtype,int npts,DBoptlist const * opts)7999 db_hdf5_PutCurve(DBfile *_dbfile, char const *name, void const *xvals, void const *yvals,
8000                  int dtype, int npts, DBoptlist const *opts)
8001 {
8002     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
8003     static char *me = "db_hdf5_PutCurve";
8004     DBcurve_mt  m;
8005 
8006     memset(&m, 0, sizeof m);
8007     PROTECT {
8008         /* Check datatype */
8009         if (DB_FLOAT!=dtype && DB_DOUBLE!=dtype) {
8010             db_perror("invalid floating-point datatype", E_BADARGS, me);
8011             UNWIND();
8012         }
8013 
8014         /* Reset global curve options */
8015         memset(&_cu, 0, sizeof _cu);
8016         _cu._missing_value = DB_MISSING_VALUE_NOT_SET;
8017         if (0!=db_ProcessOptlist(DB_CURVE, opts)) {
8018             db_perror("bad options", E_CALLFAIL, me);
8019             UNWIND();
8020         }
8021 
8022         /* Write X and Y arrays if supplied */
8023         if (npts && xvals) {
8024             db_hdf5_compwr(dbfile, dtype, 1, &npts, xvals, m.xvarname/*out*/,
8025                 friendly_name(name, "_xvals", 0));
8026         } else if (_cu._varname[0]) {
8027             db_hdf5_fullname(dbfile, _cu._varname[0], m.xvarname/*out*/);
8028         }
8029 
8030         if (npts && yvals) {
8031             db_hdf5_compwr(dbfile, dtype, 1, &npts, yvals, m.yvarname/*out*/,
8032                 friendly_name(name, "_yvals", 0));
8033         } else if (_cu._varname[1]) {
8034             db_hdf5_fullname(dbfile, _cu._varname[1], m.yvarname/*out*/);
8035         }
8036 
8037         /* Build the curve header in memory */
8038         m.npts = npts;
8039         m.guihide = _cu._guihide;
8040         m.coord_sys = _cu._coord_sys;
8041         db_SetMissingValueForPut(m.missing_value, _cu._missing_value);
8042         strcpy(m.label, OPT(_cu._label));
8043         strcpy(m.xlabel, OPT(_cu._labels[0]));
8044         strcpy(m.ylabel, OPT(_cu._labels[1]));
8045         strcpy(m.xunits, OPT(_cu._units[0]));
8046         strcpy(m.yunits, OPT(_cu._units[1]));
8047         strcpy(m.reference, OPT(_cu._reference));
8048 
8049         /* Write curve header to file */
8050         STRUCT(DBcurve) {
8051             if (m.npts) MEMBER_S(int, npts);
8052             if (m.guihide) MEMBER_S(int, guihide);
8053             if (m.coord_sys) MEMBER_S(int, coord_sys);
8054             if (m.missing_value) MEMBER_S(double, missing_value);
8055             MEMBER_S(str(_cu._label), label);
8056             MEMBER_S(str(m.xvarname), xvarname);
8057             MEMBER_S(str(m.yvarname), yvarname);
8058             MEMBER_S(str(_cu._labels[0]), xlabel);
8059             MEMBER_S(str(_cu._labels[1]), ylabel);
8060             MEMBER_S(str(_cu._units[0]), xunits);
8061             MEMBER_S(str(_cu._units[1]), yunits);
8062             MEMBER_S(str(_cu._reference), reference);
8063         } OUTPUT(dbfile, DB_CURVE, name, &m);
8064 
8065     } CLEANUP {
8066         /*void*/;
8067     } END_PROTECT;
8068     return 0;
8069 }
8070 
8071 /*-------------------------------------------------------------------------
8072  * Function:    db_hdf5_GetCurve
8073  *
8074  * Purpose:     Read a curve object from a PDB data file.
8075  *
8076  * Return:      Success:        Pointer to new curve object
8077  *
8078  *              Failure:        NULL
8079  *
8080  * Programmer:  Robb Matzke
8081  *              Thursday, March 25, 1999
8082  *
8083  * Modifications:
8084  *
8085  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
8086  *   Made it set datatype correctly. Added support for dataReadMask
8087  *
8088  *  Thomas R. Treadway, Fri Jul  7 12:44:38 PDT 2006
8089  *  Added support for DBOPT_REFERENCE in Curves
8090  *
8091  *   Mark C. Miller, Thu Sep  7 10:50:55 PDT 2006
8092  *   Added use of db_hdf5_resolvename for retrieval of x-data object
8093  *-------------------------------------------------------------------------
8094  */
8095 SILO_CALLBACK DBcurve *
db_hdf5_GetCurve(DBfile * _dbfile,char const * name)8096 db_hdf5_GetCurve(DBfile *_dbfile, char const *name)
8097 {
8098     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8099     static char         *me = "db_hdf5_GetCurve";
8100     DBcurve             *cu = NULL;
8101     DBcurve_mt          m;
8102     hid_t               o=-1, attr=-1;
8103     int                 _objtype;
8104 
8105     PROTECT {
8106         /* Open object and make sure it's a curve */
8107         if ((o=H5Topen(dbfile->cwg, name))<0) {
8108             db_perror(name, E_NOTFOUND, me);
8109             UNWIND();
8110         }
8111         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
8112             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
8113             H5Aclose(attr)<0) {
8114             db_perror(name, E_CALLFAIL, me);
8115             UNWIND();
8116         }
8117         if (DB_CURVE!=(DBObjectType)_objtype) {
8118             db_perror(name, E_CALLFAIL, me);
8119             UNWIND();
8120         }
8121 
8122         /* Read the curve data into memory */
8123         memset(&m, 0, sizeof m);
8124         if ((attr=H5Aopen_name(o, "silo"))<0 ||
8125             H5Aread(attr, DBcurve_mt5, &m)<0 ||
8126             H5Aclose(attr)<0) {
8127             db_perror(name, E_CALLFAIL, me);
8128             UNWIND();
8129         }
8130 
8131         /* Create a curve object and initialize meta data */
8132         if (NULL==(cu=DBAllocCurve())) return NULL;
8133         cu->npts = m.npts;
8134         cu->guihide = m.guihide;
8135         cu->coord_sys = m.coord_sys;
8136         cu->datatype = DB_FLOAT;
8137         if (strlen(m.xvarname)) {
8138             if ((cu->datatype = db_hdf5_GetVarType(_dbfile,
8139                                 db_hdf5_resolvename(_dbfile, name, m.xvarname))) < 0)
8140                 cu->datatype = DB_FLOAT;
8141         }
8142         if (force_single_g) cu->datatype = DB_FLOAT;
8143         cu->title = OPTDUP(m.label);
8144         if (strncmp(m.xvarname, "/.silo/#", 8))
8145             cu->xvarname = OPTDUP(m.xvarname);
8146         if (strncmp(m.yvarname, "/.silo/#", 8))
8147             cu->yvarname = OPTDUP(m.yvarname);
8148         cu->xlabel = OPTDUP(m.xlabel);
8149         cu->ylabel = OPTDUP(m.ylabel);
8150         cu->xunits = OPTDUP(m.xunits);
8151         cu->yunits = OPTDUP(m.yunits);
8152         cu->reference = OPTDUP(m.reference);
8153         db_SetMissingValueForGet(cu->missing_value, m.missing_value);
8154 
8155         /* Read X and Y data */
8156         if (SILO_Globals.dataReadMask & DBCurveArrays)
8157         {
8158             if (cu->reference) {
8159                 cu->x = NULL;
8160                 cu->y = NULL;
8161             } else {
8162                 cu->x = db_hdf5_comprd(dbfile, m.xvarname, 0);
8163                 cu->y = db_hdf5_comprd(dbfile, m.yvarname, 0);
8164             }
8165         }
8166         H5Tclose(o);
8167 
8168     } CLEANUP {
8169         H5E_BEGIN_TRY {
8170             H5Aclose(attr);
8171             H5Tclose(o);
8172         } H5E_END_TRY;
8173         DBFreeCurve(cu);
8174     } END_PROTECT;
8175 
8176     return cu;
8177 }
8178 
8179 /*-------------------------------------------------------------------------
8180  * Function:    db_hdf5_PutCsgmesh
8181  *
8182  * Purpose:     Writes a Csgmesh to the silo file.
8183  *
8184  * Return:      Success:        0
8185  *
8186  *              Failure:        -1
8187  *
8188  * Programmer:  Mark C. Miller
8189  *              Tuesday, September 6, 2005
8190  *
8191  * Modifications:
8192  *
8193  *   Mark C. Miller, Mon Jul 31 17:57:29 PDT 2006
8194  *   Eliminated use of db_hdf5_fullname for zonel_name
8195  *
8196  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
8197  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
8198  *
8199  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
8200  *   Refactored logic to handle time, dtime and cycle to a new method,
8201  *   db_hdf5_handle_ctdt().
8202  *-------------------------------------------------------------------------
8203  */
8204 /*ARGSUSED*/
8205 SILO_CALLBACK int
db_hdf5_PutCsgmesh(DBfile * _dbfile,char const * name,int ndims,int nbounds,int const * typeflags,int const * bndids,void const * coeffs,int lcoeffs,int datatype,double const * extents,char const * zonel_name,DBoptlist const * optlist)8206 db_hdf5_PutCsgmesh(DBfile *_dbfile, char const *name, int ndims,
8207                    int nbounds, int const *typeflags, int const *bndids,
8208                    void const *coeffs, int lcoeffs, int datatype,
8209                    double const *extents, char const *zonel_name,
8210                    DBoptlist const *optlist)
8211 {
8212     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8213     static char         *me = "db_hdf5_PutCsgmesh";
8214     int                 i;
8215     DBcsgmesh_mt        m;
8216 
8217     memset(&m, 0, sizeof m);
8218 
8219     PROTECT {
8220 
8221         /* Set global options */
8222         db_ResetGlobalData_Csgmesh();
8223         if (db_ProcessOptlist(DB_CSGMESH, optlist)<0) {
8224             db_perror("bad options", E_CALLFAIL, me);
8225             UNWIND();
8226         }
8227 
8228         /* hack to maintain backward compatibility with pdb driver */
8229         db_hdf5_handle_ctdt(dbfile, _csgm._time_set, _csgm._time,
8230             _csgm._dtime_set, _csgm._dtime, _csgm._cycle);
8231 
8232         if (extents)
8233         {
8234             m.min_extents[0] = extents[0];
8235             m.min_extents[1] = extents[1];
8236             m.min_extents[2] = extents[2];
8237             m.max_extents[0] = extents[3];
8238             m.max_extents[1] = extents[4];
8239             m.max_extents[2] = extents[5];
8240         }
8241 
8242         if (nbounds)
8243         {
8244             db_hdf5_compwr(dbfile,DB_INT,1,&nbounds,(void*)typeflags,m.typeflags/*out*/, friendly_name(name, "_typeflags", 0));
8245             if (bndids)
8246                 db_hdf5_compwr(dbfile,DB_INT,1,&nbounds,(void*)bndids,m.bndids/*out*/, friendly_name(name, "_bndids", 0));
8247             db_hdf5_compwr(dbfile,datatype,1,&lcoeffs,(void*)coeffs,m.coeffs/*out*/, friendly_name(name, "_coeffs", 0));
8248         }
8249 
8250         /* Build csgmesh header in memory */
8251         m.ndims = ndims;
8252         m.cycle = _csgm._cycle;
8253         m.origin = _csgm._origin;
8254         m.group_no = _csgm._group_no;
8255         m.guihide = _csgm._guihide;
8256         strcpy(m.name, name);
8257         for (i=0; i<ndims; i++) {
8258             strcpy(m.labels[i], OPT(_csgm._labels[i]));
8259             strcpy(m.units[i], OPT(_csgm._units[i]));
8260         }
8261         m.time = _csgm._time_set ? _csgm._time : 0;
8262         m.dtime = _csgm._dtime_set ? _csgm._dtime : 0;
8263         m.nbounds = nbounds;
8264         m.lcoeffs = lcoeffs;
8265         m.tv_connectivity = _csgm._tv_connectivity;
8266         m.disjoint_mode = _csgm._disjoint_mode;
8267         if (zonel_name)
8268             strcpy(m.zonel_name, zonel_name);
8269         strcpy(m.mrgtree_name, OPT(_csgm._mrgtree_name));
8270 
8271         if (_csgm._alt_nodenum_vars != NULL) {
8272             char *s; int len;
8273             DBStringArrayToStringList((char const * const *)_csgm._alt_nodenum_vars, -1, &s, &len);
8274             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.alt_nodenum_vars/*out*/,
8275                 friendly_name(name, "_alt_nodenum_vars", 0));
8276             FREE(s);
8277         }
8278 
8279         /* Build csgmesh header in file */
8280         STRUCT(DBcsgmesh) {
8281             if (m.group_no)       MEMBER_S(int, group_no);
8282             if (m.cycle)          MEMBER_S(int, cycle);
8283             if (_csgm._time_set)  MEMBER_S(float, time);
8284             if (_csgm._dtime_set) MEMBER_S(double, dtime);
8285             if (m.origin)         MEMBER_S(int, origin);
8286             if (bndids)           MEMBER_S(str(m.bndids), bndids);
8287             if (m.guihide)        MEMBER_S(int, guihide);
8288             MEMBER_S(int, lcoeffs);
8289             MEMBER_S(int, nbounds);
8290             MEMBER_S(int, ndims);
8291             MEMBER_3(double, min_extents);
8292             MEMBER_3(double, max_extents);
8293             MEMBER_R(str(m.units[_j]), units, ndims);
8294             MEMBER_R(str(m.labels[_j]), labels, ndims);
8295             MEMBER_S(str(m.typeflags), typeflags);
8296             MEMBER_S(str(m.coeffs), coeffs);
8297             MEMBER_S(str(m.zonel_name), zonel_name);
8298             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
8299             if (m.tv_connectivity) MEMBER_S(int, tv_connectivity);
8300             if (m.disjoint_mode)   MEMBER_S(int, disjoint_mode);
8301             MEMBER_S(str(m.alt_nodenum_vars), alt_nodenum_vars);
8302         } OUTPUT(dbfile, DB_CSGMESH, name, &m);
8303 
8304     } CLEANUP {
8305         /*void*/
8306     } END_PROTECT;
8307     return 0;
8308 }
8309 
8310 /*-------------------------------------------------------------------------
8311  * Function:    db_hdf5_GetCsgmesh
8312  *
8313  * Purpose:     Reads a CSG mesh object from the file.
8314  *
8315  * Return:      Success:        Pointer to a new csgmesh.
8316  *
8317  *              Failure:        NULL
8318  *
8319  * Programmer:  Mark C. Miller
8320  *              Wednesday, September 7, 2005
8321  *
8322  * Modifications:
8323  *
8324  *   Mark C. Miller, Thu Sep  7 10:50:55 PDT 2006
8325  *   Added use of db_hdf5_resolvename for retrieval of subobjects
8326  *
8327  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
8328  *   Added logic to control behavior of slash character swapping for
8329  *   windows/linux and skipping of first semicolon in calls to
8330  *   db_StringListToStringArray.
8331  *-------------------------------------------------------------------------
8332  */
8333 SILO_CALLBACK DBcsgmesh *
db_hdf5_GetCsgmesh(DBfile * _dbfile,char const * name)8334 db_hdf5_GetCsgmesh(DBfile *_dbfile, char const *name)
8335 {
8336     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8337     static char         *me = "db_hdf5_GetCsgmesh";
8338     hid_t               o=-1, attr=-1;
8339     int                 _objtype, i;
8340     DBcsgmesh_mt        m;
8341     DBcsgmesh           *csgm=NULL;
8342 
8343     PROTECT {
8344         /* Open object and make sure it's a csgmesh */
8345         if ((o=H5Topen(dbfile->cwg, name))<0) {
8346             db_perror((char*)name, E_NOTFOUND, me);
8347             UNWIND();
8348         }
8349         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
8350             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
8351             H5Aclose(attr)<0) {
8352             db_perror((char*)name, E_CALLFAIL, me);
8353             UNWIND();
8354         }
8355         if (DB_CSGMESH!=(DBObjectType)_objtype) {
8356             db_perror((char*)name, E_CALLFAIL, me);
8357             UNWIND();
8358         }
8359 
8360         /* Read header into memory */
8361         memset(&m, 0, sizeof m);
8362         if ((attr=H5Aopen_name(o, "silo"))<0 ||
8363             H5Aread(attr, DBcsgmesh_mt5, &m)<0 ||
8364             H5Aclose(attr)<0) {
8365             db_perror((char*)name, E_CALLFAIL, me);
8366             UNWIND();
8367         }
8368 
8369         /* Create a ucdmesh object and initialize meta data */
8370         if (NULL==(csgm=DBAllocCsgmesh())) return NULL;
8371         csgm->name = BASEDUP(name);
8372         csgm->cycle = m.cycle;
8373         if ((csgm->datatype = db_hdf5_GetVarType(_dbfile, m.coeffs)) < 0)
8374             csgm->datatype = DB_FLOAT;
8375         if (force_single_g) csgm->datatype = DB_FLOAT;
8376         csgm->time = m.time;
8377         csgm->dtime = m.dtime;
8378         csgm->ndims = m.ndims;
8379         csgm->nbounds = m.nbounds;
8380         csgm->lcoeffs = m.lcoeffs;
8381         csgm->origin = m.origin;
8382         csgm->group_no = m.group_no;
8383         csgm->guihide = m.guihide;
8384         for (i=0; i<m.ndims; i++) {
8385             csgm->units[i] = OPTDUP(m.units[i]);
8386             csgm->labels[i] = OPTDUP(m.labels[i]);
8387             csgm->min_extents[i] = m.min_extents[i];
8388             csgm->max_extents[i] = m.max_extents[i];
8389         }
8390         csgm->mrgtree_name = OPTDUP(m.mrgtree_name);
8391         csgm->tv_connectivity = m.tv_connectivity;
8392         csgm->disjoint_mode = m.disjoint_mode;
8393 
8394         /* Read the raw data */
8395         if ((SILO_Globals.dataReadMask & DBCSGMBoundaryInfo) && (m.nbounds > 0))
8396         {
8397             csgm->typeflags = (int *)db_hdf5_comprd(dbfile, m.typeflags, 1);
8398             csgm->bndids = (int *)db_hdf5_comprd(dbfile, m.bndids, 1);
8399         }
8400 
8401         if ((SILO_Globals.dataReadMask & DBCSGMBoundaryNames) && (m.nbounds > 0))
8402         {
8403             char *tmpbndnames = (char *)db_hdf5_comprd(dbfile, m.bndnames, 1);
8404             if (tmpbndnames)
8405                 csgm->bndnames = DBStringListToStringArray(tmpbndnames, &m.nbounds, !skipFirstSemicolon);
8406             FREE(tmpbndnames);
8407         }
8408 
8409         if ((SILO_Globals.dataReadMask & DBCSGMBoundaryInfo) && (m.lcoeffs > 0))
8410             csgm->coeffs = db_hdf5_comprd(dbfile, m.coeffs, 0);
8411 
8412         if ((m.nbounds>0 && m.zonel_name[0] && (SILO_Globals.dataReadMask & DBCSGMZonelist)))
8413             csgm->zones = db_hdf5_GetCSGZonelist(_dbfile,
8414                               db_hdf5_resolvename(_dbfile, name, m.zonel_name));
8415 
8416         /* alt nodenum vars */
8417         {
8418             int nnames = -1;
8419             char *tmpannums = (char *)db_hdf5_comprd(dbfile, m.alt_nodenum_vars, 1);
8420             if (tmpannums)
8421                 csgm->alt_nodenum_vars = DBStringListToStringArray(tmpannums, &nnames, !skipFirstSemicolon);
8422             FREE(tmpannums);
8423         }
8424 
8425         H5Tclose(o);
8426     } CLEANUP {
8427         H5E_BEGIN_TRY {
8428             H5Aclose(attr);
8429             H5Tclose(o);
8430         } H5E_END_TRY;
8431     } END_PROTECT;
8432 
8433     return csgm;
8434 }
8435 
8436 /*-------------------------------------------------------------------------
8437  * Function:    db_hdf5_PutCsgvar
8438  *
8439  * Purpose:     Writes CSG variables to the file.
8440  *
8441  * Return:      Success:        0
8442  *
8443  *              Failure:        -1
8444  *
8445  * Programmer:  Mark C. Miller
8446  *              Wednesday, September 7, 2005
8447  *
8448  * Modifications:
8449  *
8450  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
8451  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
8452  *
8453  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
8454  *   Added support for conserved/extensive options.
8455  *-------------------------------------------------------------------------
8456  */
8457 /*ARGSUSED*/
8458 SILO_CALLBACK int
db_hdf5_PutCsgvar(DBfile * _dbfile,char const * vname,char const * meshname,int nvars,char const * const * varnames,void const * const * vars,int nvals,int datatype,int centering,DBoptlist const * optlist)8459 db_hdf5_PutCsgvar(DBfile *_dbfile, char const *vname, char const *meshname,
8460                   int nvars, char const * const *varnames, void const * const *vars,
8461                   int nvals, int datatype, int centering, DBoptlist const *optlist)
8462 
8463 {
8464     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8465     static char         *me = "db_hdf5_PutCsgvar";
8466     char                *s = 0;
8467     DBcsgvar_mt         m;
8468     int                 i;
8469 
8470     memset(&m, 0, sizeof m);
8471 
8472     PROTECT {
8473         db_ResetGlobalData_Csgmesh();
8474         strcpy(_csgm._meshname, meshname);
8475         db_ProcessOptlist(DB_CSGMESH, optlist);
8476 
8477         /* Write variable arrays: vars[] */
8478         if (nvars>MAX_VARS) {
8479             db_perror("too many variables", E_BADARGS, me);
8480             UNWIND();
8481         }
8482         for (i=0; i<nvars && nvals; i++) {
8483             db_hdf5_compwr(dbfile, datatype, 1, &nvals, (void*)vars[i],
8484                 m.vals[i]/*out*/, friendly_name(varnames[i], "_data", 0));
8485         }
8486 
8487         /* output mrgtree info if we have it */
8488         if (_csgm._region_pnames != NULL) {
8489             int len;
8490             DBStringArrayToStringList((char const * const *)_csgm._region_pnames, -1, &s, &len);
8491             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.region_pnames/*out*/,
8492                 friendly_name(vname, "_region_pnames", 0));
8493             FREE(s);
8494         }
8495 
8496         /* Build header in memory */
8497         m.nvals = nvars;
8498         m.nels = nvals;
8499         m.centering = centering;
8500         m.cycle = _csgm._cycle;
8501         m.guihide = _csgm._guihide;
8502         if (_csgm._time_set)
8503             m.time = _csgm._time;
8504         if (_csgm._dtime_set)
8505             m.dtime = _um._dtime;
8506         m.use_specmf = _um._use_specmf;
8507         m.datatype = datatype;
8508         m.conserved = _csgm._conserved;
8509         m.extensive = _csgm._extensive;
8510         strcpy(m.meshname, OPT(_csgm._meshname));
8511         strcpy(m.label, OPT(_csgm._label));
8512         strcpy(m.units, OPT(_csgm._unit));
8513         db_SetMissingValueForPut(m.missing_value, _csgm._missing_value);
8514 
8515         /* Write header to file */
8516         STRUCT(DBcsgvar) {
8517             MEMBER_R(str(m.vals[_j]), vals, nvars);
8518             MEMBER_S(str(m.meshname), meshname);
8519             MEMBER_S(int, cycle);
8520             MEMBER_S(str(m.label), label);
8521             MEMBER_S(str(m.units), units);
8522             if (m.nvals)        MEMBER_S(int, nvals);
8523             if (m.nels)         MEMBER_S(int, nels);
8524             if (m.centering)    MEMBER_S(int, centering);
8525             if (m.use_specmf)   MEMBER_S(int, use_specmf);
8526             if (m.datatype)     MEMBER_S(int, datatype);
8527             if (m.guihide)      MEMBER_S(int, guihide);
8528             if (_csgm._time_set)  MEMBER_S(float, time);
8529             if (_csgm._dtime_set) MEMBER_S(double, dtime);
8530             if (m.conserved)    MEMBER_S(int, conserved);
8531             if (m.extensive)    MEMBER_S(int, extensive);
8532             if (m.missing_value) MEMBER_S(double, missing_value);
8533             MEMBER_S(str(m.region_pnames), region_pnames);
8534         } OUTPUT(dbfile, DB_CSGVAR, vname, &m);
8535 
8536     } CLEANUP {
8537         /*void*/
8538     } END_PROTECT;
8539 
8540     return 0;
8541 }
8542 
8543 /*-------------------------------------------------------------------------
8544  * Function:    db_hdf5_GetCsgvar
8545  *
8546  * Purpose:     Reads a CSG variable object from the file.
8547  *
8548  * Return:      Success:        Ptr to new CSG variable object
8549  *
8550  *              Failure:        NULL
8551  *
8552  * Programmer:  Mark C. Miller
8553  *              Wednesday, September 7, 2005
8554  *
8555  * Modifications:
8556  *
8557  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
8558  *   Added support for conserved/extensive options.
8559  *
8560  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
8561  *   Added logic to control behavior of slash character swapping for
8562  *   windows/linux and skipping of first semicolon in calls to
8563  *   db_StringListToStringArray.
8564  *-------------------------------------------------------------------------
8565  */
8566 SILO_CALLBACK DBcsgvar *
db_hdf5_GetCsgvar(DBfile * _dbfile,char const * name)8567 db_hdf5_GetCsgvar(DBfile *_dbfile, char const *name)
8568 {
8569     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8570     static char         *me = "db_hdf5_GetCsgvar";
8571     char                *s = 0;
8572     hid_t               o=-1, attr=-1;
8573     int                 _objtype, i;
8574     DBcsgvar_mt         m;
8575     DBcsgvar           *csgv=NULL;
8576 
8577     PROTECT {
8578         /* Open object and make sure it's a ucdvar */
8579         if ((o=H5Topen(dbfile->cwg, name))<0) {
8580             db_perror((char*)name, E_NOTFOUND, me);
8581             UNWIND();
8582         }
8583         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
8584             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
8585             H5Aclose(attr)<0) {
8586             db_perror((char*)name, E_CALLFAIL, me);
8587             UNWIND();
8588         }
8589         if (DB_CSGVAR!=(DBObjectType)_objtype) {
8590             db_perror((char*)name, E_CALLFAIL, me);
8591             UNWIND();
8592         }
8593 
8594         /* Read ucdvar data into memory */
8595         memset(&m, 0, sizeof m);
8596         if ((attr=H5Aopen_name(o, "silo"))<0 ||
8597             H5Aread(attr, DBcsgvar_mt5, &m)<0 ||
8598             H5Aclose(attr)<0) {
8599             db_perror((char*)name, E_CALLFAIL, me);
8600             UNWIND();
8601         }
8602 
8603         /* Create a ucdvar object and initialize meta data */
8604         if (NULL==(csgv=DBAllocCsgvar())) return NULL;
8605         csgv->name = BASEDUP(name);
8606         csgv->meshname = OPTDUP(m.meshname);
8607         csgv->cycle = m.cycle;
8608         csgv->units = OPTDUP(m.units);
8609         csgv->label = OPTDUP(m.label);
8610         csgv->time = m.time;
8611         csgv->dtime = m.dtime;
8612         if ((csgv->datatype = db_hdf5_GetVarType(_dbfile, m.vals[0])) < 0)
8613             csgv->datatype = silo2silo_type(m.datatype);
8614         if (force_single_g) csgv->datatype = DB_FLOAT;
8615         csgv->nels = m.nels;
8616         csgv->nvals = m.nvals;
8617         csgv->centering = m.centering;
8618         csgv->use_specmf = m.use_specmf;
8619         csgv->ascii_labels = m.ascii_labels;
8620         csgv->guihide = m.guihide;
8621         csgv->conserved = m.conserved;
8622         csgv->extensive = m.extensive;
8623         db_SetMissingValueForGet(csgv->missing_value, m.missing_value);
8624 
8625         /* Read the raw data */
8626         if (m.nvals>MAX_VARS) {
8627             db_perror((char*)name, E_CALLFAIL, me);
8628             UNWIND();
8629         }
8630 
8631         if (SILO_Globals.dataReadMask & DBCSGVData && m.nvals)
8632         {
8633             csgv->vals = (void **)calloc(m.nvals, sizeof(void*));
8634             for (i=0; i<m.nvals; i++) {
8635                 csgv->vals[i] = db_hdf5_comprd(dbfile, m.vals[i], 0);
8636             }
8637         }
8638 
8639         s = (char *)db_hdf5_comprd(dbfile, m.region_pnames, 1);
8640         if (s) csgv->region_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
8641         FREE(s);
8642 
8643         H5Tclose(o);
8644 
8645     } CLEANUP {
8646         H5E_BEGIN_TRY {
8647             H5Aclose(attr);
8648             H5Tclose(o);
8649         } H5E_END_TRY;
8650         DBFreeCsgvar(csgv);
8651     } END_PROTECT;
8652 
8653     return csgv;
8654 }
8655 
8656 /*-------------------------------------------------------------------------
8657  * Function:    db_hdf5_PutCSGZonelist
8658  *
8659  * Purpose:     Write a DBcsgzonelist object into the file.
8660  *
8661  * Return:      Success:        0
8662  *
8663  *              Failure:        -1
8664  *
8665  * Programmer:  Mark C. Miller
8666  *              Wednesday, September 7, 2005
8667  *
8668  * Modifications:
8669  *
8670  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
8671  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
8672  *-------------------------------------------------------------------------
8673  */
8674 SILO_CALLBACK int
db_hdf5_PutCSGZonelist(DBfile * _dbfile,char const * name,int nregs,int const * typeflags,int const * leftids,int const * rightids,void const * xforms,int lxforms,int datatype,int nzones,int const * zonelist,DBoptlist const * optlist)8675 db_hdf5_PutCSGZonelist(DBfile *_dbfile, char const *name, int nregs,
8676                  int const *typeflags,
8677                  int const *leftids, int const *rightids,
8678                  void const *xforms, int lxforms, int datatype,
8679                  int nzones, int const *zonelist, DBoptlist const *optlist)
8680 
8681 {
8682     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8683     DBcsgzonelist_mt     m;
8684     static char         *me = "db_hdf5_PutCSGZonelist";
8685 
8686     memset(&m, 0, sizeof m);
8687     PROTECT {
8688         /* Set global options */
8689         memset(&_csgzl, 0, sizeof _csgzl);
8690         if (db_ProcessOptlist(DB_CSGZONELIST, optlist)<0) {
8691             db_perror("bad options", E_CALLFAIL, me);
8692             UNWIND();
8693         }
8694 
8695         /* Write variable arrays */
8696         db_hdf5_compwr(dbfile, DB_INT, 1, &nregs, (void*)typeflags,
8697             m.typeflags/*out*/, friendly_name(name, "_typeflags",0));
8698         db_hdf5_compwr(dbfile, DB_INT, 1, &nregs, (void*)leftids,
8699             m.leftids/*out*/, friendly_name(name, "_leftids",0));
8700         db_hdf5_compwr(dbfile, DB_INT, 1, &nregs, (void*)rightids,
8701             m.rightids/*out*/, friendly_name(name, "_rightids",0));
8702         db_hdf5_compwr(dbfile, DB_INT, 1, &nzones, (void*)zonelist,
8703             m.zonelist/*out*/, friendly_name(name, "_zonelist",0));
8704         if (xforms && lxforms > 0) {
8705             db_hdf5_compwr(dbfile, datatype, 1, &lxforms, (void*)xforms,
8706                 m.xform/*out*/, friendly_name(name, "_xforms",0));
8707         }
8708 
8709         if (_csgzl._regnames) {
8710             int len; char *tmp;
8711             DBStringArrayToStringList((char const * const *)_csgzl._regnames, nregs, &tmp, &len);
8712             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
8713                 m.regnames/*out*/, friendly_name(name, "_regnames",0));
8714             FREE(tmp);
8715         }
8716 
8717         if (_csgzl._zonenames) {
8718             int len; char *tmp;
8719             DBStringArrayToStringList((char const * const *)_csgzl._zonenames, nzones, &tmp, &len);
8720             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
8721                 m.zonenames/*out*/, friendly_name(name, "_zonenames",0));
8722             FREE(tmp);
8723         }
8724 
8725         if (_csgzl._alt_zonenum_vars) {
8726             int len, nvars=-1; char *tmp;
8727             DBStringArrayToStringList((char const * const *)_csgzl._alt_zonenum_vars, nvars, &tmp, &len);
8728             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
8729                 m.alt_zonenum_vars/*out*/, friendly_name(name, "_alt_zonenum_vars",0));
8730             FREE(tmp);
8731         }
8732 
8733         /* Build header in memory */
8734         m.nregs = nregs;
8735         m.lxform = lxforms;
8736         m.nzones = nzones;
8737         if (nregs == 0 && nzones == 0) m.origin = 1;
8738 
8739         /* Write header to file */
8740         STRUCT(DBcsgzonelist) {
8741             if (m.nregs)        MEMBER_S(int, nregs);
8742             if (m.lxform)       MEMBER_S(int, lxform);
8743             if (m.nzones)       MEMBER_S(int, nzones);
8744             if (m.origin)       MEMBER_S(int, origin);
8745             MEMBER_S(str(m.typeflags), typeflags);
8746             MEMBER_S(str(m.leftids), leftids);
8747             MEMBER_S(str(m.rightids), rightids);
8748             MEMBER_S(str(m.zonelist), zonelist);
8749             MEMBER_S(str(m.xform), xform);
8750             MEMBER_S(str(m.regnames), regnames);
8751             MEMBER_S(str(m.zonenames), zonenames);
8752             MEMBER_S(str(m.alt_zonenum_vars), alt_zonenum_vars);
8753         } OUTPUT(dbfile, DB_CSGZONELIST, name, &m);
8754 
8755     } CLEANUP {
8756         /*void*/
8757     } END_PROTECT;
8758     return 0;
8759 }
8760 
8761 /*-------------------------------------------------------------------------
8762  * Function:    db_hdf5_GetCSGZonelist
8763  *
8764  * Purpose:     Reads a CSG zonelist object from the file
8765  *
8766  * Return:      Success:        Ptr to new CSG zonelist
8767  *
8768  *              Failure:        NULL
8769  *
8770  * Programmer:  Mark C. Miller
8771  *              Wednesday, September 7, 2005
8772  *
8773  * Modifications:
8774  *
8775  *   Mark C. Miller, Thu Mar 23 15:31:50 PST 2006
8776  *   Fixed case where we were forcing single on an integer array for the
8777  *   zonelist.
8778  *
8779  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
8780  *   Added logic to control behavior of slash character swapping for
8781  *   windows/linux and skipping of first semicolon in calls to
8782  *   db_StringListToStringArray.
8783  *-------------------------------------------------------------------------
8784  */
8785 SILO_CALLBACK DBcsgzonelist *
db_hdf5_GetCSGZonelist(DBfile * _dbfile,char const * name)8786 db_hdf5_GetCSGZonelist(DBfile *_dbfile, char const *name)
8787 {
8788     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
8789     static char         *me = "db_hdf5_GetCSGZonelist";
8790     hid_t               o=-1, attr=-1;
8791     int                 _objtype;
8792     DBcsgzonelist_mt     m;
8793     DBcsgzonelist       *zl=NULL;
8794 
8795     PROTECT {
8796         /* Open object and make sure it's a zonelist */
8797         if ((o=H5Topen(dbfile->cwg, name))<0) {
8798             db_perror((char*)name, E_NOTFOUND, me);
8799             UNWIND();
8800         }
8801         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
8802             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
8803             H5Aclose(attr)<0) {
8804             db_perror((char*)name, E_CALLFAIL, me);
8805             UNWIND();
8806         }
8807         if (DB_CSGZONELIST!=(DBObjectType)_objtype) {
8808             db_perror((char*)name, E_CALLFAIL, me);
8809             UNWIND();
8810         }
8811 
8812         /* Read zonelist data into memory */
8813         memset(&m, 0, sizeof m);
8814         if ((attr=H5Aopen_name(o, "silo"))<0 ||
8815             H5Aread(attr, DBcsgzonelist_mt5, &m)<0 ||
8816             H5Aclose(attr)<0) {
8817             db_perror((char*)name, E_CALLFAIL, me);
8818             UNWIND();
8819         }
8820 
8821         /* Create a zonelist object and initialize meta data */
8822         if (NULL==(zl=DBAllocCSGZonelist())) return NULL;
8823         zl->nregs = m.nregs;
8824         zl->nzones = m.nzones;
8825         zl->lxform = m.lxform;
8826         if ((zl->datatype = db_hdf5_GetVarType(_dbfile, m.xform)) < 0)
8827             zl->datatype = DB_FLOAT;
8828         if (force_single_g) zl->datatype = DB_FLOAT;
8829 
8830         /* Read the raw data */
8831         if (SILO_Globals.dataReadMask & DBZonelistInfo)
8832         {
8833             zl->typeflags = (int *)db_hdf5_comprd(dbfile, m.typeflags, 1);
8834             zl->leftids = (int *)db_hdf5_comprd(dbfile, m.leftids, 1);
8835             zl->rightids = (int *)db_hdf5_comprd(dbfile, m.rightids, 1);
8836             zl->xform = db_hdf5_comprd(dbfile, m.xform, 0);
8837             zl->zonelist = (int *)db_hdf5_comprd(dbfile, m.zonelist, 1);
8838         }
8839 
8840         if (SILO_Globals.dataReadMask & DBCSGZonelistRegNames)
8841         {
8842             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.regnames, 1);
8843             if (tmpnames)
8844                 zl->regnames = DBStringListToStringArray(tmpnames, &m.nregs, !skipFirstSemicolon);
8845             FREE(tmpnames);
8846         }
8847 
8848         if (SILO_Globals.dataReadMask & DBCSGZonelistZoneNames)
8849         {
8850             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.zonenames, 1);
8851             if (tmpnames)
8852                 zl->zonenames = DBStringListToStringArray(tmpnames, &m.nzones, !skipFirstSemicolon);
8853             FREE(tmpnames);
8854         }
8855 
8856         /* alternate zone number variables */
8857         {
8858             int nvars = -1;
8859             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_zonenum_vars, 1);
8860             if (tmpnames)
8861                 zl->alt_zonenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
8862             FREE(tmpnames);
8863         }
8864 
8865         H5Tclose(o);
8866     } CLEANUP {
8867         H5E_BEGIN_TRY {
8868             H5Aclose(attr);
8869             H5Tclose(o);
8870         } H5E_END_TRY;
8871         DBFreeCSGZonelist(zl);
8872     } END_PROTECT;
8873 
8874     return zl;
8875 }
8876 
8877 /*-------------------------------------------------------------------------
8878  * Function:    db_hdf5_PutDefvars
8879  *
8880  * Purpose:     Put a defvars object into the file.
8881  *
8882  * Return:      Success:        0
8883  *
8884  *              Failure:        -1, db_errno set
8885  *
8886  * Programmer:  Mark C. Miller
8887  *              Tuesday, September 6, 2005
8888  *
8889  * Modifications:
8890  *
8891  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
8892  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
8893  *-------------------------------------------------------------------------
8894  */
8895 SILO_CALLBACK int
db_hdf5_PutDefvars(DBfile * _dbfile,char const * name,int ndefs,char const * const * names,int const * types,char const * const * defns,DBoptlist const * const * opts)8896 db_hdf5_PutDefvars(
8897     DBfile *_dbfile,
8898     char const *name,
8899     int ndefs,
8900     char const * const *names,
8901     int const *types,
8902     char const * const *defns,
8903     DBoptlist const * const *opts
8904 )
8905 {
8906     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
8907     static char *me = "db_hdf5_PutDefvars";
8908     DBdefvars_mt  m;
8909     int len;
8910     char *s;
8911     int *guihide = NULL;
8912 
8913    /*
8914     * Optlists are a little funky for this object because we were
8915     * concerned about possibly handling things like units, etc. So,
8916     * we really have an array of optlists that needs to get serialized.
8917     */
8918    if (opts)
8919    {
8920        int i;
8921        for (i = 0; i < ndefs; i++)
8922        {
8923            memset(&_dv, 0, sizeof(_dv)); /* reset global dv data */
8924            db_ProcessOptlist (DB_DEFVARS, opts[i]);
8925            if (_dv._guihide)
8926            {
8927                if (guihide == NULL)
8928                    guihide = (int *) calloc(ndefs, sizeof(int));
8929                guihide[i] = _dv._guihide;
8930            }
8931        }
8932    }
8933 
8934     memset(&m, 0, sizeof m);
8935     PROTECT {
8936 
8937         DBStringArrayToStringList((char const * const *)names, ndefs, &s, &len);
8938         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.names/*out*/,
8939             friendly_name(name, "_names",0));
8940         FREE(s);
8941 
8942         db_hdf5_compwr(dbfile, DB_INT, 1, &ndefs, (void*)types, m.types/*out*/,
8943             friendly_name(name, "_types",0));
8944 
8945         DBStringArrayToStringList((char const * const *)defns, ndefs, &s, &len);
8946         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.defns/*out*/,
8947             friendly_name(name, "_defns",0));
8948         FREE(s);
8949 
8950         if (guihide)
8951         {
8952             db_hdf5_compwr(dbfile, DB_INT, 1, &ndefs, (void*)guihide, m.guihides/*out*/,
8953                 friendly_name(name, "_guihids",0));
8954             free(guihide);
8955         }
8956 
8957         /* Build the curve header in memory */
8958         m.ndefs = ndefs;
8959 
8960         /* Write curve header to file */
8961         STRUCT(DBdefvars) {
8962             if (m.ndefs) MEMBER_S(int, ndefs);
8963             MEMBER_S(str(m.names), names);
8964             MEMBER_S(str(m.types), types);
8965             MEMBER_S(str(m.defns), defns);
8966             MEMBER_S(str(m.guihides), guihides);
8967         } OUTPUT(dbfile, DB_DEFVARS, name, &m);
8968 
8969     } CLEANUP {
8970         if (guihide) free(guihide);
8971     } END_PROTECT;
8972     return 0;
8973 }
8974 
8975 /*-------------------------------------------------------------------------
8976  * Function:    db_hdf5_GetDefvars
8977  *
8978  * Purpose:     Read a defvars object from a data file.
8979  *
8980  * Return:      Success:        Pointer to new defvars object
8981  *
8982  *              Failure:        NULL
8983  *
8984  * Programmer:  Robb Matzke
8985  *              Thursday, March 25, 1999
8986  *
8987  * Modifications:
8988  *
8989  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
8990  *   Made it set datatype correctly. Added support for dataReadMask
8991  *
8992  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
8993  *   Added logic to control behavior of slash character swapping for
8994  *   windows/linux and skipping of first semicolon in calls to
8995  *   db_StringListToStringArray.
8996  *-------------------------------------------------------------------------
8997  */
8998 SILO_CALLBACK DBdefvars*
db_hdf5_GetDefvars(DBfile * _dbfile,char const * name)8999 db_hdf5_GetDefvars(DBfile *_dbfile, char const *name)
9000 {
9001     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9002     static char         *me = "db_hdf5_GetDefvars";
9003     DBdefvars           *defv = NULL;
9004     DBdefvars_mt         m;
9005     hid_t               o=-1, attr=-1;
9006     int                 _objtype;
9007     char               *s;
9008 
9009     PROTECT {
9010         /* Open object and make sure it's a curve */
9011         if ((o=H5Topen(dbfile->cwg, name))<0) {
9012             db_perror((char*)name, E_NOTFOUND, me);
9013             UNWIND();
9014         }
9015         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
9016             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
9017             H5Aclose(attr)<0) {
9018             db_perror((char*)name, E_CALLFAIL, me);
9019             UNWIND();
9020         }
9021         if (DB_DEFVARS!=(DBObjectType)_objtype) {
9022             db_perror((char*)name, E_CALLFAIL, me);
9023             UNWIND();
9024         }
9025 
9026         /* Read the data into memory */
9027         memset(&m, 0, sizeof m);
9028         if ((attr=H5Aopen_name(o, "silo"))<0 ||
9029             H5Aread(attr, DBdefvars_mt5, &m)<0 ||
9030             H5Aclose(attr)<0) {
9031             db_perror((char*)name, E_CALLFAIL, me);
9032             UNWIND();
9033         }
9034 
9035         /* Create a defvars object and initialize meta data */
9036         if (NULL==(defv=DBAllocDefvars(0))) return NULL;
9037         defv->ndefs = m.ndefs;
9038 
9039         s = (char *)db_hdf5_comprd(dbfile, m.names, 1);
9040         if (s) defv->names = DBStringListToStringArray(s, &(defv->ndefs), !skipFirstSemicolon);
9041         FREE(s);
9042 
9043         defv->types = (int *)db_hdf5_comprd(dbfile, m.types, 1);
9044 
9045         s = (char *)db_hdf5_comprd(dbfile, m.defns, 1);
9046         if (s) defv->defns = DBStringListToStringArray(s, &(defv->ndefs), !skipFirstSemicolon);
9047         FREE(s);
9048 
9049         defv->guihides = (int *)db_hdf5_comprd(dbfile, m.guihides, 1);
9050 
9051         H5Tclose(o);
9052 
9053     } CLEANUP {
9054         H5E_BEGIN_TRY {
9055             H5Aclose(attr);
9056             H5Tclose(o);
9057         } H5E_END_TRY;
9058         DBFreeDefvars(defv);
9059     } END_PROTECT;
9060 
9061     return defv;
9062 }
9063 
9064 /*-------------------------------------------------------------------------
9065  * Function:    PrepareForQuadmeshCompression
9066  *
9067  * Purpose:     Does some small work to prepare for possible mesh
9068  *              compression
9069  *
9070  * Return:      Success:        ALLOW_MESH_COMPRESSION
9071  *
9072  *              Failure:        0
9073  *
9074  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
9075  *-------------------------------------------------------------------------
9076  */
PrepareForQuadmeshCompression()9077 static int PrepareForQuadmeshCompression()
9078 {
9079     if (SILO_Globals.compressionParams == 0) return 0;
9080 
9081 #ifdef HAVE_HZIP
9082     db_hdf5_hzip_clear_params();
9083     db_hdf5_hzip_params.isquad = 1;
9084     return ALLOW_MESH_COMPRESSION;
9085 #endif
9086     return 0;
9087 }
9088 
9089 /*-------------------------------------------------------------------------
9090  * Function:    db_hdf5_PutQuadmesh
9091  *
9092  * Purpose:     Writes a Quadmesh to the silo file.
9093  *
9094  * Return:      Success:        0
9095  *
9096  *              Failure:        -1
9097  *
9098  * Programmer:  Robb Matzke
9099  *              Monday, March 29, 1999
9100  *
9101  * Modifications:
9102  *              Robb Matzke, 1999-07-13
9103  *              Added `group_no' and `baseindex[]' properties to duplicate
9104  *              changes made to the PDB driver.
9105  *
9106  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
9107  *              Made it set the correct mesh type
9108  *
9109  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
9110  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
9111  *
9112  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
9113  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
9114  *
9115  *   Mark C. Miller, Thu Jul 17 15:07:49 PDT 2008
9116  *   Added call to prepare for mesh compression. Changed call for
9117  *   non-collinear coordinate case to use db_hdf5_compwrz to support
9118  *   possible compression.
9119  *
9120  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
9121  *   Refactored logic to handle time, dtime and cycle to a new method,
9122  *   db_hdf5_handle_ctdt().
9123  *-------------------------------------------------------------------------
9124  */
9125 /*ARGSUSED*/
9126 SILO_CALLBACK int
db_hdf5_PutQuadmesh(DBfile * _dbfile,char const * name,char const * const * coordnames,DBVCP2_t _coords,int const * dims,int ndims,int datatype,int coordtype,DBoptlist const * optlist)9127 db_hdf5_PutQuadmesh(DBfile *_dbfile, char const *name, char const * const *coordnames,
9128                     DBVCP2_t _coords, int const *dims, int ndims, int datatype,
9129                     int coordtype, DBoptlist const *optlist)
9130 {
9131     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9132     static char         *me = "db_hdf5_PutQuadmesh";
9133     int                 i, is_empty = 1;
9134     DBquadmesh_mt       m;
9135     int                 compressionFlags;
9136     void const * const *coords = (void const * const *) _coords;
9137 
9138     FREE(_qm._meshname);
9139     memset(&_qm, 0, sizeof _qm);
9140     memset(&m, 0, sizeof m);
9141 
9142     for (i = 0; i < ndims; i++)
9143     {
9144         if (dims[i] > 0)
9145         {
9146             is_empty = 0;
9147             break;
9148         }
9149     }
9150 
9151     PROTECT {
9152         /* Check datatype */
9153         if (DB_FLOAT!=datatype && DB_DOUBLE!=datatype) {
9154             db_perror("invalid floating-point datatype", E_BADARGS, me);
9155             UNWIND();
9156         }
9157 
9158         /* Set global options */
9159         _qm._coord_sys = DB_OTHER;
9160         _qm._facetype = DB_RECTILINEAR;
9161         _qm._ndims = ndims;
9162         _qm._nspace = ndims;
9163         _qm._planar = DB_AREA;
9164         _qm._use_specmf = DB_OFF;
9165         _qm._group_no = -1;
9166         if (db_ProcessOptlist(DB_QUADMESH, optlist)<0) {
9167             db_perror("bad options", E_CALLFAIL, me);
9168             UNWIND();
9169         }
9170 
9171         /* hack to maintain backward compatibility with pdb driver */
9172         db_hdf5_handle_ctdt(dbfile, _qm._time_set, _qm._time,
9173             _qm._dtime_set, _qm._dtime, _qm._cycle);
9174 
9175         /*
9176          * Number of zones and nodes. We have to do this because
9177          * _DBQMCalcExtents uses this global information.
9178          */
9179         for (_qm._nzones=_qm._nnodes=(is_empty?0:1), i=0; i<ndims; i++) {
9180             _qm._nzones *= (dims[i]-1);
9181             _qm._nnodes *= dims[i];
9182             _qm._dims[i] = dims[i];
9183             _qm._zones[i] = dims[i]-1;
9184             _qm._minindex[i] = _qm._lo_offset[i];
9185             _qm._maxindex_n[i] = dims[i] - _qm._hi_offset[i] - 1;
9186             _qm._maxindex_z[i] = _qm._maxindex_n[i] - 1;
9187         }
9188 
9189         /* Calculate extents, stored as DB_DOUBLE */
9190         if (DB_DOUBLE==datatype) {
9191             int ii;
9192             for (ii = 0; ii < 3; ii++)
9193                 m.min_extents[ii] = m.max_extents[ii] = 0;
9194             _DBQMCalcExtents(coords, datatype, _qm._minindex, _qm._maxindex_n,
9195                              dims, ndims, coordtype,
9196                              &(m.min_extents)/*out*/,
9197                              &(m.max_extents)/*out*/);
9198         } else {
9199             float       min_extents[3] = {0,0,0};
9200             float       max_extents[3] = {0,0,0};
9201             _DBQMCalcExtents(coords, datatype, _qm._minindex, _qm._maxindex_n,
9202                              dims, ndims, coordtype,
9203                              min_extents/*out*/, max_extents/*out*/);
9204             for (i=0; i<ndims; i++) {
9205                 m.min_extents[i] = min_extents[i];
9206                 m.max_extents[i] = max_extents[i];
9207             }
9208         }
9209         for (i=0; i<ndims; i++) {
9210             m.min_index[i] = _qm._minindex[i];
9211             m.max_index[i] = _qm._maxindex_n[i];
9212         }
9213 
9214         compressionFlags = PrepareForQuadmeshCompression();
9215 
9216         /* Write coordinate arrays */
9217         if (!is_empty)
9218         {
9219             if (DB_COLLINEAR==coordtype) {
9220                 for (i=0; i<ndims; i++) {
9221                     db_hdf5_compwr(dbfile, datatype, 1, dims+i, coords[i],
9222                         m.coord[i]/*out*/, friendly_name(name, "_coord%d",&i));
9223                 }
9224             } else {
9225                 for (i=0; i<ndims; i++) {
9226                     db_hdf5_compwrz(dbfile, datatype, ndims, dims, coords[i],
9227                         m.coord[i]/*out*/, friendly_name(name, "_coord%d",&i),
9228                         compressionFlags);
9229                 }
9230             }
9231         }
9232 
9233         if (!is_empty && _qm._ghost_node_labels)
9234         {
9235             db_hdf5_compwr(dbfile, DB_CHAR, ndims, dims, _qm._ghost_node_labels,
9236                     m.ghost_node_labels/*out*/, friendly_name(name, "_ghost_node_labels", 0));
9237         }
9238         if (!is_empty && _qm._ghost_zone_labels)
9239         {
9240             int tmpdims[3];
9241             for (i = 0; i < ndims; i++)
9242                 tmpdims[i] = dims[i]-1;
9243 
9244             db_hdf5_compwr(dbfile, DB_CHAR, ndims, tmpdims, _qm._ghost_zone_labels,
9245                     m.ghost_zone_labels/*out*/, friendly_name(name, "_ghost_zone_labels", 0));
9246         }
9247 
9248         if (_qm._alt_nodenum_vars) {
9249             int len, nvars=-1; char *tmp;
9250             DBStringArrayToStringList((char const * const *)_qm._alt_nodenum_vars, nvars, &tmp, &len);
9251             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
9252                 m.alt_nodenum_vars/*out*/, friendly_name(name, "_alt_nodenum_vars",0));
9253             FREE(tmp);
9254         }
9255 
9256         if (_qm._alt_zonenum_vars) {
9257             int len, nvars=-1; char *tmp;
9258             DBStringArrayToStringList((char const * const *)_qm._alt_zonenum_vars, nvars, &tmp, &len);
9259             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
9260                 m.alt_zonenum_vars/*out*/, friendly_name(name, "_alt_zonenum_vars",0));
9261             FREE(tmp);
9262         }
9263 
9264         /* Build quadmesh header in memory */
9265         m.ndims = ndims;
9266         m.coordtype = coordtype;
9267         m.nspace = _qm._nspace;
9268         m.nnodes = _qm._nnodes;
9269         m.facetype = _qm._facetype;
9270         m.major_order = _qm._majororder;
9271         m.cycle = _qm._cycle;
9272         m.coord_sys = _qm._coord_sys;
9273         m.planar = _qm._planar;
9274         m.origin = _qm._origin;
9275         m.group_no = _qm._group_no;
9276         m.guihide = _qm._guihide;
9277         for (i=0; i<ndims; i++) {
9278             m.dims[i] = dims[i];
9279             m.baseindex[i] = _qm._baseindex[i];
9280             strcpy(m.label[i], OPT(_qm._labels[i]));
9281             strcpy(m.units[i], OPT(_qm._units[i]));
9282         }
9283         m.time = _qm._time_set ? _qm._time : 0;
9284         m.dtime = _qm._dtime_set ? _qm._dtime : 0;
9285         strcpy(m.mrgtree_name, OPT(_qm._mrgtree_name));
9286 
9287         /* Build quadmesh header in file */
9288         STRUCT(DBquadmesh) {
9289             MEMBER_R(str(m.coord[_j]), coord, ndims);
9290             MEMBER_3(double, min_extents);
9291             MEMBER_3(double, max_extents);
9292             MEMBER_S(int, ndims);
9293             MEMBER_S(int, coordtype);
9294             MEMBER_S(int, nspace);
9295             MEMBER_S(int, nnodes);
9296             MEMBER_S(int, facetype);
9297             if (m.major_order)  MEMBER_S(int, major_order);
9298             if (m.cycle)        MEMBER_S(int, cycle);
9299             if (m.origin)       MEMBER_S(int, origin);
9300             if (m.group_no)     MEMBER_S(int, group_no);
9301             if (m.guihide)      MEMBER_S(int, guihide);
9302             MEMBER_S(int, coord_sys);
9303             MEMBER_S(int, planar);
9304             MEMBER_3(int, dims);
9305             MEMBER_3(int, min_index);
9306             MEMBER_3(int, max_index);
9307             MEMBER_3(int, baseindex);
9308             if (_qm._time_set) MEMBER_S(float, time);
9309             if (_qm._dtime_set) MEMBER_S(double, dtime);
9310             MEMBER_R(str(m.label[_j]), label, ndims);
9311             MEMBER_R(str(m.units[_j]), units, ndims);
9312             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
9313             MEMBER_S(str(m.ghost_node_labels), ghost_node_labels);
9314             MEMBER_S(str(m.ghost_zone_labels), ghost_zone_labels);
9315             MEMBER_S(str(m.alt_nodenum_vars), alt_nodenum_vars);
9316             MEMBER_S(str(m.alt_zonenum_vars), alt_zonenum_vars);
9317         } OUTPUT(dbfile, coordtype == DB_COLLINEAR ? DB_QUADRECT : DB_QUADCURV, name, &m);
9318 
9319     } CLEANUP {
9320         /*void*/
9321     } END_PROTECT;
9322     return 0;
9323 }
9324 
9325 /*-------------------------------------------------------------------------
9326  * Function:    PrepareForQuadmeshDeompression
9327  *
9328  * Purpose:     Does some small work to prepare for possible mesh
9329  *              decompression
9330  *
9331  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
9332  *-------------------------------------------------------------------------
9333  */
9334 static void
PrepareForQuadmeshDecompression(DBfile_hdf5 * dbfile,char const * meshname,const DBquadmesh * qm)9335 PrepareForQuadmeshDecompression(DBfile_hdf5 *dbfile, char const *meshname,
9336     const DBquadmesh *qm)
9337 {
9338 #ifdef HAVE_HZIP
9339     int i;
9340     db_hdf5_hzip_clear_params();
9341     db_hdf5_hzip_params.dbfile = dbfile;
9342     db_hdf5_hzip_params.isquad = 1;
9343     db_hdf5_hzip_params.meshname = meshname;
9344     db_hdf5_hzip_params.ndims = qm->ndims;
9345     for (i = 0; i < qm->ndims; i++)
9346         db_hdf5_hzip_params.dims[i] = qm->dims[i];
9347 #endif
9348 }
9349 
9350 /*-------------------------------------------------------------------------
9351  * Function:    db_hdf5_GetQuadmesh
9352  *
9353  * Purpose:     Reads a quadmesh object from the file.
9354  *
9355  * Return:      Success:        Ptr to new quadmesh
9356  *
9357  *              Failure:        NULL
9358  *
9359  * Programmer:  Robb Matzke
9360  *              Tuesday, March 30, 1999
9361  *
9362  * Modifications:
9363  *              Robb Matzke, 1999-07-13
9364  *              Added `group_no' and `baseindex[]' properties to duplicate
9365  *              changes made to the PDB driver.
9366  *
9367  *              Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
9368  *              Added support for dataReadMask
9369  *
9370  *              Mark C. Miller, Thu Jul 17 15:09:51 PDT 2008
9371  *              Added call to prepare for mesh decompression.
9372  *-------------------------------------------------------------------------
9373  */
9374 SILO_CALLBACK DBquadmesh *
db_hdf5_GetQuadmesh(DBfile * _dbfile,char const * name)9375 db_hdf5_GetQuadmesh(DBfile *_dbfile, char const *name)
9376 {
9377     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9378     static char         *me = "db_hdf5_GetQuadmesh";
9379     DBquadmesh          *qm = NULL;
9380     DBquadmesh_mt       m;
9381     hid_t               o=-1, attr=-1;
9382     int                 _objtype, stride, i;
9383 
9384     PROTECT {
9385         /* Open object and make sure it's a quadmesh */
9386         if ((o=H5Topen(dbfile->cwg, name))<0) {
9387             db_perror(name, E_NOTFOUND, me);
9388             UNWIND();
9389         }
9390         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
9391             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
9392             H5Aclose(attr)<0) {
9393             db_perror(name, E_CALLFAIL, me);
9394             UNWIND();
9395         }
9396         if ((DB_QUADMESH!=(DBObjectType)_objtype) &&
9397             (DB_QUAD_CURV!=(DBObjectType)_objtype) &&
9398             (DB_QUAD_RECT!=(DBObjectType)_objtype)) {
9399             db_perror(name, E_CALLFAIL, me);
9400             UNWIND();
9401         }
9402 
9403         /* Read quadmesh data into memory */
9404         memset(&m, 0, sizeof m);
9405         if ((attr=H5Aopen_name(o, "silo"))<0 ||
9406             H5Aread(attr, DBquadmesh_mt5, &m)<0 ||
9407             H5Aclose(attr)<0) {
9408             db_perror(name, E_CALLFAIL, me);
9409             UNWIND();
9410         }
9411 
9412         /* Create a quadmesh object and initialize meta data */
9413         if (NULL==(qm=DBAllocQuadmesh())) return NULL;
9414         qm->name = BASEDUP(name);
9415         qm->cycle = m.cycle;
9416         qm->coord_sys = m.coord_sys;
9417         qm->major_order = m.major_order;
9418         qm->coordtype = m.coordtype;
9419         qm->facetype = m.facetype;
9420         qm->planar = m.planar;
9421         if ((qm->datatype = db_hdf5_GetVarType(_dbfile, m.coord[0])) < 0)
9422             qm->datatype = DB_FLOAT;
9423         if (force_single_g) qm->datatype = DB_FLOAT;
9424         qm->time = m.time;
9425         qm->dtime = m.dtime;
9426         qm->ndims = m.ndims;
9427         qm->nspace = m.nspace;
9428         qm->nnodes = m.nnodes;
9429         qm->origin = m.origin;
9430         qm->group_no = m.group_no;
9431         qm->guihide = m.guihide;
9432         qm->mrgtree_name = OPTDUP(m.mrgtree_name);
9433 
9434         for (stride=1, i=0; i<qm->ndims; i++) {
9435             if (qm->datatype == DB_DOUBLE)
9436             {
9437                 ((double*)qm->min_extents)[i] = m.min_extents[i];
9438                 ((double*)qm->max_extents)[i] = m.max_extents[i];
9439             }
9440             else
9441             {
9442                 qm->min_extents[i] = m.min_extents[i];
9443                 qm->max_extents[i] = m.max_extents[i];
9444             }
9445             qm->labels[i] = OPTDUP(m.label[i]);
9446             qm->units[i] = OPTDUP(m.units[i]);
9447             qm->dims[i] = m.dims[i];
9448             qm->min_index[i] = m.min_index[i];
9449             qm->max_index[i] = m.max_index[i];
9450             qm->base_index[i] = m.baseindex[i];
9451             qm->stride[i] = stride;
9452             stride *= qm->dims[i];
9453         }
9454 
9455         PrepareForQuadmeshDecompression(dbfile, name, qm);
9456 
9457         /* Read coordinate arrays */
9458         for (i=0; i<qm->ndims; i++) {
9459             if (SILO_Globals.dataReadMask & DBQMCoords)
9460                 qm->coords[i] = db_hdf5_comprd(dbfile, m.coord[i], 0);
9461         }
9462 
9463         if (SILO_Globals.dataReadMask & DBQMGhostNodeLabels)
9464             qm->ghost_node_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_node_labels, 0);
9465         if (SILO_Globals.dataReadMask & DBQMGhostZoneLabels)
9466             qm->ghost_zone_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_zone_labels, 0);
9467 
9468         /* alternate node number variables */
9469         {
9470             int nvars = -1;
9471             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_nodenum_vars, 1);
9472             if (tmpnames)
9473                 qm->alt_nodenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
9474             FREE(tmpnames);
9475         }
9476 
9477         /* alternate zone number variables */
9478         {
9479             int nvars = -1;
9480             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_zonenum_vars, 1);
9481             if (tmpnames)
9482                 qm->alt_zonenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
9483             FREE(tmpnames);
9484         }
9485 
9486         H5Tclose(o);
9487 
9488     } CLEANUP {
9489         H5E_BEGIN_TRY {
9490             H5Aclose(attr);
9491             H5Tclose(o);
9492         } H5E_END_TRY;
9493         DBFreeQuadmesh(qm);
9494     } END_PROTECT;
9495 
9496     return qm;
9497 }
9498 
9499 /*-------------------------------------------------------------------------
9500  * Function:    PrepareForQuadvarCompression
9501  *
9502  * Purpose:     Does some small work to prepare for possible quadvar
9503  *              compression
9504  *
9505  * Return:      Success:        ALLOW_MESH_COMPRESSION
9506  *
9507  *              Failure:        0
9508  *
9509  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
9510  *-------------------------------------------------------------------------
9511  */
9512 static int
PrepareForQuadvarCompression(int centering,int datatype)9513 PrepareForQuadvarCompression(int centering, int datatype)
9514 {
9515     if (SILO_Globals.compressionParams == 0) return 0;
9516     if (centering == DB_ZONECENT) return 0;
9517 
9518 #ifdef HAVE_HZIP
9519     db_hdf5_hzip_clear_params();
9520     db_hdf5_hzip_params.isquad = 1;
9521     return ALLOW_MESH_COMPRESSION;
9522 #endif
9523     return 0;
9524 
9525 }
9526 
9527 /*-------------------------------------------------------------------------
9528  * Function:    db_hdf5_PutQuadvar
9529  *
9530  * Purpose:     Write a quadvar object to the file. The VARS and MIXVARS
9531  *              arguments should actually be of type `void*[]' because they
9532  *              point to either `float' or `double' depending on the value of
9533  *              the DATATYPE argument.
9534  *
9535  * Return:      Success:        0
9536  *
9537  *              Failure:        -1
9538  *
9539  * Programmer:  Robb Matzke
9540  *              Wednesday, March 31, 1999
9541  *
9542  * Modifications:
9543  *
9544  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
9545  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
9546  *
9547  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
9548  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
9549  *
9550  *   Mark C. Miller, Thu Jul 17 15:10:50 PDT 2008
9551  *   Added call to prepare for compression. Changed call to write variable
9552  *   data to comprdz to support possible comporession.
9553  *
9554  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
9555  *   Added support for conserved/extensive options.
9556  *
9557  *   Mark C. Miller, Wed Nov 11 09:18:12 PST 2009
9558  *   Fixed support for edge/face centered variables.
9559  *
9560  *   Mark C. Miller, Wed Jan  6 13:46:45 PST 2010
9561  *   Fixed setting of align member based on centering.
9562  *
9563  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
9564  *   Refactored logic to handle time, dtime and cycle to a new method,
9565  *   db_hdf5_handle_ctdt().
9566  *-------------------------------------------------------------------------
9567  */
9568 /*ARGSUSED*/
9569 SILO_CALLBACK int
db_hdf5_PutQuadvar(DBfile * _dbfile,char const * name,char const * meshname,int nvars,char const * const * varnames,DBVCP2_t _vars,int const * dims,int ndims,DBVCP2_t _mixvars,int mixlen,int datatype,int centering,DBoptlist const * optlist)9570 db_hdf5_PutQuadvar(DBfile *_dbfile, char const *name, char const *meshname, int nvars,
9571                    char const * const *varnames, DBVCP2_t _vars,
9572                    int const *dims, int ndims, DBVCP2_t _mixvars,
9573                    int mixlen, int datatype, int centering, DBoptlist const *optlist)
9574 {
9575     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9576     static char         *me = "db_hdf5_PutQuadvar";
9577     char                *s = 0;
9578     DBquadvar_mt        m;
9579     int                 i, nels, is_empty = 1;
9580     int                 compressionFlags;
9581     void const * const    *vars = (void const * const *) _vars;
9582     void const * const *mixvars = (void const * const *) _mixvars;
9583 
9584     for (i = 0; i < ndims; i++)
9585     {
9586         if (dims[i] > 0)
9587         {
9588             is_empty = 0;
9589             break;
9590         }
9591     }
9592 
9593     FREE(_qm._meshname);
9594     memset(&_qm, 0, sizeof _qm);
9595     memset(&m, 0, sizeof m);
9596 
9597     PROTECT {
9598         /* Set global options */
9599         _qm._coord_sys = DB_OTHER;
9600         _qm._facetype = DB_RECTILINEAR;
9601         _qm._ndims = _qm._nspace = ndims;
9602         _qm._planar = DB_AREA;
9603         _qm._use_specmf = DB_OFF;
9604         _qm._group_no = -1;
9605         _qm._missing_value = DB_MISSING_VALUE_NOT_SET;
9606         db_ProcessOptlist(DB_QUADMESH, optlist); /*yes, QUADMESH*/
9607         _qm._meshname = STRDUP(meshname);
9608         _qm._nzones = _qm._nnodes = 1; /*initial value only*/
9609         for (nels=(ndims?1:0), i=0; i<ndims; i++) {
9610             nels *= dims[i];
9611             _qm._nzones *= (dims[i]-1);
9612             _qm._nnodes *= dims[i];
9613             _qm._dims[i] = dims[i];
9614             _qm._zones[i] = dims[i]-1;
9615             _qm._minindex[i] = _qm._lo_offset[i];
9616             _qm._maxindex_n[i] = dims[i] - _qm._hi_offset[i] - 1;
9617             _qm._maxindex_z[i] = _qm._maxindex_n[i] - 1;
9618         }
9619 
9620         /* adjust things for edge/face centerings */
9621         if ((ndims > 1 && centering == DB_EDGECENT) ||
9622             (ndims > 2 && centering == DB_FACECENT))
9623            nels *= ndims;
9624 
9625         /* hack to maintain backward compatibility with pdb driver */
9626         db_hdf5_handle_ctdt(dbfile, _qm._time_set, _qm._time,
9627             _qm._dtime_set, _qm._dtime, _qm._cycle);
9628 
9629         compressionFlags = PrepareForQuadvarCompression(centering, datatype);
9630 
9631         /* Write variable arrays: vars[] and mixvars[] */
9632         if (nvars>MAX_VARS) {
9633             db_perror("too many subvariables", E_BADARGS, me);
9634             UNWIND();
9635         }
9636         for (i=0; i<nvars && !is_empty; i++) {
9637             /* Handle adjustment for edge/face centerings */
9638             if ((ndims > 1 && centering == DB_EDGECENT) ||
9639                 (ndims > 2 && centering == DB_FACECENT))
9640             {
9641                 int j, tmpndims = ndims+1;
9642                 int tmpdims[4];
9643                 for (j = ndims; j > 0; j--)
9644                     tmpdims[j] = dims[j-1];
9645                 tmpdims[0] = ndims;
9646                 db_hdf5_compwrz(dbfile, datatype, tmpndims, tmpdims, vars[i],
9647                     m.value[i]/*out*/, friendly_name(varnames[i], "_data", 0),
9648                     compressionFlags);
9649             }
9650             else
9651             {
9652                 db_hdf5_compwrz(dbfile, datatype, ndims, dims, vars[i],
9653                     m.value[i]/*out*/, friendly_name(varnames[i], "_data", 0),
9654                     compressionFlags);
9655             }
9656             if (mixvars && mixvars[i] && mixlen>0) {
9657                 db_hdf5_compwr(dbfile, datatype, 1, &mixlen, mixvars[i],
9658                     m.mixed_value[i]/*out*/, friendly_name(varnames[i], "_mix", 0));
9659             }
9660         }
9661 
9662         /* Build quadvar header in memory */
9663         m.ndims = ndims;
9664         m.nvals = nvars;
9665         m.nels = nels;
9666         m.origin = _qm._origin;
9667         m.mixlen = mixlen;
9668         m.major_order = _qm._majororder;
9669         m.cycle = _qm._cycle;
9670         m.time = _qm._time;
9671         m.dtime = _qm._dtime;
9672         m.use_specmf = _qm._use_specmf;
9673         m.ascii_labels = _qm._ascii_labels;
9674         m.guihide = _qm._guihide;
9675         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
9676         m.conserved = _qm._conserved;
9677         m.extensive = _qm._extensive;
9678         m.centering = centering;
9679         strcpy(m.label, OPT(_qm._label));
9680         strcpy(m.units, OPT(_qm._unit));
9681         strcpy(m.meshid, OPT(_qm._meshname));
9682         db_SetMissingValueForPut(m.missing_value, _qm._missing_value);
9683 
9684         for (i=0; i<ndims; i++) {
9685             m.dims[i] = _qm._dims[i];
9686             m.zones[i] = _qm._zones[i];
9687             m.min_index[i] = _qm._minindex[i];
9688             m.max_index[i] = _qm._maxindex_n[i];
9689             switch (centering) {
9690                 case DB_NODECENT:
9691                     m.align[i] = 0.0; break;
9692                 case DB_EDGECENT: /* edge centering on 1D mesh is like zone centering */
9693                     if (ndims == 1) m.align[i] = 0.5; break;
9694                 case DB_FACECENT: /* face centering on 2D mesh is like zone centering */
9695                     if (ndims == 2) m.align[i] = 0.5; break;
9696                 case DB_ZONECENT:
9697                     m.align[i] = 0.5; break;
9698                 default:
9699                     m.align[i] = 0.5; break;
9700             }
9701         }
9702 
9703         /* output mrgtree info if we have it */
9704         if (_qm._region_pnames != NULL) {
9705             int len;
9706             DBStringArrayToStringList((char const * const *)_qm._region_pnames, -1, &s, &len);
9707             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.region_pnames/*out*/,
9708                 friendly_name(name, "_region_pnames", 0));
9709             FREE(s);
9710         }
9711 
9712         /* Write quadvar header to file */
9713         STRUCT(DBquadvar) {
9714             MEMBER_S(str(m.meshid), meshid);
9715             MEMBER_R(str(m.value[_j]), value, nvars);
9716             MEMBER_R(str(m.mixed_value[_j]), mixed_value, nvars);
9717             if (m.ndims)        MEMBER_S(int, ndims);
9718             if (m.nvals)        MEMBER_S(int, nvals);
9719             if (m.nels)         MEMBER_S(int, nels);
9720             if (m.origin)       MEMBER_S(int, origin);
9721             if (m.mixlen)       MEMBER_S(int, mixlen);
9722             if (m.major_order)  MEMBER_S(int, major_order);
9723             if (m.cycle)        MEMBER_S(int, cycle);
9724             if (_qm._time_set)  MEMBER_S(float, time);
9725             if (_qm._dtime_set) MEMBER_S(double, dtime);
9726             if (m.use_specmf)   MEMBER_S(int, use_specmf);
9727             if (m.ascii_labels) MEMBER_S(int, ascii_labels);
9728             if (m.datatype)     MEMBER_S(int, datatype);
9729             if (m.guihide)      MEMBER_S(int, guihide);
9730             if (m.conserved)    MEMBER_S(int, conserved);
9731             if (m.extensive)    MEMBER_S(int, extensive);
9732             if (m.centering)    MEMBER_S(int, centering);
9733             if (m.missing_value)MEMBER_S(double, missing_value);
9734             MEMBER_3(int, dims);
9735             MEMBER_3(int, zones);
9736             MEMBER_3(int, min_index);
9737             MEMBER_3(int, max_index);
9738             MEMBER_3(float, align);
9739             MEMBER_S(str(m.label), label);
9740             MEMBER_S(str(m.units), units);
9741             MEMBER_S(str(m.region_pnames), region_pnames);
9742         } OUTPUT(dbfile, DB_QUADVAR, name, &m);
9743 
9744         FREE(_qm._meshname);
9745     } CLEANUP {
9746         FREE(_qm._meshname);
9747         /*void*/
9748     } END_PROTECT;
9749     return 0;
9750 }
9751 
9752 /*-------------------------------------------------------------------------
9753  * Function:    PrepareForQuadvarDecompression
9754  *
9755  * Purpose:     Does some small work to prepare for possible quadvar
9756  *              decompression
9757  *
9758  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
9759  *-------------------------------------------------------------------------
9760  */
9761 static void
PrepareForQuadvarDecompression(DBfile_hdf5 * dbfile,char const * varname,const DBquadvar * qv)9762 PrepareForQuadvarDecompression(DBfile_hdf5 *dbfile, char const *varname,
9763     const DBquadvar *qv)
9764 {
9765 #ifdef HAVE_HZIP
9766     int i;
9767     db_hdf5_hzip_clear_params();
9768     db_hdf5_hzip_params.dbfile = dbfile;
9769     db_hdf5_hzip_params.isquad = 1;
9770     db_hdf5_hzip_params.meshname = qv->meshname;
9771     db_hdf5_hzip_params.ndims = qv->ndims;
9772     for (i = 0; i < qv->ndims; i++)
9773         db_hdf5_hzip_params.dims[i] = qv->dims[i];
9774 #endif
9775 }
9776 
9777 /*-------------------------------------------------------------------------
9778  * Function:    db_hdf5_GetQuadvar
9779  *
9780  * Purpose:     Reads a quadvar object from the file
9781  *
9782  * Return:      Success:        Ptr to new quadvar object
9783  *
9784  *              Failure:        NULL
9785  *
9786  * Programmer:  Robb Matzke
9787  *              Wednesday, March 31, 1999
9788  *
9789  * Modifications:
9790  *
9791  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
9792  *   Made it set datatype correctly. Added support for dataReadMask
9793  *
9794  *   Mark C. Miller, Thu Jul 17 15:13:57 PDT 2008
9795  *   Added to call to prepare for possible decompression.
9796  *
9797  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
9798  *   Added support for conserved/extensive options.
9799  *
9800  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
9801  *   Added logic to control behavior of slash character swapping for
9802  *   windows/linux and skipping of first semicolon in calls to
9803  *   db_StringListToStringArray.
9804  *
9805  *   Mark C. Miller, Thu Feb  4 11:27:59 PST 2010
9806  *   Added missing setting for recently added centering member.
9807  *-------------------------------------------------------------------------
9808  */
9809 SILO_CALLBACK DBquadvar *
db_hdf5_GetQuadvar(DBfile * _dbfile,char const * name)9810 db_hdf5_GetQuadvar(DBfile *_dbfile, char const *name)
9811 {
9812     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9813     static char         *me = "db_hdf5_GetQuadvar";
9814     char                *s = 0;
9815     hid_t               o=-1, attr=-1;
9816     int                 _objtype, stride, i;
9817     DBquadvar_mt        m;
9818     DBquadvar           *qv=NULL;
9819 
9820     PROTECT {
9821         /* Open object and make sure it's a quadvar */
9822         if ((o=H5Topen(dbfile->cwg, name))<0) {
9823             db_perror(name, E_NOTFOUND, me);
9824             UNWIND();
9825         }
9826         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
9827             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
9828             H5Aclose(attr)<0) {
9829             db_perror(name, E_CALLFAIL, me);
9830             UNWIND();
9831         }
9832         if (DB_QUADVAR!=(DBObjectType)_objtype) {
9833             db_perror(name, E_CALLFAIL, me);
9834             UNWIND();
9835         }
9836 
9837         /* Read quadvar data into memory */
9838         memset(&m, 0, sizeof m);
9839         if ((attr=H5Aopen_name(o, "silo"))<0 ||
9840             H5Aread(attr, DBquadvar_mt5, &m)<0 ||
9841             H5Aclose(attr)<0) {
9842             db_perror(name, E_CALLFAIL, me);
9843             UNWIND();
9844         }
9845 
9846         /* Create a quadvar object and initialize meta data */
9847         if (NULL==(qv=DBAllocQuadvar())) return NULL;
9848         qv->name = BASEDUP(name);
9849         qv->meshname = OPTDUP(m.meshid);
9850         qv->units = OPTDUP(m.units);
9851         qv->label = OPTDUP(m.label);
9852         qv->cycle = m.cycle;
9853         if ((qv->datatype = db_hdf5_GetVarType(_dbfile, m.value[0])) < 0)
9854             qv->datatype = silo2silo_type(m.datatype);
9855         if (force_single_g) qv->datatype = DB_FLOAT;
9856         qv->nels = m.nels;
9857         qv->nvals = m.nvals;
9858         qv->ndims = m.ndims;
9859         qv->major_order = m.major_order;
9860         qv->origin = m.origin;
9861         qv->time = m.time;
9862         qv->dtime = m.dtime;
9863         qv->mixlen = m.mixlen;
9864         qv->use_specmf = m.use_specmf;
9865         qv->ascii_labels = m.ascii_labels;
9866         qv->guihide = m.guihide;
9867         qv->conserved = m.conserved;
9868         qv->extensive = m.extensive;
9869         qv->centering = m.centering;
9870         db_SetMissingValueForGet(qv->missing_value, m.missing_value);
9871         for (stride=1, i=0; i<m.ndims; stride*=m.dims[i++]) {
9872             qv->dims[i] = m.dims[i];
9873             qv->stride[i] = stride;
9874             qv->min_index[i] = m.min_index[i];
9875             qv->max_index[i] = m.max_index[i];
9876             qv->align[i] = m.align[i];
9877         }
9878 
9879         PrepareForQuadvarDecompression(dbfile, name, qv);
9880 
9881         /* Read the raw data */
9882         if (m.nvals>MAX_VARS) {
9883             db_perror(name, E_CALLFAIL, me);
9884             UNWIND();
9885         }
9886         if (SILO_Globals.dataReadMask & DBQVData && m.nvals && m.ndims>0)
9887         {
9888             qv->vals = (void **)calloc(m.nvals, sizeof(void*));
9889             if (m.mixlen) qv->mixvals = (void **)calloc(m.nvals, sizeof(void*));
9890             for (i=0; i<m.nvals; i++) {
9891                 qv->vals[i] = db_hdf5_comprd(dbfile, m.value[i], 0);
9892                 if (m.mixlen && m.mixed_value[i][0]) {
9893                     qv->mixvals[i] = db_hdf5_comprd(dbfile, m.mixed_value[i], 0);
9894                 }
9895             }
9896         }
9897 
9898         s = (char *)db_hdf5_comprd(dbfile, m.region_pnames, 1);
9899         if (s) qv->region_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
9900         FREE(s);
9901 
9902         H5Tclose(o);
9903 
9904     } CLEANUP {
9905         H5E_BEGIN_TRY {
9906             H5Aclose(attr);
9907             H5Tclose(o);
9908         } H5E_END_TRY;
9909         DBFreeQuadvar(qv);
9910     } END_PROTECT;
9911 
9912     return qv;
9913 }
9914 
9915 /*-------------------------------------------------------------------------
9916  * Function:    PrepareForUcdmeshCompression
9917  *
9918  * Purpose:     Does some small work to prepare for possible mesh
9919  *              compression
9920  *
9921  * Return:      Success:        ALLOW_MESH_COMPRESSION
9922  *
9923  *              Failure:        0
9924  *
9925  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
9926  *-------------------------------------------------------------------------
9927  */
PrepareForUcdmeshCompression(DBfile_hdf5 * dbfile,char const * meshname,char const * zlname)9928 static int PrepareForUcdmeshCompression(DBfile_hdf5 *dbfile,
9929     char const *meshname, char const *zlname)
9930 {
9931     if (SILO_Globals.compressionParams == 0) return 0;
9932 
9933 #ifdef HAVE_HZIP
9934     if (LookupNodelist(dbfile, zlname, meshname) != 0)
9935     {
9936         db_hdf5_hzip_clear_params();
9937         db_hdf5_hzip_params.dbfile = dbfile;
9938         db_hdf5_hzip_params.zlname = zlname;
9939         db_hdf5_hzip_params.meshname = meshname;
9940         AddMeshnameToNodelist(dbfile, zlname, meshname);
9941         return ALLOW_MESH_COMPRESSION;
9942     }
9943 #endif
9944     return 0;
9945 }
9946 
9947 /*-------------------------------------------------------------------------
9948  * Function:    db_hdf5_PutUcdmesh
9949  *
9950  * Purpose:     Write a ucdmesh object to the file.
9951  *
9952  * Return:      Success:        0
9953  *
9954  *              Failure:        -1
9955  *
9956  * Programmer:  Robb Matzke
9957  *              Thursday, April  1, 1999
9958  *
9959  * Modifications:
9960  *              Robb Matzke, 1999-07-13
9961  *              Added `group_no' and `gnodeno' properties to duplicate
9962  *              changes made to the PDB driver.
9963  *
9964  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
9965  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
9966  *
9967  *   Mark C. Miller, Mon Jul 31 17:43:52 PDT 2006
9968  *   Removed use of fullname for zonelist, facelist, phzonelist options
9969  *
9970  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
9971  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
9972  *
9973  *   Mark C. Miller, Thu Jul 17 15:14:44 PDT 2008
9974  *   Added call to prepare for possible compression. Changed calls that
9975  *   write coordinates and gnodeno to use compwrz
9976  *
9977  *   Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
9978  *   Added support for long long global node numbers.
9979  *   Changed how long long global node/zone numbers are supported
9980  *   from a int (bool), "llong_gnode|zoneno" to an int holding
9981  *   the actual datatype. The type is assumed int if it its
9982  *   value is zero or it does not exist. Otherwise, the type is
9983  *   is whatever is stored in gnznodtype member.
9984  *
9985  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
9986  *   Refactored logic to handle time, dtime and cycle to a new method,
9987  *   db_hdf5_handle_ctdt().
9988  *-------------------------------------------------------------------------
9989  */
9990 /*ARGSUSED*/
9991 SILO_CALLBACK int
db_hdf5_PutUcdmesh(DBfile * _dbfile,char const * name,int ndims,char const * const * coordnames,DBVCP2_t _coords,int nnodes,int nzones,char const * zlname,char const * flname,int datatype,DBoptlist const * optlist)9992 db_hdf5_PutUcdmesh(DBfile *_dbfile, char const *name, int ndims, char const * const *coordnames,
9993                    DBVCP2_t _coords, int nnodes, int nzones, char const *zlname,
9994                    char const *flname, int datatype, DBoptlist const *optlist)
9995 {
9996     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
9997     static char         *me = "db_hdf5_PutUcdmesh";
9998     DBucdmesh_mt        m;
9999     int                 i, compressionFlags;
10000     void const * const *coords = (void const * const *) _coords;
10001 
10002     memset(&_um, 0, sizeof _um);
10003     memset(&m, 0, sizeof m);
10004 
10005     PROTECT {
10006         /* Check datatype */
10007         if (DB_FLOAT!=datatype && DB_DOUBLE!=datatype) {
10008             db_perror("invalid floating-point datatype", E_BADARGS, me);
10009             UNWIND();
10010         }
10011 
10012         /* Set global options */
10013         strcpy(_um._meshname, name);
10014         _um._coord_sys = DB_OTHER;
10015         _um._facetype = DB_RECTILINEAR;
10016         _um._ndims = ndims;
10017         _um._nnodes = nnodes;
10018         _um._nzones = nzones;
10019         _um._planar = DB_OTHER;
10020         _um._use_specmf = DB_OFF;
10021         _um._group_no = -1;
10022         db_ProcessOptlist(DB_UCDMESH, optlist);
10023 
10024         /* Prepare for possible compression of coords/gnodeno */
10025         compressionFlags = PrepareForUcdmeshCompression(dbfile,
10026             name, zlname);
10027 
10028         /* hack to maintain backward compatibility with pdb driver */
10029         db_hdf5_handle_ctdt(dbfile, _um._time_set, _um._time,
10030             _um._dtime_set, _um._dtime, _um._cycle);
10031 
10032         /* Obtain extents as doubles */
10033         if (DB_DOUBLE==datatype) {
10034             UM_CalcExtents(coords, datatype, ndims, nnodes,
10035                            m.min_extents/*out*/, m.max_extents/*out*/);
10036         } else {
10037             float min_extents[3], max_extents[3];
10038             UM_CalcExtents(coords, datatype, ndims, nnodes,
10039                            min_extents/*out*/, max_extents/*out*/);
10040             for (i=0; i<ndims; i++) {
10041                 m.min_extents[i] = min_extents[i];
10042                 m.max_extents[i] = max_extents[i];
10043             }
10044         }
10045 
10046         /* Write variable arrays: coords[], gnodeno[] */
10047         for (i=0; (i<ndims) && (nnodes>0); i++) {
10048             db_hdf5_compwrz(dbfile, datatype, 1, &nnodes, coords[i],
10049                 m.coord[i]/*out*/, friendly_name(name, "_coord%d", &i),
10050                 compressionFlags);
10051         }
10052         if (_um._llong_gnodeno && (nnodes > 0))
10053             db_hdf5_compwr(dbfile, DB_LONG_LONG, 1, &nnodes, _um._gnodeno,
10054                 m.gnodeno/*out*/, friendly_name(name, "_gnodeno",0));
10055         else if (nnodes > 0)
10056             db_hdf5_compwrz(dbfile, DB_INT, 1, &nnodes, _um._gnodeno,
10057                 m.gnodeno/*out*/, friendly_name(name, "_gnodeno",0),
10058                 compressionFlags);
10059 
10060         if (nnodes && _um._ghost_node_labels)
10061         {
10062             db_hdf5_compwr(dbfile, DB_CHAR, 1, &nnodes, _um._ghost_node_labels,
10063                 m.ghost_node_labels/*out*/, friendly_name(name, "_ghost_node_labels",0));
10064         }
10065 
10066         if (_um._alt_nodenum_vars != NULL) {
10067             char *s; int len;
10068             DBStringArrayToStringList((char const * const *)_um._alt_nodenum_vars, -1, &s, &len);
10069             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.alt_nodenum_vars/*out*/,
10070                 friendly_name(name, "_alt_nodenum_vars", 0));
10071             FREE(s);
10072         }
10073 
10074         /* Build ucdmesh header in memory */
10075         m.ndims = ndims;
10076         m.nnodes = nnodes;
10077         m.nzones = nzones;
10078         m.facetype = _um._facetype;
10079         m.coord_sys = _um._coord_sys;
10080         m.topo_dim = _um._topo_dim;
10081         m.planar = _um._planar;
10082         m.origin = _um._origin;
10083         m.cycle = _um._cycle;
10084         m.time = _um._time;
10085         m.dtime = _um._dtime;
10086         m.group_no = _um._group_no;
10087         m.guihide = _um._guihide;
10088         strcpy(m.zonelist, OPT(zlname));
10089         strcpy(m.facelist, OPT(flname));
10090         strcpy(m.phzonelist, OPT(_um._phzl_name));
10091         for (i=0; i<ndims; i++) {
10092             strcpy(m.label[i], OPT(_um._labels[i]));
10093             strcpy(m.units[i], OPT(_um._units[i]));
10094         }
10095         strcpy(m.mrgtree_name, OPT(_um._mrgtree_name));
10096         m.tv_connectivity = _um._tv_connectivity;
10097         m.disjoint_mode = _um._disjoint_mode;
10098         m.gnznodtype = _um._llong_gnodeno?DB_LONG_LONG:0;
10099 
10100         /* Write ucdmesh header to file */
10101         STRUCT(DBucdmesh) {
10102             if (m.ndims)        MEMBER_S(int, ndims);
10103             if (m.nnodes)       MEMBER_S(int, nnodes);
10104             if (m.nzones)       MEMBER_S(int, nzones);
10105             if (m.facetype)     MEMBER_S(int, facetype);
10106             if (m.cycle)        MEMBER_S(int, cycle);
10107             if (m.coord_sys)    MEMBER_S(int, coord_sys);
10108             if (m.topo_dim)     MEMBER_S(int, topo_dim);
10109             if (m.planar)       MEMBER_S(int, planar);
10110             if (m.origin)       MEMBER_S(int, origin);
10111             if (m.group_no)     MEMBER_S(int, group_no);
10112             if (m.guihide)      MEMBER_S(int, guihide);
10113             if (_um._time_set)  MEMBER_S(float, time);
10114             if (_um._dtime_set) MEMBER_S(double, dtime);
10115             MEMBER_S(str(m.facelist), facelist);
10116             MEMBER_S(str(m.zonelist), zonelist);
10117             MEMBER_S(str(m.gnodeno), gnodeno);
10118             MEMBER_3(double, min_extents);
10119             MEMBER_3(double, max_extents);
10120             MEMBER_R(str(m.coord[_j]), coord, ndims);
10121             MEMBER_R(str(m.label[_j]), label, ndims);
10122             MEMBER_R(str(m.units[_j]), units, ndims);
10123             MEMBER_S(str(m.phzonelist), phzonelist);
10124             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
10125             if (m.tv_connectivity) MEMBER_S(int, tv_connectivity);
10126             if (m.disjoint_mode)   MEMBER_S(int, disjoint_mode);
10127             if (m.gnznodtype)   MEMBER_S(int, gnznodtype);
10128             MEMBER_S(str(m.ghost_node_labels), ghost_node_labels);
10129             MEMBER_S(str(m.alt_nodenum_vars), alt_nodenum_vars);
10130         } OUTPUT(dbfile, DB_UCDMESH, name, &m);
10131 
10132     } CLEANUP {
10133         /*void*/
10134     } END_PROTECT;
10135     return 0;
10136 }
10137 
10138 /*-------------------------------------------------------------------------
10139  * Function:    db_hdf5_PutUcdsubmesh
10140  *
10141  * Purpose:     Write a subset of a ucdmesh object into the file.
10142  *
10143  * Return:      Success:        0
10144  *
10145  *              Failure:        -1
10146  *
10147  * Programmer:  Robb Matzke
10148  *              Friday, April  2, 1999
10149  *
10150  * Modifications:
10151  *
10152  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
10153  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
10154  *
10155  *   Mark C. Miller, Mon Jul 31 17:57:29 PDT 2006
10156  *   Eliminated use of db_hdf5_fullname for zlname, flname and added
10157  *   possible optional ph_zlname which was mistakenly left out in the
10158  *   initial implementation.
10159  *
10160  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
10161  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
10162  *
10163  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
10164  *   Refactored logic to handle time, dtime and cycle to a new method,
10165  *   db_hdf5_handle_ctdt().
10166  *-------------------------------------------------------------------------
10167  */
10168 /*ARGSUSED*/
10169 SILO_CALLBACK int
db_hdf5_PutUcdsubmesh(DBfile * _dbfile,char const * name,char const * parentmesh,int nzones,char const * zlname,char const * flname,DBoptlist const * optlist)10170 db_hdf5_PutUcdsubmesh(DBfile *_dbfile, char const *name, char const *parentmesh,
10171                       int nzones, char const *zlname, char const *flname,
10172                       DBoptlist const *optlist)
10173 {
10174     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
10175     static char         *me = "db_pdb_PutUcdmesh";
10176     hid_t               o=-1, attr=-1;
10177     int                 _objtype, i;
10178     DBucdmesh_mt        m;
10179 
10180     PROTECT {
10181         /* Get metadata from the parent UCD mesh */
10182         if ((o=H5Topen(dbfile->cwg, parentmesh))<0) {
10183             db_perror(name, E_NOTFOUND, me);
10184             UNWIND();
10185         }
10186         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
10187             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
10188             H5Aclose(attr)<0) {
10189             db_perror(name, E_CALLFAIL, me);
10190             UNWIND();
10191         }
10192         if (DB_UCDMESH!=(DBObjectType)_objtype) {
10193             db_perror(name, E_CALLFAIL, me);
10194             UNWIND();
10195         }
10196         memset(&m, 0, sizeof m);
10197         if ((attr=H5Aopen_name(o, "silo"))<0 ||
10198             H5Aread(attr, DBucdmesh_mt5, &m)<0 ||
10199             H5Aclose(attr)<0) {
10200             db_perror(name, E_CALLFAIL, me);
10201             UNWIND();
10202         }
10203         H5Tclose(o);
10204 
10205         /* Set global options */
10206         strcpy(_um._meshname, name);
10207         _um._coord_sys = DB_OTHER;
10208         _um._facetype = DB_RECTILINEAR;
10209         _um._ndims = m.ndims;
10210         _um._nnodes = m.nnodes;
10211         _um._nzones = m.nzones;
10212         _um._planar = DB_OTHER;
10213         _um._use_specmf = DB_OFF;
10214         _um._group_no = -1;
10215         db_ProcessOptlist(DB_UCDMESH, optlist);
10216 
10217         /* hack to maintain backward compatibility with pdb driver */
10218         db_hdf5_handle_ctdt(dbfile, _um._time_set, _um._time,
10219             _um._dtime_set, _um._dtime, _um._cycle);
10220 
10221         /* Build header in memory -- most fields are already initialized */
10222         m.ndims = _um._ndims;
10223         m.nnodes = _um._nnodes;
10224         m.nzones = _um._nzones;
10225         m.facetype = _um._facetype;
10226         m.cycle = _um._cycle;
10227         m.coord_sys = _um._coord_sys;
10228         m.topo_dim = _um._topo_dim;
10229         m.planar = _um._planar;
10230         m.origin = _um._origin;
10231         m.time = _um._time;
10232         m.dtime = _um._dtime;
10233         m.guihide = _um._guihide;
10234         strcpy(m.zonelist, zlname);
10235         strcpy(m.facelist, OPT(flname));
10236         strcpy(m.phzonelist, OPT(_um._phzl_name));
10237         for (i=0; i<m.ndims; i++) {
10238             strcpy(m.label[i], OPT(_um._labels[i]));
10239             strcpy(m.units[i], OPT(_um._units[i]));
10240         }
10241         strcpy(m.mrgtree_name, OPT(_um._mrgtree_name));
10242         m.tv_connectivity = _um._tv_connectivity;
10243         m.disjoint_mode = _um._disjoint_mode;
10244 
10245         /* Write header to file */
10246         STRUCT(DBucdmesh) {
10247             if (m.ndims)        MEMBER_S(int, ndims);
10248             if (m.nnodes)       MEMBER_S(int, nnodes);
10249             if (m.nzones)       MEMBER_S(int, nzones);
10250             if (m.facetype)     MEMBER_S(int, facetype);
10251             if (m.cycle)        MEMBER_S(int, cycle);
10252             if (m.coord_sys)    MEMBER_S(int, coord_sys);
10253             if (m.topo_dim)     MEMBER_S(int, topo_dim);
10254             if (m.planar)       MEMBER_S(int, planar);
10255             if (m.origin)       MEMBER_S(int, origin);
10256             if (m.guihide)      MEMBER_S(int, guihide);
10257             if (_um._time_set)  MEMBER_S(float, time);
10258             if (_um._dtime_set) MEMBER_S(double, dtime);
10259             MEMBER_S(str(m.facelist), facelist);
10260             MEMBER_S(str(m.zonelist), zonelist);
10261             MEMBER_3(double, min_extents);
10262             MEMBER_3(double, max_extents);
10263             MEMBER_R(str(m.coord[_j]), coord, m.ndims);
10264             MEMBER_R(str(m.label[_j]), label, m.ndims);
10265             MEMBER_R(str(m.units[_j]), units, m.ndims);
10266             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
10267             if (m.tv_connectivity) MEMBER_S(int, tv_connectivity);
10268             if (m.disjoint_mode)   MEMBER_S(int, disjoint_mode);
10269         } OUTPUT(dbfile, DB_UCDMESH, name, &m);
10270 
10271     } CLEANUP {
10272         /*void*/
10273     } END_PROTECT;
10274     return 0;
10275 }
10276 
10277 /*-------------------------------------------------------------------------
10278  * Function:    PrepareForUcdmeshDecompression
10279  *
10280  * Purpose:     Does some small work to prepare for possible mesh
10281  *              decompression
10282  *
10283  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
10284  *-------------------------------------------------------------------------
10285  */
10286 static void
PrepareForUcdmeshDecompression(DBfile_hdf5 * dbfile,char const * meshname,char const * zlname)10287 PrepareForUcdmeshDecompression(DBfile_hdf5 *dbfile, char const *meshname,
10288     char const *zlname)
10289 {
10290 #ifdef HAVE_HZIP
10291     db_hdf5_hzip_clear_params();
10292     db_hdf5_hzip_params.dbfile = dbfile;
10293     db_hdf5_hzip_params.meshname = meshname;
10294     db_hdf5_hzip_params.zlname = zlname;
10295 #endif
10296 }
10297 
10298 /*-------------------------------------------------------------------------
10299  * Function:    db_hdf5_GetUcdmesh
10300  *
10301  * Purpose:     Reads a UCD mesh object from the file.
10302  *
10303  * Return:      Success:        Pointer to a new ucdmesh.
10304  *
10305  *              Failure:        NULL
10306  *
10307  * Programmer:  Robb Matzke
10308  *              Thursday, April  1, 1999
10309  *
10310  * Modifications:
10311  *              Robb Matzke, 1999-07-13
10312  *              Added `group_no', and `gnodeno' to duplicate changes made to
10313  *              the PDB driver.
10314  *
10315  *              Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
10316  *              Made it set datatype correctly.
10317  *              Added support for dataReadMask
10318  *
10319  *              Mark C. Miller, Thu Sep  7 10:50:55 PDT 2006
10320  *              Added use of db_hdf5_resolvename for retrieval of
10321  *              sub-objects.
10322  *
10323  *              Mark C. Miller, Thu Jul 17 15:16:13 PDT 2008
10324  *              Added support for decompression. Needed to change order
10325  *              of operations to read zonelist first as that is the
10326  *              bootstrap HZIP needs to decompress anything.
10327  *
10328  *              Mark C. Miller, Thu Nov  5 16:17:18 PST 2009
10329  *              Made it NOT db_Split() the zonelist if mask is such
10330  *              that zonelist info is NOT included.
10331  *
10332  *              Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
10333  *              Changed how long long global node/zone numbers are supported
10334  *              from a int (bool), "llong_gnode|zoneno" to an int holding
10335  *              the actual datatype. The type is assumed int if it its
10336  *              value is zero or it does not exist. Otherwise, the type is
10337  *              is whatever is stored in gnznodtype member.
10338  *-------------------------------------------------------------------------
10339  */
10340 SILO_CALLBACK DBucdmesh *
db_hdf5_GetUcdmesh(DBfile * _dbfile,char const * name)10341 db_hdf5_GetUcdmesh(DBfile *_dbfile, char const *name)
10342 {
10343     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
10344     static char         *me = "db_hdf5_GetUcdmesh";
10345     hid_t               o=-1, attr=-1;
10346     int                 _objtype, i;
10347     DBucdmesh_mt        m;
10348     DBucdmesh           *um=NULL;
10349 
10350     PROTECT {
10351         /* Open object and make sure it's a ucdmesh */
10352         if ((o=H5Topen(dbfile->cwg, name))<0) {
10353             db_perror(name, E_NOTFOUND, me);
10354             UNWIND();
10355         }
10356         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
10357             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
10358             H5Aclose(attr)<0) {
10359             db_perror(name, E_CALLFAIL, me);
10360             UNWIND();
10361         }
10362         if (DB_UCDMESH!=(DBObjectType)_objtype) {
10363             db_perror(name, E_CALLFAIL, me);
10364             UNWIND();
10365         }
10366 
10367         /* Read header into memory */
10368         memset(&m, 0, sizeof m);
10369         if ((attr=H5Aopen_name(o, "silo"))<0 ||
10370             H5Aread(attr, DBucdmesh_mt5, &m)<0 ||
10371             H5Aclose(attr)<0) {
10372             db_perror(name, E_CALLFAIL, me);
10373             UNWIND();
10374         }
10375 
10376         /* Create a ucdmesh object and initialize meta data */
10377         if (NULL==(um=DBAllocUcdmesh())) return NULL;
10378         um->name = BASEDUP(name);
10379         um->cycle = m.cycle;
10380         um->coord_sys = m.coord_sys;
10381         um->topo_dim = m.topo_dim;
10382         /* The value we store to the file for 'topo_dim' member is
10383            designed such that zero indicates a value that was NOT
10384            specified in the file. Since zero is a valid topological
10385            dimension, when we store topo_dim to a file, we always
10386            add 1. So, we have to subtract it here. However, this
10387            data member was not being handled correctly in files
10388            versions before 4.7. So, for older files, if topo_dim
10389            is non-zero we just pass it without alteration. */
10390         if (!DBFileVersionGE(_dbfile,4,5,1) || DBFileVersionGE(_dbfile, 4,7,0))
10391             um->topo_dim = um->topo_dim - 1;
10392         if ((um->datatype = db_hdf5_GetVarType(_dbfile, m.coord[0])) < 0)
10393             um->datatype = DB_FLOAT;
10394         if (force_single_g) um->datatype = DB_FLOAT;
10395         um->time = m.time;
10396         um->dtime = m.dtime;
10397         um->ndims = m.ndims;
10398         um->nnodes = m.nnodes;
10399         um->origin = m.origin;
10400         um->group_no = m.group_no;
10401         um->guihide = m.guihide;
10402         for (i=0; i<m.ndims; i++) {
10403             um->units[i] = OPTDUP(m.units[i]);
10404             um->labels[i] = OPTDUP(m.label[i]);
10405             if (um->datatype == DB_DOUBLE)
10406             {
10407                 ((double*)um->min_extents)[i] = m.min_extents[i];
10408                 ((double*)um->max_extents)[i] = m.max_extents[i];
10409             }
10410             else
10411             {
10412                 um->min_extents[i] = m.min_extents[i];
10413                 um->max_extents[i] = m.max_extents[i];
10414             }
10415         }
10416         um->mrgtree_name = OPTDUP(m.mrgtree_name);
10417         um->tv_connectivity = m.tv_connectivity;
10418         um->disjoint_mode = m.disjoint_mode;
10419 
10420         /* We have a problem with data read mask and compression. If
10421            masks says not to read zonelist but the zonelist is actually
10422            compressed, we're gonna need it to complete the mesh read.
10423            So, we need a cheap way to ask if the zonelist is compressed
10424            and hope it is cheap enough that always asking that question
10425            won't present performance problems. For now, we are just
10426            going to let it fail. */
10427 
10428         /* For compression's sake, read the zonelist first */
10429         if (um->nnodes>0 && m.zonelist[0] && (SILO_Globals.dataReadMask & DBUMZonelist)) {
10430             calledFromGetUcdmesh = um->name;
10431             um->zones = db_hdf5_GetZonelist(_dbfile,
10432                             db_hdf5_resolvename(_dbfile, name, m.zonelist));
10433             calledFromGetUcdmesh = 0;
10434 
10435             /*----------------------------------------------------------*/
10436             /* If we have ghost zones, split any group of shapecnt so   */
10437             /* all the shapecnt refer to all real zones or all ghost    */
10438             /* zones.  This will make dealing with ghost zones easier   */
10439             /* for applications.                                        */
10440             /*----------------------------------------------------------*/
10441             if (um->zones)
10442             {
10443                 if (((um->zones->min_index != 0) ||
10444                      (um->zones->max_index != um->zones->nzones - 1)) &&
10445                      SILO_Globals.dataReadMask & DBZonelistInfo)
10446                 {
10447                     db_SplitShapelist (um);
10448                 }
10449             }
10450         }
10451 
10452         /* Prepare for possible ucdmesh decompression */
10453         PrepareForUcdmeshDecompression(dbfile, name, m.zonelist);
10454 
10455         /* Read the raw data */
10456         if (SILO_Globals.dataReadMask & DBUMCoords)
10457         {
10458             for (i=0; i<m.ndims; i++) {
10459                 um->coords[i] = db_hdf5_comprd(dbfile, m.coord[i], 0);
10460             }
10461         }
10462         if (SILO_Globals.dataReadMask & DBUMGlobNodeNo)
10463             um->gnodeno = db_hdf5_comprd(dbfile, m.gnodeno, 1);
10464         um->gnznodtype = m.gnznodtype?m.gnznodtype:DB_INT;
10465         if (SILO_Globals.dataReadMask & DBUMGhostNodeLabels)
10466             um->ghost_node_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_node_labels, 1);
10467 
10468         /* alt nodenum vars */
10469         {
10470             int nnames = -1;
10471             char *tmpannums = (char *)db_hdf5_comprd(dbfile, m.alt_nodenum_vars, 1);
10472             if (tmpannums)
10473                 um->alt_nodenum_vars = DBStringListToStringArray(tmpannums, &nnames, !skipFirstSemicolon);
10474             FREE(tmpannums);
10475         }
10476 
10477         /* Read face, zone, and edge lists */
10478         if (um->nnodes>0 && m.facelist[0] && (SILO_Globals.dataReadMask & DBUMFacelist)) {
10479             um->faces = db_hdf5_GetFacelist(_dbfile,
10480                             db_hdf5_resolvename(_dbfile, name, m.facelist));
10481         }
10482         if (um->nnodes>0 && m.phzonelist[0] && (SILO_Globals.dataReadMask & DBUMZonelist)) {
10483             um->phzones = db_hdf5_GetPHZonelist(_dbfile,
10484                               db_hdf5_resolvename(_dbfile, name, m.phzonelist));
10485         }
10486         um->edges = NULL;                               /*FIXME*/
10487 
10488         H5Tclose(o);
10489     } CLEANUP {
10490         H5E_BEGIN_TRY {
10491             H5Aclose(attr);
10492             H5Tclose(o);
10493         } H5E_END_TRY;
10494     } END_PROTECT;
10495 
10496 #ifdef HAVE_HZIP
10497     db_hdf5_hzip_clear_params();
10498 #endif
10499 
10500     return um;
10501 }
10502 
10503 /*-------------------------------------------------------------------------
10504  * Function:    PrepareForUcdvarCompression
10505  *
10506  * Purpose:     Does some small work to prepare for possible ucdvar
10507  *              compression
10508  *
10509  * Return:      Success:        ALLOW_MESH_COMPRESSION
10510  *
10511  *              Failure:        0
10512  *
10513  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
10514  *-------------------------------------------------------------------------
10515  */
10516 static int
PrepareForUcdvarCompression(DBfile_hdf5 * dbfile,char const * varname,char const * meshname,int datatype,int centering)10517 PrepareForUcdvarCompression(DBfile_hdf5 *dbfile, char const *varname,
10518     char const *meshname, int datatype, int centering)
10519 {
10520     if (SILO_Globals.compressionParams == 0) return 0;
10521 
10522 #ifdef HAVE_HZIP
10523     if (centering == DB_NODECENT)
10524     {
10525         db_hdf5_hzip_clear_params();
10526         db_hdf5_hzip_params.meshname = meshname;
10527         db_hdf5_hzip_params.dbfile = dbfile;
10528         return ALLOW_MESH_COMPRESSION;
10529     }
10530 #endif
10531     return 0;
10532 }
10533 
10534 /*-------------------------------------------------------------------------
10535  * Function:    db_hdf5_PutUcdvar
10536  *
10537  * Purpose:     Writes UCD variables to the file.
10538  *
10539  * Return:      Success:        0
10540  *
10541  *              Failure:        -1
10542  *
10543  * Programmer:  Robb Matzke
10544  *              Thursday, April  1, 1999
10545  *
10546  * Modifications:
10547  *
10548  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
10549  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
10550  *
10551  *   Brad Whitlock, Wed Jan 18 15:17:15 PST 2006
10552  *   Added ascii_labels.
10553  *
10554  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
10555  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
10556  *
10557  *   Mark C. Miller, Thu Jul 17 15:17:51 PDT 2008
10558  *   Added call to prepare for compression. Changed call to write data
10559  *   to use compwrz.
10560  *
10561  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
10562  *   Added support for conserved/extensive options.
10563  *
10564  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
10565  *   Refactored logic to handle time, dtime and cycle to a new method,
10566  *   db_hdf5_handle_ctdt().
10567  *-------------------------------------------------------------------------
10568  */
10569 /*ARGSUSED*/
10570 SILO_CALLBACK int
db_hdf5_PutUcdvar(DBfile * _dbfile,char const * name,char const * meshname,int nvars,char const * const * varnames,DBVCP2_t _vars,int nels,DBVCP2_t _mixvars,int mixlen,int datatype,int centering,DBoptlist const * optlist)10571 db_hdf5_PutUcdvar(DBfile *_dbfile, char const *name, char const *meshname, int nvars,
10572                   char const * const *varnames, DBVCP2_t _vars,
10573                   int nels, DBVCP2_t _mixvars, int mixlen,
10574                   int datatype, int centering, DBoptlist const *optlist)
10575 {
10576     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
10577     static char         *me = "db_hdf5_PutUcdvar";
10578     char                *s = 0;
10579     DBucdvar_mt         m;
10580     int                 i, saved_ndims, saved_nnodes, saved_nzones;
10581     int                 compressionFlags;
10582     void const * const    *vars = (void const * const *) _vars;
10583     void const * const *mixvars = (void const * const *) _mixvars;
10584 
10585     memset(&m, 0, sizeof m);
10586 
10587     PROTECT {
10588         /* Set global options  - based on previous PutUcdmesh() call */
10589         saved_ndims = _um._ndims;
10590         saved_nnodes = _um._nnodes;
10591         saved_nzones = _um._nzones;
10592         memset(&_um, 0, sizeof _um);
10593         _um._coord_sys = DB_OTHER;
10594         _um._topo_dim = saved_ndims;
10595         _um._facetype = DB_RECTILINEAR;
10596         _um._ndims = saved_ndims;
10597         _um._nnodes = saved_nnodes;
10598         _um._nzones = saved_nzones;
10599         _um._planar = DB_OTHER;
10600         _um._use_specmf = DB_OFF;
10601         _um._group_no = -1;
10602         _um._missing_value = DB_MISSING_VALUE_NOT_SET;
10603         strcpy(_um._meshname, meshname);
10604         db_ProcessOptlist(DB_UCDMESH, optlist); /*yes, UCDMESH*/
10605 
10606         /* Prepare for possible compression of ucdvars */
10607         compressionFlags = PrepareForUcdvarCompression(dbfile, name, meshname,
10608             datatype, centering);
10609 
10610         /* hack to maintain backward compatibility with pdb driver */
10611         db_hdf5_handle_ctdt(dbfile, _um._time_set, _um._time,
10612             _um._dtime_set, _um._dtime, _um._cycle);
10613 
10614         /* Write variable arrays: vars[], mixvars[] */
10615         if (nvars>MAX_VARS) {
10616             db_perror("too many variables", E_BADARGS, me);
10617             UNWIND();
10618         }
10619         for (i=0; i<nvars && nels; i++) {
10620             db_hdf5_compwrz(dbfile, datatype, 1, &nels, vars[i],
10621                 m.value[i]/*out*/, friendly_name(varnames[i], "_data", 0), compressionFlags);
10622 //#warning WHY NOT COMPRESS MIX DATA TOO
10623             if (mixvars && mixvars[i] && mixlen>0) {
10624                 db_hdf5_compwr(dbfile, datatype, 1, &mixlen, mixvars[i],
10625                     m.mixed_value[i]/*out*/, friendly_name(varnames[i], "_mix", 0));
10626             }
10627         }
10628 
10629         /* output mrgtree info if we have it */
10630         if (_um._region_pnames != NULL) {
10631             int len;
10632             DBStringArrayToStringList((char const * const *)_um._region_pnames, -1, &s, &len);
10633             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.region_pnames/*out*/,
10634                 friendly_name(name, "_region_pnames", 0));
10635             FREE(s);
10636         }
10637 
10638         /* Build header in memory */
10639         m.ndims = _um._ndims;
10640         m.nvals = nvars;
10641         m.nels = nels;
10642         m.centering = centering;
10643         m.origin = _um._origin;
10644         m.mixlen = mixlen;
10645         m.cycle = _um._cycle;
10646         m.time = _um._time;
10647         m.dtime = _um._dtime;
10648         m.lo_offset = _um._lo_offset;
10649         m.hi_offset = _um._hi_offset;
10650         m.use_specmf = _um._use_specmf;
10651         m.ascii_labels = _um._ascii_labels;
10652         m.guihide = _um._guihide;
10653         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
10654         m.conserved = _um._conserved;
10655         m.extensive = _um._extensive;
10656         db_SetMissingValueForPut(m.missing_value, _um._missing_value);
10657         strcpy(m.meshid, OPT(_um._meshname));
10658         strcpy(m.label, OPT(_um._label));
10659         strcpy(m.units, OPT(_um._unit));
10660 
10661         /* Write header to file */
10662         STRUCT(DBucdvar) {
10663             MEMBER_R(str(m.value[_j]), value, nvars);
10664             MEMBER_R(str(m.mixed_value[_j]), mixed_value, nvars);
10665             MEMBER_S(str(m.meshid), meshid);
10666             if (m.ndims)        MEMBER_S(int, ndims);
10667             if (m.nvals)        MEMBER_S(int, nvals);
10668             if (m.nels)         MEMBER_S(int, nels);
10669             if (m.centering)    MEMBER_S(int, centering);
10670             if (m.origin)       MEMBER_S(int, origin);
10671             if (m.mixlen)       MEMBER_S(int, mixlen);
10672             if (m.cycle)        MEMBER_S(int, cycle);
10673             if (m.use_specmf)   MEMBER_S(int, use_specmf);
10674             if (m.ascii_labels) MEMBER_S(int, ascii_labels);
10675             if (m.guihide)      MEMBER_S(int, guihide);
10676             if (m.datatype)     MEMBER_S(int, datatype);
10677             if (_um._time_set)  MEMBER_S(float, time);
10678             if (_um._dtime_set) MEMBER_S(double, dtime);
10679             if (_um._lo_offset_set) MEMBER_S(int, lo_offset);
10680             if (_um._hi_offset_set) MEMBER_S(int, hi_offset);
10681             if (m.conserved)    MEMBER_S(int, conserved);
10682             if (m.extensive)    MEMBER_S(int, extensive);
10683             if (m.missing_value)MEMBER_S(double, missing_value);
10684             MEMBER_S(str(m.label), label);
10685             MEMBER_S(str(m.units), units);
10686             MEMBER_S(str(m.region_pnames), region_pnames);
10687         } OUTPUT(dbfile, DB_UCDVAR, name, &m);
10688 
10689     } CLEANUP {
10690         /*void*/
10691     } END_PROTECT;
10692     return 0;
10693 }
10694 
10695 /*-------------------------------------------------------------------------
10696  * Function:    PrepareForUcdvarDecompression
10697  *
10698  * Purpose:     Does some small work to prepare for possible ucdvar
10699  *              decompression
10700  *
10701  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
10702  *
10703  *     We assume here that looking up the nodelist is cheaper than
10704  *     checking if the values are compressed, so we perform that
10705  *     operation first. Reason being is that checking if the
10706  *     dataset is compressed may involve disk I/O. Looking up
10707  *     the nodelist is a bunch of string and pointer compars.
10708  *     But, that operation is always performed!!!
10709  *-------------------------------------------------------------------------
10710  */
10711 static void
PrepareForUcdvarDecompression(DBfile * _dbfile,char const * varname,char const * meshname,char valnames[MAX_VARS][256],int nvals)10712 PrepareForUcdvarDecompression(DBfile *_dbfile, char const *varname,
10713     char const *meshname, char valnames[MAX_VARS][256], int nvals)
10714 {
10715 
10716 #ifdef HAVE_HZIP
10717 
10718     /* We have to have read the mesh zonelist first,
10719        if we don't already have it. */
10720     if (LookupNodelist((DBfile_hdf5*)_dbfile, 0, meshname) == 0)
10721     {
10722         /* See if we even have compressed data to begin with */
10723         int i, haveCompressed = 0;
10724         for (i=0; i<nvals && !haveCompressed; i++)
10725             haveCompressed = db_hdf5_compckz((DBfile_hdf5*)_dbfile, (char*) valnames[i]);
10726 
10727         if (haveCompressed)
10728         {
10729             unsigned long long currentMask = DBGetDataReadMask2();
10730             DBucdmesh *um;
10731             DBSetDataReadMask2(DBUMZonelist|DBZonelistInfo);
10732             um = db_hdf5_GetUcdmesh(_dbfile, (char*) meshname);
10733 
10734             /* Note that if for some reason the zl was not compressed, then
10735                getting it via the above GetUcdmesh call won't register it.
10736                Also, registering an already existing zonelist has no effect.
10737                So, as a precaution, we register the zonelist here, too.
10738                And, since we know the meshname here also, that will get
10739                added to the registered zonelist if it already exists. */
10740             if (um && um->zones)
10741             {
10742                 RegisterNodelist((DBfile_hdf5*)_dbfile, 0, meshname,
10743                     um->zones->ndims, um->zones->nzones, um->zones->origin,
10744                     um->zones->nodelist);
10745                 DBSetDataReadMask2(currentMask);
10746                 DBFreeUcdmesh(um);
10747             }
10748         }
10749     }
10750 
10751     db_hdf5_hzip_clear_params();
10752     db_hdf5_hzip_params.dbfile = (DBfile_hdf5*)_dbfile;
10753     db_hdf5_hzip_params.meshname = meshname;
10754 
10755 #endif
10756 }
10757 
10758 /*-------------------------------------------------------------------------
10759  * Function:    db_hdf5_GetUcdvar
10760  *
10761  * Purpose:     Reads a UCD variable object from the file.
10762  *
10763  * Return:      Success:        Ptr to new UCD variable object
10764  *
10765  *              Failure:        NULL
10766  *
10767  * Programmer:  Robb Matzke
10768  *              Thursday, April  1, 1999
10769  *
10770  * Modifications:
10771  *
10772  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
10773  *   Made it set the correct datatype. Added support for dataReadMask
10774  *
10775  *   Brad Whitlock, Wed Jan 18 15:17:48 PST 2006
10776  *   Added ascii_labels.
10777  *
10778  *   Mark C. Miller, Thu Jul 17 15:19:14 PDT 2008
10779  *   Added call to prepare for possible decompression.
10780  *
10781  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
10782  *   Added support for conserved/extensive options.
10783  *
10784  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
10785  *   Added logic to control behavior of slash character swapping for
10786  *   windows/linux and skipping of first semicolon in calls to
10787  *   db_StringListToStringArray.
10788  *-------------------------------------------------------------------------
10789  */
10790 SILO_CALLBACK DBucdvar *
db_hdf5_GetUcdvar(DBfile * _dbfile,char const * name)10791 db_hdf5_GetUcdvar(DBfile *_dbfile, char const *name)
10792 {
10793     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
10794     static char         *me = "db_hdf5_GetUcdvar";
10795     char                *s = 0;
10796     hid_t               o=-1, attr=-1;
10797     int                 _objtype, i;
10798     DBucdvar_mt         m;
10799     DBucdvar            *uv=NULL;
10800 
10801     PROTECT {
10802         /* Open object and make sure it's a ucdvar */
10803         if ((o=H5Topen(dbfile->cwg, name))<0) {
10804             db_perror(name, E_NOTFOUND, me);
10805             UNWIND();
10806         }
10807         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
10808             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
10809             H5Aclose(attr)<0) {
10810             db_perror(name, E_CALLFAIL, me);
10811             UNWIND();
10812         }
10813         if (DB_UCDVAR!=(DBObjectType)_objtype) {
10814             db_perror(name, E_CALLFAIL, me);
10815             UNWIND();
10816         }
10817 
10818         /* Read ucdvar data into memory */
10819         memset(&m, 0, sizeof m);
10820         if ((attr=H5Aopen_name(o, "silo"))<0 ||
10821             H5Aread(attr, DBucdvar_mt5, &m)<0 ||
10822             H5Aclose(attr)<0) {
10823             db_perror(name, E_CALLFAIL, me);
10824             UNWIND();
10825         }
10826 
10827         /* Create a ucdvar object and initialize meta data */
10828         if (NULL==(uv=DBAllocUcdvar())) return NULL;
10829         uv->name = BASEDUP(name);
10830         uv->meshname = OPTDUP(m.meshid);
10831         uv->cycle = m.cycle;
10832         uv->units = OPTDUP(m.units);
10833         uv->label = OPTDUP(m.label);
10834         uv->time = m.time;
10835         uv->dtime = m.dtime;
10836         if ((uv->datatype = db_hdf5_GetVarType(_dbfile, m.value[0])) < 0)
10837             uv->datatype = silo2silo_type(m.datatype);
10838         if (force_single_g) uv->datatype = DB_FLOAT;
10839         uv->nels = m.nels;
10840         uv->nvals = m.nvals;
10841         uv->ndims = m.ndims;
10842         uv->origin = m.origin;
10843         uv->centering = m.centering;
10844         uv->mixlen = m.mixlen;
10845         uv->use_specmf = m.use_specmf;
10846         uv->ascii_labels = m.ascii_labels;
10847         uv->guihide = m.guihide;
10848         uv->conserved = m.conserved;
10849         uv->extensive = m.extensive;
10850         db_SetMissingValueForGet(uv->missing_value, m.missing_value);
10851 
10852         /* If var is compressed, we need to do some work to decompress it */
10853         PrepareForUcdvarDecompression(_dbfile, name, uv->meshname?uv->meshname:"", m.value, m.nvals);
10854 
10855         /* Read the raw data */
10856         if (m.nvals>MAX_VARS) {
10857             db_perror(name, E_CALLFAIL, me);
10858             UNWIND();
10859         }
10860         if (SILO_Globals.dataReadMask & DBUVData && m.nvals)
10861         {
10862             uv->vals = (void **)calloc(m.nvals, sizeof(void*));
10863             if (m.mixlen) uv->mixvals = (void **)calloc(m.nvals, sizeof(void*));
10864             for (i=0; i<m.nvals; i++) {
10865                 uv->vals[i] = db_hdf5_comprd(dbfile, m.value[i], 0);
10866                 if (m.mixlen && m.mixed_value[i][0]) {
10867                     uv->mixvals[i] = db_hdf5_comprd(dbfile, m.mixed_value[i], 0);
10868                 }
10869             }
10870         }
10871 
10872         s = (char *)db_hdf5_comprd(dbfile, m.region_pnames, 1);
10873         if (s) uv->region_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
10874         FREE(s);
10875 
10876         H5Tclose(o);
10877 
10878     } CLEANUP {
10879         H5E_BEGIN_TRY {
10880             H5Aclose(attr);
10881             H5Tclose(o);
10882         } H5E_END_TRY;
10883         DBFreeUcdvar(uv);
10884     } END_PROTECT;
10885 
10886     return uv;
10887 }
10888 
10889 /*-------------------------------------------------------------------------
10890  * Function:    db_hdf5_PutFacelist
10891  *
10892  * Purpose:     Writes facelist information to a facelist object in the file.
10893  *
10894  * Return:      Success:        0
10895  *
10896  *              Failure:        -1
10897  *
10898  * Programmer:  Robb Matzke
10899  *              Thursday, April  1, 1999
10900  *
10901  * Modifications:
10902  *
10903  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
10904  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
10905  *-------------------------------------------------------------------------
10906  */
10907 SILO_CALLBACK int
db_hdf5_PutFacelist(DBfile * _dbfile,char const * name,int nfaces,int ndims,int const * nodelist,int lnodelist,int origin,int const * zoneno,int const * shapesize,int const * shapecnt,int nshapes,int const * types,int const * typelist,int ntypes)10908 db_hdf5_PutFacelist(
10909     DBfile *_dbfile,
10910     char const *name,
10911     int nfaces,
10912     int ndims,
10913     int const *nodelist,
10914     int lnodelist,
10915     int origin,
10916     int const *zoneno,
10917     int const *shapesize,
10918     int const *shapecnt,
10919     int nshapes,
10920     int const *types,
10921     int const *typelist,
10922     int ntypes
10923 )
10924 {
10925     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
10926     DBfacelist_mt       m;
10927 
10928     memset(&m, 0, sizeof m);
10929 
10930     PROTECT {
10931         /* Write variable arrays */
10932         if (lnodelist) {
10933             db_hdf5_compwr(dbfile, DB_INT, 1, &lnodelist, nodelist,
10934                 m.nodelist/*out*/, friendly_name(name, "_nodelist", 0));
10935         }
10936         if (3==ndims) {
10937             db_hdf5_compwr(dbfile, DB_INT, 1, &nshapes, shapecnt,
10938                 m.shapecnt/*out*/, friendly_name(name, "_shapecnt", 0));
10939             db_hdf5_compwr(dbfile, DB_INT, 1, &nshapes, shapesize,
10940                 m.shapesize/*out*/, friendly_name(name, "_shapesize", 0));
10941         }
10942         if (ntypes && typelist) {
10943             db_hdf5_compwr(dbfile, DB_INT, 1, &ntypes, typelist,
10944                 m.typelist/*out*/, friendly_name(name, "_typelist", 0));
10945         }
10946         if (ntypes && types) {
10947             db_hdf5_compwr(dbfile, DB_INT, 1, &nfaces, types,
10948                 m.types/*out*/, friendly_name(name, "_types", 0));
10949         }
10950         if (zoneno) {
10951             db_hdf5_compwr(dbfile, DB_INT, 1, &nfaces, zoneno,
10952                 m.zoneno/*out*/, friendly_name(name, "_zoneno", 0));
10953         }
10954 
10955         /* Build header in memory */
10956         m.ndims = ndims;
10957         m.nfaces = nfaces;
10958         m.nshapes = nshapes;
10959         m.ntypes = ntypes;
10960         m.lnodelist = lnodelist;
10961         m.origin = origin;
10962 
10963         /* Write header to file */
10964         STRUCT(DBfacelist) {
10965             if (m.ndims)        MEMBER_S(int, ndims);
10966             if (m.nfaces)       MEMBER_S(int, nfaces);
10967             if (m.nshapes)      MEMBER_S(int, nshapes);
10968             if (m.ntypes)       MEMBER_S(int, ntypes);
10969             if (m.lnodelist)    MEMBER_S(int, lnodelist);
10970             if (m.origin)       MEMBER_S(int, origin);
10971             MEMBER_S(str(m.nodelist), nodelist);
10972             MEMBER_S(str(m.shapecnt), shapecnt);
10973             MEMBER_S(str(m.shapesize), shapesize);
10974             MEMBER_S(str(m.typelist), typelist);
10975             MEMBER_S(str(m.types), types);
10976             MEMBER_S(str(m.zoneno), zoneno);
10977         } OUTPUT(dbfile, DB_FACELIST, name, &m);
10978 
10979     } CLEANUP {
10980         /*void*/
10981     } END_PROTECT;
10982     return 0;
10983 }
10984 
10985 /*-------------------------------------------------------------------------
10986  * Function:    db_hdf5_GetFacelist
10987  *
10988  * Purpose:     Reads a facelist object from the file.
10989  *
10990  * Return:      Success:        Ptr to a new facelist object.
10991  *
10992  *              Failure:        NULL
10993  *
10994  * Programmer:  Robb Matzke
10995  *              Thursday, April  1, 1999
10996  *
10997  * Modifications:
10998  *
10999  *  Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
11000  *  Added support for dataReadMask
11001  *
11002  *-------------------------------------------------------------------------
11003  */
11004 SILO_CALLBACK DBfacelist *
db_hdf5_GetFacelist(DBfile * _dbfile,char const * name)11005 db_hdf5_GetFacelist(DBfile *_dbfile, char const *name)
11006 {
11007     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11008     static char         *me = "db_hdf5_GetFacelist";
11009     hid_t               o=-1, attr=-1;
11010     int                 _objtype;
11011     DBfacelist_mt       m;
11012     DBfacelist          *fl=NULL;
11013 
11014     PROTECT {
11015         /* Open object and make sure it's a facelist */
11016         if ((o=H5Topen(dbfile->cwg, name))<0) {
11017             db_perror(name, E_NOTFOUND, me);
11018             UNWIND();
11019         }
11020         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
11021             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
11022             H5Aclose(attr)<0) {
11023             db_perror(name, E_CALLFAIL, me);
11024             UNWIND();
11025         }
11026         if (DB_FACELIST!=(DBObjectType)_objtype) {
11027             db_perror(name, E_CALLFAIL, me);
11028             UNWIND();
11029         }
11030 
11031         /* Read facelist data into memory */
11032         memset(&m, 0, sizeof m);
11033         if ((attr=H5Aopen_name(o, "silo"))<0 ||
11034             H5Aread(attr, DBfacelist_mt5, &m)<0 ||
11035             H5Aclose(attr)<0) {
11036             db_perror(name, E_CALLFAIL, me);
11037             UNWIND();
11038         }
11039 
11040         /* Create a facelist object and initialize meta data */
11041         if (NULL==(fl=DBAllocFacelist())) return NULL;
11042         fl->ndims = m.ndims;
11043         fl->nfaces = m.nfaces;
11044         fl->origin = m.origin;
11045         fl->lnodelist = m.lnodelist;
11046         fl->nshapes = m.nshapes;
11047         fl->ntypes = m.ntypes;
11048 
11049         /* Read the raw data */
11050         if (SILO_Globals.dataReadMask & DBFacelistInfo)
11051         {
11052             fl->nodelist = (int *)db_hdf5_comprd(dbfile, m.nodelist, 1);
11053             fl->shapecnt = (int *)db_hdf5_comprd(dbfile, m.shapecnt, 1);
11054             fl->shapesize = (int *)db_hdf5_comprd(dbfile, m.shapesize, 1);
11055             fl->typelist = (int *)db_hdf5_comprd(dbfile, m.typelist, 1);
11056             fl->types = (int *)db_hdf5_comprd(dbfile, m.types, 1);
11057             fl->zoneno = (int *)db_hdf5_comprd(dbfile, m.zoneno, 1);
11058         }
11059 
11060         H5Tclose(o);
11061     } CLEANUP {
11062         H5E_BEGIN_TRY {
11063             H5Aclose(attr);
11064             H5Tclose(o);
11065         } H5E_END_TRY;
11066         DBFreeFacelist(fl);
11067     } END_PROTECT;
11068 
11069     return fl;
11070 }
11071 
11072 /*-------------------------------------------------------------------------
11073  * Function:    PrepareForZonelistCompression
11074  *
11075  * Purpose:     Does some small work to prepare for possible zonelist
11076  *              compression
11077  *
11078  * Return:      Success:        ALLOW_MESH_COMPRESSION
11079  *
11080  *              Failure:        0
11081  *
11082  * HZIP supports only 2D quad meshes and 3D hex meshes.
11083  *
11084  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
11085  *-------------------------------------------------------------------------
11086  */
11087 static int
PrepareForZonelistCompression(DBfile_hdf5 * dbfile,char const * name,int origin,int ndims,int nshapes,int const * shapetype,int const * shapesize,int const * shapecnt,int const * nodelist)11088 PrepareForZonelistCompression(DBfile_hdf5 *dbfile, char const *name,
11089     int origin, int ndims, int nshapes, int const *shapetype, int const *shapesize,
11090     int const *shapecnt, int const *nodelist)
11091 {
11092 	int i;
11093     int ntopo = 0, zncnt = 0;
11094 
11095     if (nshapes == 0) return 0;
11096     if (SILO_Globals.compressionParams == 0) return 0;
11097 
11098     zncnt = shapecnt[0];
11099 #ifdef HAVE_HZIP
11100 
11101     if (shapetype)
11102     {
11103         /* hzip supports only quad/hex meshes */
11104         if (shapetype[0] == DB_ZONETYPE_QUAD)
11105         {
11106             ntopo = 2;
11107             for (i = 1; i < nshapes; i++)
11108             {
11109                 zncnt += shapecnt[i];
11110                 if (shapetype[i] != DB_ZONETYPE_QUAD)
11111                     return 0;
11112             }
11113         }
11114         else if (shapetype[0] == DB_ZONETYPE_HEX)
11115         {
11116             ntopo = 3;
11117             for (i = 1; i < nshapes; i++)
11118             {
11119                 zncnt += shapecnt[i];
11120                 if (shapetype[i] != DB_ZONETYPE_HEX)
11121                     return 0;
11122             }
11123         }
11124         else
11125         {
11126             return 0;
11127         }
11128     }
11129     else
11130     {
11131         if (ndims == 2)
11132         {
11133             ntopo = 2;
11134             for (i = 0; i < nshapes; i++)
11135             {
11136                 zncnt += shapecnt[i];
11137                 if (shapesize[i] != 4)
11138                     return 0;
11139             }
11140         }
11141         else if (ndims == 3)
11142         {
11143             ntopo = 3;
11144             for (i = 0; i < nshapes; i++)
11145             {
11146                 zncnt += shapecnt[i];
11147                 if (shapesize[i] != 8)
11148                     return 0;
11149             }
11150         }
11151         else
11152         {
11153             return 0;
11154         }
11155     }
11156 
11157     db_hdf5_hzip_clear_params();
11158     db_hdf5_hzip_params.iszl = 1;
11159     db_hdf5_hzip_params.zlname = name;
11160     db_hdf5_hzip_params.dbfile = dbfile;
11161     RegisterNodelist(dbfile, name, 0, ntopo, zncnt, origin, nodelist);
11162     return ALLOW_MESH_COMPRESSION;
11163 
11164 #else
11165 
11166     return 0;
11167 
11168 #endif
11169 }
11170 
11171 /*-------------------------------------------------------------------------
11172  * Function:    db_hdf5_PutZonelist
11173  *
11174  * Purpose:     Writes a zonelist to a file.
11175  *
11176  * Return:      Success:        0
11177  *
11178  *              Failure:        -1
11179  *
11180  * Programmer:  Robb Matzke
11181  *              Thursday, April  1, 1999
11182  *
11183  * Modifications:
11184  *
11185  *-------------------------------------------------------------------------
11186  */
11187 SILO_CALLBACK int
db_hdf5_PutZonelist(DBfile * _dbfile,char const * name,int nzones,int ndims,int const * nodelist,int lnodelist,int origin,int const * shapesize,int const * shapecnt,int nshapes)11188 db_hdf5_PutZonelist(DBfile *_dbfile, char const *name, int nzones, int ndims,
11189                     int const *nodelist, int lnodelist, int origin, int const *shapesize,
11190                     int const *shapecnt, int nshapes)
11191 {
11192     db_hdf5_PutZonelist2(_dbfile, name, nzones, ndims, nodelist, lnodelist,
11193                          origin, 0, 0, NULL, shapesize, shapecnt, nshapes,
11194                          NULL);
11195     return 0;
11196 }
11197 
11198 /*-------------------------------------------------------------------------
11199  * Function:    db_hdf5_PutZonelist2
11200  *
11201  * Purpose:     Write a ucd zonelist object into the file.
11202  *
11203  * Return:      Success:        0
11204  *
11205  *              Failure:        -1
11206  *
11207  * Programmer:  Robb Matzke
11208  *              Monday, April 12, 1999
11209  *
11210  * Modifications:
11211  *              Robb Matzke, 1999-07-13
11212  *              Added an option list argument to duplicate changes to the
11213  *              PDB driver. Added gzoneno property.
11214  *
11215  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
11216  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
11217  *
11218  *   Mark C. Miller, Thu Jul 17 15:20:31 PDT 2008
11219  *   Added code to prepare for possible compression. Changed call to
11220  *   write nodelist to use compwrz.
11221  *
11222  *   Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
11223  *   Changed how long long global node/zone numbers are supported
11224  *   from a int (bool), "llong_gnode|zoneno" to an int holding
11225  *   the actual datatype. The type is assumed int if it its
11226  *   value is zero or it does not exist. Otherwise, the type is
11227  *   is whatever is stored in gnznodtype member.
11228  *-------------------------------------------------------------------------
11229  */
11230 SILO_CALLBACK int
db_hdf5_PutZonelist2(DBfile * _dbfile,char const * name,int nzones,int ndims,int const * nodelist,int lnodelist,int origin,int lo_offset,int hi_offset,int const * shapetype,int const * shapesize,int const * shapecnt,int nshapes,DBoptlist const * optlist)11231 db_hdf5_PutZonelist2(DBfile *_dbfile, char const *name, int nzones, int ndims,
11232                      int const *nodelist, int lnodelist, int origin,
11233                      int lo_offset, int hi_offset, int const *shapetype,
11234                      int const *shapesize, int const *shapecnt, int nshapes,
11235                      DBoptlist const *optlist)
11236 {
11237     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11238     DBzonelist_mt       m;
11239     int                 compressionFlags;
11240 
11241     memset(&m, 0, sizeof m);
11242     PROTECT {
11243         /* Set global options */
11244         memset(&_uzl, 0, sizeof _uzl);
11245         db_ProcessOptlist(DB_ZONELIST, optlist);
11246 
11247         /* Prepare for possible compression of zonelist */
11248         compressionFlags = PrepareForZonelistCompression(dbfile,
11249             name, origin, ndims, nshapes, shapetype, shapesize, shapecnt, nodelist);
11250 
11251         /* Write variable arrays (currently only support compression of nodelist) */
11252         db_hdf5_compwrz(dbfile, DB_INT, 1, &lnodelist, nodelist,
11253             m.nodelist/*out*/, friendly_name(name,"_nodelist", 0), compressionFlags);
11254         db_hdf5_compwr(dbfile, DB_INT, 1, &nshapes, shapecnt,
11255             m.shapecnt/*out*/, friendly_name(name,"_shapecnt", 0));
11256         db_hdf5_compwr(dbfile, DB_INT, 1, &nshapes, shapesize,
11257             m.shapesize/*out*/, friendly_name(name,"_shapesize", 0));
11258         db_hdf5_compwr(dbfile, DB_INT, 1, &nshapes, shapetype,
11259             m.shapetype/*out*/, friendly_name(name,"_shapetype", 0));
11260 
11261         if (_uzl._llong_gzoneno)
11262             db_hdf5_compwr(dbfile, DB_LONG_LONG, 1, &nzones, _uzl._gzoneno,
11263                 m.gzoneno/*out*/, friendly_name(name,"_gzoneno", 0));
11264         else
11265             db_hdf5_compwr(dbfile, DB_INT, 1, &nzones, _uzl._gzoneno,
11266                 m.gzoneno/*out*/, friendly_name(name,"_gzoneno", 0));
11267 
11268         if (_uzl._ghost_zone_labels)
11269         {
11270             db_hdf5_compwr(dbfile, DB_CHAR, 1, &nzones, _uzl._ghost_zone_labels,
11271                 m.ghost_zone_labels/*out*/, friendly_name(name,"_ghost_zone_labels", 0));
11272         }
11273 
11274         if (_uzl._alt_zonenum_vars) {
11275             int len, nvars=-1; char *tmp;
11276             DBStringArrayToStringList((char const * const *)_uzl._alt_zonenum_vars, nvars, &tmp, &len);
11277             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
11278                 m.alt_zonenum_vars/*out*/, friendly_name(name, "_alt_zonenum_vars",0));
11279             FREE(tmp);
11280         }
11281 
11282         /* Build header in memory */
11283         m.ndims = ndims;
11284         m.nzones = nzones;
11285         m.nshapes = nshapes;
11286         m.lnodelist = lnodelist;
11287         m.origin = origin;
11288         m.lo_offset = lo_offset;
11289         m.hi_offset = hi_offset;
11290         m.gnznodtype = _uzl._llong_gzoneno?DB_LONG_LONG:0;
11291 
11292         /* Write header to file */
11293         STRUCT(DBzonelist) {
11294             if (m.ndims)        MEMBER_S(int, ndims);
11295             if (m.nzones)       MEMBER_S(int, nzones);
11296             if (m.nshapes)      MEMBER_S(int, nshapes);
11297             if (m.lnodelist)    MEMBER_S(int, lnodelist);
11298             if (m.origin)       MEMBER_S(int, origin);
11299             if (m.lo_offset)    MEMBER_S(int, lo_offset);
11300             if (m.hi_offset)    MEMBER_S(int, hi_offset);
11301             MEMBER_S(str(m.nodelist), nodelist);
11302             MEMBER_S(str(m.shapecnt), shapecnt);
11303             MEMBER_S(str(m.shapesize), shapesize);
11304             MEMBER_S(str(m.shapetype), shapetype);
11305             MEMBER_S(str(m.gzoneno), gzoneno);
11306             if (m.gnznodtype)   MEMBER_S(int, gnznodtype);
11307             MEMBER_S(str(m.ghost_zone_labels), ghost_zone_labels);
11308             MEMBER_S(str(m.alt_zonenum_vars), alt_zonenum_vars);
11309         } OUTPUT(dbfile, DB_ZONELIST, name, &m);
11310 
11311     } CLEANUP {
11312         /*void*/
11313     } END_PROTECT;
11314     return 0;
11315 }
11316 
11317 /*-------------------------------------------------------------------------
11318  * Function:    db_hdf5_PutPHZonelist
11319  *
11320  * Purpose:     Write a DBphzonelist object into the file.
11321  *
11322  * Return:      Success:        0
11323  *
11324  *              Failure:        -1
11325  *
11326  * Programmer:  Robb Matzke
11327  *              Monday, April 12, 1999
11328  *
11329  * Modifications:
11330  *              Robb Matzke, 1999-07-13
11331  *              Added an option list argument to duplicate changes to the
11332  *              PDB driver. Added gzoneno property.
11333  *
11334  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
11335  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
11336  *
11337  *   Mark C. Miller, Fri Nov 13 15:26:38 PST 2009
11338  *   Add support for long long global node/zone numbers.
11339  *
11340  *   Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
11341  *   Changed how long long global node/zone numbers are supported
11342  *   from a int (bool), "llong_gnode|zoneno" to an int holding
11343  *   the actual datatype. The type is assumed int if it its
11344  *   value is zero or it does not exist. Otherwise, the type is
11345  *   is whatever is stored in gnznodtype member.
11346  *-------------------------------------------------------------------------
11347  */
11348 SILO_CALLBACK int
db_hdf5_PutPHZonelist(DBfile * _dbfile,char const * name,int nfaces,int const * nodecnt,int lnodelist,int const * nodelist,char const * extface,int nzones,int const * facecnt,int lfacelist,int const * facelist,int origin,int lo_offset,int hi_offset,DBoptlist const * optlist)11349 db_hdf5_PutPHZonelist(DBfile *_dbfile, char const *name,
11350                       int nfaces, int const *nodecnt, int lnodelist, int const *nodelist,
11351                       char const *extface,
11352                       int nzones, int const *facecnt, int lfacelist, int const *facelist,
11353                       int origin, int lo_offset, int hi_offset,
11354                       DBoptlist const *optlist)
11355 {
11356     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11357     DBphzonelist_mt       m;
11358 
11359     memset(&m, 0, sizeof m);
11360     PROTECT {
11361         /* Set global options */
11362         memset(&_phzl, 0, sizeof _phzl);
11363         db_ProcessOptlist(DB_PHZONELIST, optlist);
11364 
11365         /* Write variable arrays */
11366         db_hdf5_compwr(dbfile, DB_INT, 1, &nfaces, nodecnt,
11367             m.nodecnt/*out*/, friendly_name(name,"_nodecnt", 0));
11368         db_hdf5_compwr(dbfile, DB_INT, 1, &lnodelist, nodelist,
11369             m.nodelist/*out*/, friendly_name(name,"_nodelist", 0));
11370         db_hdf5_compwr(dbfile, DB_CHAR, 1, &nfaces, extface,
11371             m.extface/*out*/, friendly_name(name,"_extface", 0));
11372         db_hdf5_compwr(dbfile, DB_INT, 1, &nzones, facecnt,
11373             m.facecnt/*out*/, friendly_name(name,"_facecnt", 0));
11374         db_hdf5_compwr(dbfile, DB_INT, 1, &lfacelist, facelist,
11375             m.facelist/*out*/, friendly_name(name,"_facelist", 0));
11376         if (_phzl._llong_gzoneno)
11377             db_hdf5_compwr(dbfile, DB_LONG_LONG, 1, &nzones, _phzl._gzoneno,
11378                 m.gzoneno/*out*/, friendly_name(name,"_gzoneno", 0));
11379         else
11380             db_hdf5_compwr(dbfile, DB_INT, 1, &nzones, _phzl._gzoneno,
11381                 m.gzoneno/*out*/, friendly_name(name,"_gzoneno", 0));
11382 
11383         if (_phzl._ghost_zone_labels)
11384         {
11385             db_hdf5_compwr(dbfile, DB_CHAR, 1, &nzones, _phzl._ghost_zone_labels,
11386                 m.ghost_zone_labels/*out*/, friendly_name(name,"_ghost_zone_labels", 0));
11387         }
11388 
11389         if (_phzl._alt_zonenum_vars) {
11390             int len, nvars=-1; char *tmp;
11391             DBStringArrayToStringList((char const * const *)_phzl._alt_zonenum_vars, nvars, &tmp, &len);
11392             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
11393                 m.alt_zonenum_vars/*out*/, friendly_name(name, "_alt_zonenum_vars",0));
11394             FREE(tmp);
11395         }
11396 
11397         /* Build header in memory */
11398         m.nfaces = nfaces;
11399         m.lnodelist = lnodelist;
11400         m.nzones = nzones;
11401         m.lfacelist = lfacelist;
11402         m.origin = origin;
11403         m.lo_offset = lo_offset;
11404         m.hi_offset = hi_offset;
11405         m.gnznodtype = _phzl._llong_gzoneno?DB_LONG_LONG:0;
11406 
11407         /* Write header to file */
11408         STRUCT(DBphzonelist) {
11409             if (m.nfaces)       MEMBER_S(int, nfaces);
11410             if (m.lnodelist)    MEMBER_S(int, lnodelist);
11411             if (m.nzones)       MEMBER_S(int, nzones);
11412             if (m.lfacelist)    MEMBER_S(int, lfacelist);
11413             if (m.origin)       MEMBER_S(int, origin);
11414             if (m.lo_offset)    MEMBER_S(int, lo_offset);
11415             if (m.hi_offset)    MEMBER_S(int, hi_offset);
11416             MEMBER_S(str(m.nodecnt), nodecnt);
11417             MEMBER_S(str(m.nodelist), nodelist);
11418             MEMBER_S(str(m.extface), extface);
11419             MEMBER_S(str(m.facecnt), facecnt);
11420             MEMBER_S(str(m.facelist), facelist);
11421             MEMBER_S(str(m.gzoneno), gzoneno);
11422             if (m.gnznodtype)   MEMBER_S(int, gnznodtype);
11423             MEMBER_S(str(m.ghost_zone_labels), ghost_zone_labels);
11424         } OUTPUT(dbfile, DB_PHZONELIST, name, &m);
11425 
11426     } CLEANUP {
11427         /*void*/
11428     } END_PROTECT;
11429     return 0;
11430 }
11431 
11432 /*-------------------------------------------------------------------------
11433  * Function:    PrepareForZonelistDecompression
11434  *
11435  * Purpose:     Does some small work to prepare for possible zonelist
11436  *              de compression
11437  *
11438  * Programmer:  Mark C. Miller, Thu Jul 17 15:07:21 PDT 2008
11439  *-------------------------------------------------------------------------
11440  */
11441 static void
PrepareForZonelistDecompression(DBfile_hdf5 * dbfile,char const * zlname,char const * meshname,int origin)11442 PrepareForZonelistDecompression(DBfile_hdf5* dbfile, char const *zlname,
11443     char const *meshname, int origin)
11444 {
11445 #ifdef HAVE_HZIP
11446     db_hdf5_hzip_clear_params();
11447     db_hdf5_hzip_params.dbfile = dbfile;
11448     db_hdf5_hzip_params.iszl = 1;
11449     db_hdf5_hzip_params.zlname = zlname;
11450     db_hdf5_hzip_params.meshname = meshname;
11451     db_hdf5_hzip_params.zlorigin = origin;
11452 #endif
11453 }
11454 
11455 /*-------------------------------------------------------------------------
11456  * Function:    db_hdf5_GetZonelist
11457  *
11458  * Purpose:     Reads a zonelist object from the file
11459  *
11460  * Return:      Success:        Ptr to new zonelist
11461  *
11462  *              Failure:        NULL
11463  *
11464  * Programmer:  Robb Matzke
11465  *              Friday, April  2, 1999
11466  *
11467  * Modifications:
11468  *              Robb Matzke, 1999-07-14
11469  *              Added the `gzoneno' property to mirror changes made to the
11470  *              PDB driver.
11471  *
11472  *              Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
11473  *              Made it behave identically to PDB driver (for better or
11474  *              worse) when called from GetUcdmesh. Added support for
11475  *              dataReadMask
11476  *
11477  *              Mark C. Miller, Thu Jul 17 15:21:35 PDT 2008
11478  *              Added code to prepare for possible zonelist decompression.
11479  *
11480  *              Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
11481  *              Changed how long long global node/zone numbers are supported
11482  *              from a int (bool), "llong_gnode|zoneno" to an int holding
11483  *              the actual datatype. The type is assumed int if it its
11484  *              value is zero or it does not exist. Otherwise, the type is
11485  *              is whatever is stored in gnznodtype member.
11486  *
11487  *              Mark C. Miller, Tue Jul 27 23:20:27 PDT 2010
11488  *              Removed odd-ball logic to summarily set min/max index to
11489  *              zero unless 'calledFromGetUcdmesh'
11490  *-------------------------------------------------------------------------
11491  */
11492 SILO_CALLBACK DBzonelist *
db_hdf5_GetZonelist(DBfile * _dbfile,char const * name)11493 db_hdf5_GetZonelist(DBfile *_dbfile, char const *name)
11494 {
11495     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11496     static char         *me = "db_hdf5_GetZonelist";
11497     hid_t               o=-1, attr=-1;
11498     int                 _objtype;
11499     DBzonelist_mt       m;
11500     DBzonelist          *zl=NULL;
11501 
11502     PROTECT {
11503         /* Open object and make sure it's a zonelist */
11504         if ((o=H5Topen(dbfile->cwg, name))<0) {
11505             db_perror(name, E_NOTFOUND, me);
11506             UNWIND();
11507         }
11508         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
11509             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
11510             H5Aclose(attr)<0) {
11511             db_perror(name, E_CALLFAIL, me);
11512             UNWIND();
11513         }
11514         if (DB_ZONELIST!=(DBObjectType)_objtype) {
11515             db_perror(name, E_CALLFAIL, me);
11516             UNWIND();
11517         }
11518 
11519         /* Read zonelist data into memory */
11520         memset(&m, 0, sizeof m);
11521         if ((attr=H5Aopen_name(o, "silo"))<0 ||
11522             H5Aread(attr, DBzonelist_mt5, &m)<0 ||
11523             H5Aclose(attr)<0) {
11524             db_perror(name, E_CALLFAIL, me);
11525             UNWIND();
11526         }
11527 
11528         /* Create a zonelist object and initialize meta data */
11529         if (NULL==(zl=DBAllocZonelist())) return NULL;
11530         zl->ndims = m.ndims;
11531         zl->nzones = m.nzones;
11532         zl->nshapes = m.nshapes;
11533         zl->lnodelist = m.lnodelist;
11534         zl->origin = m.origin;
11535         zl->min_index = m.lo_offset;
11536         zl->max_index = m.nzones - m.hi_offset - 1;
11537 
11538         /* Prepare for possible zonelist decompression */
11539         PrepareForZonelistDecompression(dbfile, name,
11540             calledFromGetUcdmesh, zl->origin);
11541 
11542         /* Read the raw data */
11543         if (SILO_Globals.dataReadMask & DBZonelistInfo)
11544         {
11545             zl->shapecnt = (int *)db_hdf5_comprd(dbfile, m.shapecnt, 1);
11546             zl->shapesize = (int *)db_hdf5_comprd(dbfile, m.shapesize, 1);
11547             zl->shapetype = (int *)db_hdf5_comprd(dbfile, m.shapetype, 1);
11548             zl->nodelist = (int *)db_hdf5_comprd(dbfile, m.nodelist, 1);
11549         }
11550         if (SILO_Globals.dataReadMask & DBZonelistGlobZoneNo)
11551             zl->gzoneno = db_hdf5_comprd(dbfile, m.gzoneno, 1);
11552         zl->gnznodtype = m.gnznodtype?m.gnznodtype:DB_INT;
11553         if (SILO_Globals.dataReadMask & DBZonelistGhostZoneLabels)
11554             zl->ghost_zone_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_zone_labels, 1);
11555 
11556         /* alternate zone number variables */
11557         {
11558             int nvars = -1;
11559             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_zonenum_vars, 1);
11560             if (tmpnames)
11561                 zl->alt_zonenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
11562             FREE(tmpnames);
11563         }
11564 
11565         H5Tclose(o);
11566     } CLEANUP {
11567         H5E_BEGIN_TRY {
11568             H5Aclose(attr);
11569             H5Tclose(o);
11570         } H5E_END_TRY;
11571         DBFreeZonelist(zl);
11572     } END_PROTECT;
11573 
11574     return zl;
11575 }
11576 
11577 /*-------------------------------------------------------------------------
11578  * Function:    db_hdf5_GetPHZonelist
11579  *
11580  * Purpose:     Reads a DBphzonelist object from the file
11581  *
11582  * Return:      Success:        Ptr to new DBphzonelist
11583  *
11584  *              Failure:        NULL
11585  *
11586  * Programmer:  Robb Matzke
11587  *              Friday, April  2, 1999
11588  *
11589  * Modifications:
11590  *              Robb Matzke, 1999-07-14
11591  *              Added the `gzoneno' property to mirror changes made to the
11592  *              PDB driver.
11593  *
11594  *  Mark C. Miller, Wed Jan 27 10:37:25 PST 2010
11595  *  Added missing initialization of gnznodtype
11596  *-------------------------------------------------------------------------
11597  */
11598 SILO_CALLBACK DBphzonelist *
db_hdf5_GetPHZonelist(DBfile * _dbfile,char const * name)11599 db_hdf5_GetPHZonelist(DBfile *_dbfile, char const *name)
11600 {
11601     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11602     static char         *me = "db_hdf5_GetPHZonelist";
11603     hid_t               o=-1, attr=-1;
11604     int                 _objtype;
11605     DBphzonelist_mt       m;
11606     DBphzonelist          *phzl=NULL;
11607 
11608     PROTECT {
11609         /* Open object and make sure it's a phzonelist */
11610         if ((o=H5Topen(dbfile->cwg, name))<0) {
11611             db_perror(name, E_NOTFOUND, me);
11612             UNWIND();
11613         }
11614         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
11615             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
11616             H5Aclose(attr)<0) {
11617             db_perror(name, E_CALLFAIL, me);
11618             UNWIND();
11619         }
11620         if (DB_PHZONELIST!=(DBObjectType)_objtype) {
11621             db_perror(name, E_CALLFAIL, me);
11622             UNWIND();
11623         }
11624 
11625         /* Read phzonelist data into memory */
11626         memset(&m, 0, sizeof m);
11627         if ((attr=H5Aopen_name(o, "silo"))<0 ||
11628             H5Aread(attr, DBphzonelist_mt5, &m)<0 ||
11629             H5Aclose(attr)<0) {
11630             db_perror(name, E_CALLFAIL, me);
11631             UNWIND();
11632         }
11633 
11634         /* Create a phzonelist object and initialize meta data */
11635         if (NULL==(phzl=DBAllocPHZonelist())) return NULL;
11636         phzl->nfaces = m.nfaces;
11637         phzl->lnodelist = m.lnodelist;
11638         phzl->nzones = m.nzones;
11639         phzl->lfacelist = m.lfacelist;
11640         phzl->origin = m.origin;
11641         phzl->lo_offset = m.lo_offset;
11642         phzl->hi_offset = m.hi_offset;
11643         phzl->gnznodtype = m.gnznodtype?m.gnznodtype:DB_INT;
11644 
11645         if (SILO_Globals.dataReadMask & DBZonelistInfo)
11646         {
11647             phzl->nodecnt = (int *)db_hdf5_comprd(dbfile, m.nodecnt, 1);
11648             phzl->nodelist = (int *)db_hdf5_comprd(dbfile, m.nodelist, 1);
11649             phzl->extface = (char *)db_hdf5_comprd(dbfile, m.extface, 1);
11650             phzl->facecnt = (int *)db_hdf5_comprd(dbfile, m.facecnt, 1);
11651             phzl->facelist = (int  *)db_hdf5_comprd(dbfile, m.facelist, 1);
11652         }
11653         if (SILO_Globals.dataReadMask & DBZonelistGlobZoneNo)
11654             phzl->gzoneno = db_hdf5_comprd(dbfile, m.gzoneno, 1);
11655         if (SILO_Globals.dataReadMask & DBZonelistGhostZoneLabels)
11656             phzl->ghost_zone_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_zone_labels, 1);
11657 
11658         /* alternate zone number variables */
11659         {
11660             int nvars = -1;
11661             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_zonenum_vars, 1);
11662             if (tmpnames)
11663                 phzl->alt_zonenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
11664             FREE(tmpnames);
11665         }
11666 
11667         H5Tclose(o);
11668     } CLEANUP {
11669         H5E_BEGIN_TRY {
11670             H5Aclose(attr);
11671             H5Tclose(o);
11672         } H5E_END_TRY;
11673         DBFreePHZonelist(phzl);
11674     } END_PROTECT;
11675 
11676     return phzl;
11677 }
11678 
11679 /*-------------------------------------------------------------------------
11680  * Function:    db_hdf5_PutMaterial
11681  *
11682  * Purpose:     Write a material object to the file
11683  *
11684  * Return:      Success:        0
11685  *
11686  *              Failure:        -1
11687  *
11688  * Programmer:  Robb Matzke
11689  *              Friday, April  2, 1999
11690  *
11691  * Modifications:
11692  *
11693  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
11694  *   Added support for dataReadMask. Added warning regarding missing
11695  *   material name functionality
11696  *
11697  *   Mark C. Miller, August 9, 2004
11698  *   Added code to output optional material names
11699  *
11700  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
11701  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
11702  *
11703  *   Mark C. Miller, Thu Feb 11 09:40:10 PST 2010
11704  *   Set global values in _ma to zero after use.
11705  *-------------------------------------------------------------------------
11706  */
11707 SILO_CALLBACK int
db_hdf5_PutMaterial(DBfile * _dbfile,char const * name,char const * mname,int nmat,int const * matnos,int const * matlist,int const * dims,int ndims,int const * mix_next,int const * mix_mat,int const * mix_zone,void const * mix_vf,int mixlen,int datatype,DBoptlist const * optlist)11708 db_hdf5_PutMaterial(
11709     DBfile *_dbfile,
11710     char const *name,
11711     char const *mname,
11712     int nmat,
11713     int const *matnos,
11714     int const *matlist,
11715     int const *dims,
11716     int ndims,
11717     int const *mix_next,
11718     int const *mix_mat,
11719     int const *mix_zone,
11720     void const *mix_vf,
11721     int mixlen,
11722     int datatype,
11723     DBoptlist const *optlist
11724 )
11725 {
11726     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11727     DBmaterial_mt       m;
11728     int                 i, nels, is_empty = 1;
11729     char               *s = NULL;
11730 
11731     for (i = 0; i < ndims; i++)
11732     {
11733         if (dims[i] > 0)
11734         {
11735             is_empty = 0;
11736             break;
11737         }
11738     }
11739 
11740     memset(&m, 0, sizeof m);
11741     PROTECT {
11742         /* Set global options */
11743         db_ProcessOptlist(DB_MATERIAL, optlist);
11744         nels = 1;
11745         for (i=0; i<ndims; i++) nels *= dims[i];
11746 
11747         /* Write raw data arrays */
11748         if (!is_empty)
11749             db_hdf5_compwr(dbfile, DB_INT, 1, &nels, matlist, m.matlist/*out*/, friendly_name(name,"_matlist", 0));
11750         db_hdf5_compwr(dbfile, DB_INT, 1, &nmat, matnos,
11751             m.matnos/*out*/, friendly_name(name,"_matnos", 0));
11752         if (!is_empty && mixlen>0) {
11753             db_hdf5_compwr(dbfile, datatype, 1, &mixlen, mix_vf,
11754                 m.mix_vf/*out*/, friendly_name(name,"_mix_vf", 0));
11755             db_hdf5_compwr(dbfile, DB_INT, 1, &mixlen, mix_next,
11756                 m.mix_next/*out*/, friendly_name(name,"_mix_next", 0));
11757             db_hdf5_compwr(dbfile, DB_INT, 1, &mixlen, mix_mat,
11758                 m.mix_mat/*out*/, friendly_name(name,"_mix_mat", 0));
11759             db_hdf5_compwr(dbfile, DB_INT, 1, &mixlen, mix_zone,
11760                 m.mix_zone/*out*/, friendly_name(name,"_mix_zone", 0));
11761         }
11762 
11763         if (_ma._matnames != NULL) {
11764             int len;
11765             DBStringArrayToStringList((char const * const *)_ma._matnames, nmat, &s, &len);
11766             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.matnames/*out*/,
11767                 friendly_name(name, "_matnames", 0));
11768             FREE(s);
11769             _ma._matnames = NULL;
11770         }
11771 
11772         if (_ma._matcolors != NULL) {
11773             int len;
11774             DBStringArrayToStringList((char const * const *)_ma._matcolors, nmat, &s, &len);
11775             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.matcolors/*out*/,
11776                 friendly_name(name,"_matcolors", 0));
11777             FREE(s);
11778             _ma._matcolors = NULL;
11779         }
11780 
11781         /* Build header in memory */
11782         m.ndims = ndims;
11783         m.nmat = nmat;
11784         m.mixlen = mixlen;
11785         m.origin = _ma._origin;
11786         m.major_order = _ma._majororder;
11787         m.allowmat0 = _ma._allowmat0;
11788         m.guihide = _ma._guihide;
11789         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
11790         strcpy(m.meshid, OPT(mname));
11791         for (nels=1, i=0; i<ndims; i++) {
11792             m.dims[i] = dims[i];
11793         }
11794 
11795         /* Write header to file */
11796         STRUCT(DBmaterial) {
11797             if (m.dims)         MEMBER_S(int, ndims);
11798             if (m.nmat)         MEMBER_S(int, nmat);
11799             if (m.mixlen)       MEMBER_S(int, mixlen);
11800             if (m.origin)       MEMBER_S(int, origin);
11801             if (m.major_order)  MEMBER_S(int, major_order);
11802             if (m.datatype)     MEMBER_S(int, datatype);
11803             if (m.allowmat0)    MEMBER_S(int, allowmat0);
11804             if (m.guihide)      MEMBER_S(int, guihide);
11805             MEMBER_3(int, dims);
11806             MEMBER_S(str(m.meshid), meshid);
11807             MEMBER_S(str(m.matlist), matlist);
11808             MEMBER_S(str(m.matnos), matnos);
11809             MEMBER_S(str(m.mix_vf), mix_vf);
11810             MEMBER_S(str(m.mix_next), mix_next);
11811             MEMBER_S(str(m.mix_mat), mix_mat);
11812             MEMBER_S(str(m.mix_zone), mix_zone);
11813             MEMBER_S(str(m.matnames), matnames);
11814             MEMBER_S(str(m.matcolors), matcolors);
11815         } OUTPUT(dbfile, DB_MATERIAL, name, &m);
11816 
11817         FREE(s);
11818 
11819     } CLEANUP {
11820         FREE(s);
11821     } END_PROTECT;
11822     return 0;
11823 }
11824 
11825 /*-------------------------------------------------------------------------
11826  * Function:    db_hdf5_GetMaterial
11827  *
11828  * Purpose:     Reads a material object from the file.
11829  *
11830  * Return:      Success:        Ptr to new material
11831  *
11832  *              Failure:        NULL
11833  *
11834  * Programmer:  Robb Matzke
11835  *              Friday, April  2, 1999
11836  *
11837  * Modifications:
11838  *
11839  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
11840  *   Made it set correct datatype. Added support for dataReadMask
11841  *
11842  *   Mark C. Miller, August 9, 2004
11843  *   Added code to read in optional material names
11844  *
11845  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
11846  *   Added logic to control behavior of slash character swapping for
11847  *   windows/linux and skipping of first semicolon in calls to
11848  *   db_StringListToStringArray.
11849  *-------------------------------------------------------------------------
11850  */
11851 SILO_CALLBACK DBmaterial *
db_hdf5_GetMaterial(DBfile * _dbfile,char const * name)11852 db_hdf5_GetMaterial(DBfile *_dbfile, char const *name)
11853 {
11854     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11855     static char         *me = "db_hdf5_GetMaterial";
11856     hid_t               o=-1, attr=-1;
11857     int                 _objtype, i, nels;
11858     DBmaterial_mt       m;
11859     DBmaterial          *ma=NULL;
11860     char                *s=NULL;
11861 
11862     PROTECT {
11863         /* Open object and make sure it's a material */
11864         if ((o=H5Topen(dbfile->cwg, name))<0) {
11865             db_perror(name, E_NOTFOUND, me);
11866             UNWIND();
11867         }
11868         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
11869             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
11870             H5Aclose(attr)<0) {
11871             db_perror(name, E_CALLFAIL, me);
11872             UNWIND();
11873         }
11874         if (DB_MATERIAL!=(DBObjectType)_objtype) {
11875             db_perror(name, E_CALLFAIL, me);
11876             UNWIND();
11877         }
11878 
11879         /* Read meta data into memory */
11880         memset(&m, 0, sizeof m);
11881         if ((attr=H5Aopen_name(o, "silo"))<0 ||
11882             H5Aread(attr, DBmaterial_mt5, &m)<0 ||
11883             H5Aclose(attr)<0) {
11884             db_perror(name, E_CALLFAIL, me);
11885             UNWIND();
11886         }
11887 
11888         /* Create object and initialize meta data */
11889         if (NULL==(ma=DBAllocMaterial())) return NULL;
11890         ma->name = BASEDUP(name);
11891         ma->meshname = OPTDUP(m.meshid);
11892         ma->ndims = m.ndims;
11893         ma->origin = m.origin;
11894         ma->major_order = m.major_order;
11895         ma->allowmat0 = m.allowmat0;
11896         ma->guihide = m.guihide;
11897         ma->nmat = m.nmat;
11898         ma->mixlen = m.mixlen;
11899         if ((ma->datatype = db_hdf5_GetVarType(_dbfile, m.mix_vf)) < 0)
11900             ma->datatype = DB_DOUBLE;  /* PDB driver assumes double */
11901         if (force_single_g) ma->datatype = DB_FLOAT;
11902         for (nels=1, i=0; i<m.ndims; i++) {
11903             ma->dims[i] = m.dims[i];
11904             ma->stride[i] = nels;
11905             nels *= m.dims[i];
11906         }
11907 
11908         /* Read the raw data */
11909         if (SILO_Globals.dataReadMask & DBMatMatlist)
11910             ma->matlist = (int *)db_hdf5_comprd(dbfile, m.matlist, 1);
11911         if (SILO_Globals.dataReadMask & DBMatMatnos)
11912             ma->matnos = (int *)db_hdf5_comprd(dbfile, m.matnos, 1);
11913         if (SILO_Globals.dataReadMask & DBMatMixList)
11914         {
11915             ma->mix_vf = db_hdf5_comprd(dbfile, m.mix_vf, 0);
11916             ma->mix_next = (int *)db_hdf5_comprd(dbfile, m.mix_next, 1);
11917             ma->mix_mat = (int *)db_hdf5_comprd(dbfile, m.mix_mat, 1);
11918             ma->mix_zone = (int *)db_hdf5_comprd(dbfile, m.mix_zone, 1);
11919         }
11920         if (SILO_Globals.dataReadMask & DBMatMatnames)
11921         {
11922             s = (char *)db_hdf5_comprd(dbfile, m.matnames, 1);
11923             if (s) ma->matnames = DBStringListToStringArray(s, &(ma->nmat), !skipFirstSemicolon);
11924             FREE(s);
11925         }
11926         if (SILO_Globals.dataReadMask & DBMatMatcolors)
11927         {
11928             s = (char *)db_hdf5_comprd(dbfile, m.matcolors, 1);
11929             if (s) ma->matcolors = DBStringListToStringArray(s, &(ma->nmat), !skipFirstSemicolon);
11930             FREE(s);
11931         }
11932 
11933         H5Tclose(o);
11934         FREE(s);
11935 
11936     } CLEANUP {
11937         H5E_BEGIN_TRY {
11938             H5Aclose(attr);
11939             H5Tclose(o);
11940         } H5E_END_TRY;
11941         DBFreeMaterial(ma);
11942         FREE(s);
11943     } END_PROTECT;
11944 
11945     return ma;
11946 }
11947 
11948 /*-------------------------------------------------------------------------
11949  * Function:    db_hdf5_PutMatspecies
11950  *
11951  * Purpose:     Write a matspecies object to the file.
11952  *
11953  * Return:      Success:        0
11954  *
11955  *              Failure:        -1
11956  *
11957  * Programmer:  Robb Matzke
11958  *              Tuesday, April  6, 1999
11959  *
11960  * Modifications:
11961  *              Robb Matzke, 1999-07-13
11962  *              Removed the `origin' property to duplicate changes made to
11963  *              the PDB driver.
11964  *
11965  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
11966  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
11967  *
11968  *   Mark C. Miller, Tue Sep  8 15:40:51 PDT 2009
11969  *   Added names and colors for species.
11970  *
11971  *   Mark C. Miller, Thu Feb 11 09:40:10 PST 2010
11972  *   Set global values in _ms to zero after use.
11973  *-------------------------------------------------------------------------
11974  */
11975 SILO_CALLBACK int
db_hdf5_PutMatspecies(DBfile * _dbfile,char const * name,char const * matname,int nmat,int const * nmatspec,int const * speclist,int const * dims,int ndims,int nspecies_mf,void const * species_mf,int const * mix_speclist,int mixlen,int datatype,DBoptlist const * optlist)11976 db_hdf5_PutMatspecies(DBfile *_dbfile, char const *name, char const *matname, int nmat,
11977                       int const *nmatspec, int const *speclist, int const *dims, int ndims,
11978                       int nspecies_mf, void const *species_mf, int const *mix_speclist,
11979                       int mixlen, int datatype, DBoptlist const *optlist)
11980 {
11981     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
11982     DBmatspecies_mt     m;
11983     char               *s = NULL;
11984     int                 i, nels, nstrs = 0, is_empty = 1;
11985 
11986     for (i = 0; i < ndims; i++)
11987     {
11988         if (dims[i] > 0)
11989         {
11990             is_empty = 0;
11991             break;
11992         }
11993     }
11994 
11995     memset(&m, 0, sizeof m);
11996     PROTECT {
11997         /* Set global options */
11998         db_ProcessOptlist(DB_MATSPECIES, optlist);
11999 
12000         /* Write raw data arrays */
12001         nels = 1;
12002         for (i=0; i<ndims; i++) nels *= dims[i];
12003         if (!is_empty)
12004             db_hdf5_compwr(dbfile, DB_INT, 1, &nels, speclist, m.speclist/*out*/, friendly_name(name,"_speclist", 0));
12005         db_hdf5_compwr(dbfile, DB_INT, 1, &nmat, nmatspec, m.nmatspec/*out*/,
12006             friendly_name(name,"_nmatspec", 0));
12007         if (!is_empty)
12008         {
12009             db_hdf5_compwr(dbfile, datatype, 1, &nspecies_mf, species_mf, m.species_mf/*out*/,
12010                 friendly_name(name,"_species_mf", 0));
12011             db_hdf5_compwr(dbfile, DB_INT, 1, &mixlen, mix_speclist, m.mix_speclist/*out*/,
12012                 friendly_name(name,"_mix_speclist", 0));
12013         }
12014 
12015         if (_ms._specnames != NULL) {
12016             int len;
12017             for (i = 0; i < nmat; i++)
12018                 nstrs += nmatspec[i];
12019             DBStringArrayToStringList((char const * const *)_ms._specnames, nstrs, &s, &len);
12020             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.specnames/*out*/,
12021                 friendly_name(name, "_species_names", 0));
12022             FREE(s);
12023             _ms._specnames = NULL;
12024         }
12025 
12026         if (_ms._speccolors != NULL) {
12027             int len;
12028             if (nstrs == 0)
12029             {
12030                 for (i = 0; i < nmat; i++)
12031                     nstrs += nmatspec[i];
12032             }
12033             DBStringArrayToStringList((char const * const *)_ms._speccolors, nstrs, &s, &len);
12034             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.speccolors/*out*/,
12035                 friendly_name(name,"_speccolors", 0));
12036             FREE(s);
12037             _ms._speccolors = NULL;
12038         }
12039 
12040         /* Build header in memory */
12041         m.ndims = ndims;
12042         m.nmat = nmat;
12043         m.nspecies_mf = nspecies_mf;
12044         m.mixlen = mixlen;
12045         m.major_order = _ms._majororder;
12046         m.guihide = _ms._guihide;
12047         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
12048         strcpy(m.matname, OPT(matname));
12049         for (i=0; i<ndims; i++) m.dims[i] = dims[i];
12050 
12051         /* Write header to file */
12052         STRUCT(DBmatspecies) {
12053             if (m.ndims)        MEMBER_S(int, ndims);
12054             if (m.nmat)         MEMBER_S(int, nmat);
12055             if (m.nspecies_mf)  MEMBER_S(int, nspecies_mf);
12056             if (m.mixlen)       MEMBER_S(int, mixlen);
12057             if (m.major_order)  MEMBER_S(int, major_order);
12058             if (m.datatype)     MEMBER_S(int, datatype);
12059             if (m.guihide)      MEMBER_S(int, guihide);
12060             MEMBER_3(int, dims);
12061             MEMBER_S(str(m.matname), matname);
12062             MEMBER_S(str(m.speclist), speclist);
12063             MEMBER_S(str(m.nmatspec), nmatspec);
12064             MEMBER_S(str(m.species_mf), species_mf);
12065             MEMBER_S(str(m.mix_speclist), mix_speclist);
12066             MEMBER_S(str(m.specnames), specnames);
12067             MEMBER_S(str(m.speccolors), speccolors);
12068         } OUTPUT(dbfile, DB_MATSPECIES, name, &m);
12069 
12070     } CLEANUP {
12071         /*void*/
12072     } END_PROTECT;
12073     return 0;
12074 }
12075 
12076 /*-------------------------------------------------------------------------
12077  * Function:    db_hdf5_GetMatspecies
12078  *
12079  * Purpose:     Reads a matspecies object from the file.
12080  *
12081  * Return:      Success:        Ptr to new matspecies object.
12082  *
12083  *              Failure:        NULL
12084  *
12085  * Programmer:  Robb Matzke
12086  *              Tuesday, April  6, 1999
12087  *
12088  * Modifications:
12089  *              Robb Matzke, 1999-07-13
12090  *              Removed the `origin' property, duplicating changes made to
12091  *              the PDB driver.
12092  *
12093  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
12094  *              Made it set correct datatype.
12095  *
12096  *              Mark C. Miller, Tue Sep  8 15:40:51 PDT 2009
12097  *              Added names and colors for species.
12098  *
12099  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
12100  *   Added logic to control behavior of slash character swapping for
12101  *   windows/linux and skipping of first semicolon in calls to
12102  *   db_StringListToStringArray.
12103  *-------------------------------------------------------------------------
12104  */
12105 SILO_CALLBACK DBmatspecies *
db_hdf5_GetMatspecies(DBfile * _dbfile,char const * name)12106 db_hdf5_GetMatspecies(DBfile *_dbfile, char const *name)
12107 {
12108     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
12109     static char         *me = "db_hdf5_GetMatspecies";
12110     hid_t               o=-1, attr=-1;
12111     int                 _objtype, i, nels, nstrs = 0;
12112     DBmatspecies_mt     m;
12113     DBmatspecies        *ms=NULL;
12114     char                *s=NULL;
12115 
12116     PROTECT {
12117         /* Open object and make sure it's a matspecies */
12118         if ((o=H5Topen(dbfile->cwg, name))<0) {
12119             db_perror(name, E_NOTFOUND, me);
12120             UNWIND();
12121         }
12122         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
12123             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
12124             H5Aclose(attr)<0) {
12125             db_perror(name, E_CALLFAIL, me);
12126             UNWIND();
12127         }
12128         if (DB_MATSPECIES!=(DBObjectType)_objtype) {
12129             db_perror(name, E_CALLFAIL, me);
12130             UNWIND();
12131         }
12132 
12133         /* Read meta data into memory */
12134         memset(&m, 0, sizeof m);
12135         if ((attr=H5Aopen_name(o, "silo"))<0 ||
12136             H5Aread(attr, DBmatspecies_mt5, &m)<0 ||
12137             H5Aclose(attr)<0) {
12138             db_perror(name, E_CALLFAIL, me);
12139             UNWIND();
12140         }
12141 
12142         /* Create object and initialize meta data */
12143         if (NULL==(ms=DBAllocMatspecies())) return NULL;
12144         ms->name = BASEDUP(name);
12145         ms->matname = OPTDUP(m.matname);
12146         ms->nmat = m.nmat;
12147         ms->ndims = m.ndims;
12148         ms->guihide = m.guihide;
12149         ms->major_order = m.major_order;
12150         ms->nspecies_mf = m.nspecies_mf;
12151         ms->mixlen = m.mixlen;
12152         if ((ms->datatype = db_hdf5_GetVarType(_dbfile, m.species_mf)) < 0)
12153             ms->datatype = silo2silo_type(m.datatype);
12154         if (force_single_g) ms->datatype = DB_FLOAT;
12155         for (i=0, nels=1; i<m.ndims; i++) {
12156             ms->dims[i] = m.dims[i];
12157             ms->stride[i] = nels;
12158             nels *= m.dims[i];
12159         }
12160 
12161         /* Read the raw data */
12162         ms->nmatspec = (int *)db_hdf5_comprd(dbfile, m.nmatspec, 1);
12163         ms->species_mf = db_hdf5_comprd(dbfile, m.species_mf, 0);
12164         ms->speclist = (int *)db_hdf5_comprd(dbfile, m.speclist, 1);
12165         ms->mix_speclist = (int *)db_hdf5_comprd(dbfile, m.mix_speclist, 1);
12166         if (ms->nmatspec && SILO_Globals.dataReadMask & DBMatMatnames)
12167         {
12168             for (i=0; i < ms->nmat; i++)
12169                 nstrs += ms->nmatspec[i];
12170             s = (char *)db_hdf5_comprd(dbfile, m.specnames, 1);
12171             if (s) ms->specnames = DBStringListToStringArray(s, &nstrs, !skipFirstSemicolon);
12172             FREE(s);
12173         }
12174         if (ms->nmatspec && SILO_Globals.dataReadMask & DBMatMatcolors)
12175         {
12176             if (nstrs == 0)
12177             {
12178                 for (i=0; i < ms->nmat; i++)
12179                     nstrs += ms->nmatspec[i];
12180             }
12181             s = (char *)db_hdf5_comprd(dbfile, m.speccolors, 1);
12182             if (s) ms->speccolors = DBStringListToStringArray(s, &nstrs, !skipFirstSemicolon);
12183             FREE(s);
12184         }
12185 
12186         H5Aclose(attr);
12187         H5Tclose(o);
12188 
12189     } CLEANUP {
12190         H5E_BEGIN_TRY {
12191             H5Aclose(attr);
12192             H5Tclose(o);
12193         } H5E_END_TRY;
12194         DBFreeMatspecies(ms);
12195     } END_PROTECT;
12196     return ms;
12197 }
12198 
12199 /*-------------------------------------------------------------------------
12200  * Function:    db_hdf5_PutMultimesh
12201  *
12202  * Purpose:     Write a multi-block mesh object to the file.
12203  *
12204  * Return:      Success:        0
12205  *
12206  *              Failure:        -1
12207  *
12208  * Programmer:  Robb Matzke
12209  *              Friday, April  2, 1999
12210  *
12211  * Modifications:
12212  *              Robb Matzke, 1999-07-13
12213  *              Added `ngroups', `blockorigin', and `grouporigin' to
12214  *              duplicate changes to the PDB driver.
12215  *
12216  *              Eric Brugger, 2004-03-12
12217  *              Split the declaration and initialization of sizes
12218  *              into multiple statements so that it compiles on old
12219  *              sgi compilers.
12220  *
12221  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
12222  *              Added call to reset global data
12223  *
12224  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
12225  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
12226  *
12227  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
12228  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
12229  *
12230  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
12231  *   Refactored logic to handle time, dtime and cycle to a new method,
12232  *   db_hdf5_handle_ctdt().
12233  *
12234  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
12235  *   Added support for namescheme/empty_list options for multi-block objs.
12236  *-------------------------------------------------------------------------
12237  */
12238 SILO_CALLBACK int
db_hdf5_PutMultimesh(DBfile * _dbfile,char const * name,int nmesh,char const * const * meshnames,int const * meshtypes,DBoptlist const * optlist)12239 db_hdf5_PutMultimesh(DBfile *_dbfile, char const *name, int nmesh,
12240                      char const *const *meshnames, int const *meshtypes,
12241                      DBoptlist const *optlist)
12242 {
12243     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
12244     DBmultimesh_mt      m;
12245     int                 i, len;
12246     char                *s=NULL;
12247     char                *t=NULL;
12248 
12249     memset(&m, 0, sizeof m);
12250     PROTECT {
12251         /* Set global options */
12252         db_ResetGlobalData_MultiMesh();
12253         db_ProcessOptlist(DB_MULTIMESH, optlist);
12254 
12255         /* hack to maintain backward compatibility with pdb driver */
12256         db_hdf5_handle_ctdt(dbfile, _mm._time_set, _mm._time,
12257             _mm._dtime_set, _mm._dtime, _mm._cycle);
12258 
12259         /*
12260          * Create a character string which is a semi-colon separated list of
12261          * mesh names.
12262          */
12263         if (meshnames)
12264         {
12265             for (i=len=0; i<nmesh; i++) len += strlen(meshnames[i])+1;
12266             s = (char *)malloc(len+1);
12267             for (i=len=0; i<nmesh; i++) {
12268                 if (i) s[len++] = ';';
12269                 strcpy(s+len, meshnames[i]);
12270                 len += strlen(meshnames[i]);
12271             }
12272             len++; /*count null*/
12273             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s,
12274                 m.meshnames/*out*/, friendly_name(name,"_meshnames", 0));
12275         }
12276 
12277         /* Write raw data arrays */
12278         if (meshtypes)
12279             db_hdf5_compwr(dbfile, DB_INT, 1, &nmesh, meshtypes,
12280                 m.meshtypes/*out*/, friendly_name(name,"_meshtypes", 0));
12281         if (_mm._extents && _mm._extentssize) {
12282             int sizes[2];
12283             sizes[0] = nmesh;
12284             sizes[1] = _mm._extentssize;
12285             db_hdf5_compwr(dbfile, DB_DOUBLE, 2, sizes, _mm._extents,
12286                 m.extents/*out*/, friendly_name(name,"_extents",0));
12287         }
12288         if (_mm._zonecounts) {
12289             db_hdf5_compwr(dbfile, DB_INT, 1, &nmesh, _mm._zonecounts,
12290                 m.zonecounts/*out*/, friendly_name(name,"_zoneconts",0));
12291         }
12292         if (_mm._has_external_zones) {
12293             db_hdf5_compwr(dbfile, DB_INT, 1, &nmesh, _mm._has_external_zones,
12294                 m.has_external_zones/*out*/, friendly_name(name,"_has_external_zones",0));
12295         }
12296         if (_mm._lgroupings > 0 && _mm._groupings != NULL) {
12297             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._lgroupings, _mm._groupings,
12298                 m.groupings/*out*/, friendly_name(name,"_groupings",0));
12299         }
12300         if (_mm._lgroupings > 0 && _mm._groupnames != NULL) {
12301            DBStringArrayToStringList((char const * const *)_mm._groupnames,
12302                            _mm._lgroupings, &t, &len);
12303            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, t,
12304                 m.groupnames/*out*/, friendly_name(name,"_groupnames",0));
12305            FREE(t);
12306         }
12307         if (_mm._file_ns)
12308         {
12309            len = strlen(_mm._file_ns)+1;
12310            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._file_ns,
12311                 m.file_ns_name/*out*/, friendly_name(name,"_file_ns",0));
12312         }
12313         if (_mm._block_ns)
12314         {
12315            len = strlen(_mm._block_ns)+1;
12316            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._block_ns,
12317                 m.block_ns_name/*out*/, friendly_name(name,"_block_ns",0));
12318         }
12319         if (_mm._empty_list && _mm._empty_cnt>0) {
12320             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._empty_cnt, _mm._empty_list,
12321                 m.empty_list/*out*/, friendly_name(name,"_empty_list",0));
12322         }
12323 
12324         if (_mm._alt_nodenum_vars) {
12325             int len, nvars=-1; char *tmp;
12326             DBStringArrayToStringList((char const * const *)_mm._alt_nodenum_vars, nvars, &tmp, &len);
12327             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
12328                 m.alt_nodenum_vars/*out*/, friendly_name(name, "_alt_nodenum_vars",0));
12329             FREE(tmp);
12330         }
12331 
12332         if (_mm._alt_zonenum_vars) {
12333             int len, nvars=-1; char *tmp;
12334             DBStringArrayToStringList((char const * const *)_mm._alt_zonenum_vars, nvars, &tmp, &len);
12335             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
12336                 m.alt_zonenum_vars/*out*/, friendly_name(name, "_alt_zonenum_vars",0));
12337             FREE(tmp);
12338         }
12339 
12340         /* Initialize meta data */
12341         m.nblocks = nmesh;
12342         m.cycle = _mm._cycle;
12343         m.time = _mm._time;
12344         m.dtime = _mm._dtime;
12345         m.ngroups = _mm._ngroups;
12346         m.blockorigin = _mm._blockorigin;
12347         m.grouporigin = _mm._grouporigin;
12348         m.extentssize = _mm._extentssize;
12349         m.guihide = _mm._guihide;
12350         m.lgroupings = _mm._lgroupings;
12351         m.tv_connectivity = _mm._tv_connectivity;
12352         m.disjoint_mode = _mm._disjoint_mode;
12353         m.topo_dim = _mm._topo_dim;
12354         strcpy(m.mrgtree_name, OPT(_mm._mrgtree_name));
12355         m.block_type = _mm._block_type;
12356         m.empty_cnt = _mm._empty_cnt;
12357         m.repr_block_idx = _mm._repr_block_idx;
12358 
12359         /* Write meta data to file */
12360         STRUCT(DBmultimesh) {
12361             if (m.nblocks)      MEMBER_S(int, nblocks);
12362             if (m.cycle)        MEMBER_S(int, cycle);
12363             if (m.ngroups)      MEMBER_S(int, ngroups);
12364             if (m.blockorigin)  MEMBER_S(int, blockorigin);
12365             if (m.grouporigin)  MEMBER_S(int, grouporigin);
12366             if (_mm._time_set)  MEMBER_S(float, time);
12367             if (_mm._dtime_set) MEMBER_S(double, dtime);
12368             if (m.extentssize)  MEMBER_S(int, extentssize);
12369             if (m.guihide)      MEMBER_S(int, guihide);
12370             MEMBER_S(str(m.meshtypes), meshtypes);
12371             MEMBER_S(str(m.meshnames), meshnames);
12372             MEMBER_S(str(m.extents), extents);
12373             MEMBER_S(str(m.zonecounts), zonecounts);
12374             MEMBER_S(str(m.has_external_zones), has_external_zones);
12375             if (m.lgroupings)   MEMBER_S(int, lgroupings);
12376             MEMBER_S(str(m.groupings), groupings);
12377             MEMBER_S(str(m.groupnames), groupnames);
12378             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
12379             if (m.tv_connectivity) MEMBER_S(int, tv_connectivity);
12380             if (m.disjoint_mode)   MEMBER_S(int, disjoint_mode);
12381             if (m.topo_dim)     MEMBER_S(int, topo_dim);
12382             MEMBER_S(str(m.file_ns_name), file_ns_name);
12383             MEMBER_S(str(m.block_ns_name), block_ns_name);
12384             if (m.block_type)   MEMBER_S(int, block_type);
12385             MEMBER_S(str(m.empty_list), empty_list);
12386             if (m.empty_cnt)   MEMBER_S(int, empty_cnt);
12387             if (m.repr_block_idx)   MEMBER_S(int, repr_block_idx);
12388             MEMBER_S(str(m.alt_nodenum_vars), alt_nodenum_vars);
12389             MEMBER_S(str(m.alt_zonenum_vars), alt_zonenum_vars);
12390         } OUTPUT(dbfile, DB_MULTIMESH, name, &m);
12391 
12392         /* Free resources */
12393         FREE(s);
12394 
12395     } CLEANUP {
12396         FREE(s);
12397     } END_PROTECT;
12398     return 0;
12399 }
12400 
12401 /*-------------------------------------------------------------------------
12402  * Function:    db_hdf5_GetMultimesh
12403  *
12404  * Purpose:     Reads a multimesh object from the file.
12405  *
12406  * Return:      Success:        Ptr to new multimesh object
12407  *
12408  *              Failure:        NULL
12409  *
12410  * Programmer:  Robb Matzke
12411  *              Tuesday, April  6, 1999
12412  *
12413  * Modifications:
12414  *              Robb Matzke, 1999-07-13
12415  *              Added `ngroups', `blockorigin', and `grouporigin' to
12416  *              duplicate changes to the PDB driver.
12417  *
12418  *              Mark C. Miller, Wed Feb  2 07:52:22 PST 2005
12419  *              Added code to temporarily disable force single when
12420  *              reading extents
12421  *
12422  *   Mark C. Miller, Tue Feb 15 14:53:29 PST 2005
12423  *   Changed how force_single was handled to deal with possible throw
12424  *
12425  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
12426  *   Added logic to control behavior of slash character swapping for
12427  *   windows/linux and skipping of first semicolon in calls to
12428  *   db_StringListToStringArray.
12429  *
12430  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
12431  *   Added support for namescheme/empty_list options for multi-block objs.
12432  *-------------------------------------------------------------------------
12433  */
12434 SILO_CALLBACK DBmultimesh *
db_hdf5_GetMultimesh(DBfile * _dbfile,char const * name)12435 db_hdf5_GetMultimesh(DBfile *_dbfile, char const *name)
12436 {
12437     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
12438     static char         *me = "db_hdf5_GetMultimesh";
12439     hid_t               o=-1, attr=-1;
12440     int                 _objtype;
12441     DBmultimesh_mt      m;
12442     DBmultimesh         *mm=NULL;
12443     char                *t=NULL;
12444     char                *meshnames=NULL;
12445 
12446     PROTECT {
12447         /* Open object and make sure it's a multimesh */
12448         if ((o=H5Topen(dbfile->cwg, name))<0) {
12449             db_perror(name, E_NOTFOUND, me);
12450             UNWIND();
12451         }
12452         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
12453             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
12454             H5Aclose(attr)<0) {
12455             db_perror(name, E_CALLFAIL, me);
12456             UNWIND();
12457         }
12458         if (DB_MULTIMESH!=(DBObjectType)_objtype) {
12459             db_perror(name, E_CALLFAIL, me);
12460             UNWIND();
12461         }
12462 
12463         /* Read meta data into memory */
12464         memset(&m, 0, sizeof m);
12465         if ((attr=H5Aopen_name(o, "silo"))<0 ||
12466             H5Aread(attr, DBmultimesh_mt5, &m)<0 ||
12467             H5Aclose(attr)<0) {
12468             db_perror(name, E_CALLFAIL, me);
12469             UNWIND();
12470         }
12471 
12472         /* Create object and initialize meta data */
12473         if (NULL==(mm=DBAllocMultimesh(0))) return NULL;
12474         mm->nblocks = m.nblocks;
12475         mm->ngroups = m.ngroups;
12476         mm->blockorigin = m.blockorigin;
12477         mm->grouporigin = m.grouporigin;
12478         mm->extentssize = m.extentssize;
12479         mm->guihide = m.guihide;
12480         mm->lgroupings = m.lgroupings;
12481         mm->mrgtree_name = OPTDUP(m.mrgtree_name);
12482         mm->tv_connectivity = m.tv_connectivity;
12483         mm->disjoint_mode = m.disjoint_mode;
12484         /* The value we store to the file for 'topo_dim' member is
12485            designed such that zero indicates a value that was NOT
12486            specified in the file. Since zero is a valid topological
12487            dimension, when we store topo_dim to a file, we always
12488            add 1. So, we have to subtract it here. This was implemented
12489            for multimeshes in 4.7 and so is handled correctly for
12490            them in all cases. */
12491         mm->topo_dim = m.topo_dim - 1;
12492         mm->repr_block_idx = m.repr_block_idx - 1;
12493 
12494         /* Read the raw data */
12495         if (mm->extentssize>0)
12496            mm->extents = (double*)db_hdf5_comprd(dbfile, m.extents, 1);
12497         mm->zonecounts =  (int *)db_hdf5_comprd(dbfile, m.zonecounts, 1);
12498         mm->has_external_zones =  (int *)db_hdf5_comprd(dbfile, m.has_external_zones, 1);
12499         mm->meshtypes = (int *)db_hdf5_comprd(dbfile, m.meshtypes, 1);
12500         meshnames = (char *)db_hdf5_comprd(dbfile, m.meshnames, 1);
12501         db_StringListToStringArrayMBOpt(meshnames, &(mm->meshnames), &(mm->meshnames_alloc), m.nblocks);
12502         mm->groupings =  (int *)db_hdf5_comprd(dbfile, m.groupings, 1);
12503         t = (char *)db_hdf5_comprd(dbfile, m.groupnames, 1);
12504         if (t) mm->groupnames = DBStringListToStringArray(t, &(mm->lgroupings), !skipFirstSemicolon);
12505         FREE(t);
12506         mm->file_ns =  (char *)db_hdf5_comprd(dbfile, m.file_ns_name, 1);
12507         mm->block_ns =  (char *)db_hdf5_comprd(dbfile, m.block_ns_name, 1);
12508         mm->block_type = m.block_type;
12509         mm->empty_list =  (int* )db_hdf5_comprd(dbfile, m.empty_list, 1);
12510         mm->empty_cnt = m.empty_cnt;
12511 
12512         /* alternate node number variables */
12513         {
12514             int nvars = -1;
12515             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_nodenum_vars, 1);
12516             if (tmpnames)
12517                 mm->alt_nodenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
12518             FREE(tmpnames);
12519         }
12520 
12521         /* alternate zone number variables */
12522         {
12523             int nvars = -1;
12524             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_zonenum_vars, 1);
12525             if (tmpnames)
12526                 mm->alt_zonenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
12527             FREE(tmpnames);
12528         }
12529 
12530         H5Tclose(o);
12531 
12532     } CLEANUP {
12533         H5E_BEGIN_TRY {
12534             H5Aclose(attr);
12535             H5Tclose(o);
12536         } H5E_END_TRY;
12537         DBFreeMultimesh(mm);
12538         FREE(t);
12539     } END_PROTECT;
12540     return mm;
12541 }
12542 
12543 
12544 /*-------------------------------------------------------------------------
12545  * Function:    db_hdf5_PutMultimeshadj
12546  *
12547  * Purpose:     Write a multi-block mesh adjacency object to the file.
12548  *
12549  * Return:      Success:        0
12550  *
12551  *              Failure:        -1
12552  *
12553  * Programmer:  Mark C. Miller
12554  *              Thursday, September 8, 2005
12555  *
12556  * Modifcations:
12557  *
12558  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
12559  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
12560  *
12561  *   Mark C. Miller, Sat Oct 18 08:22:18 PDT 2008
12562  *   Added patch from Sean Ahern where the write of the zonelists was
12563  *   actually referring to the nodelists array.
12564  *
12565  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
12566  *   Refactored logic to handle time, dtime and cycle to a new method,
12567  *   db_hdf5_handle_ctdt().
12568  *
12569  *   Mark C. Miller, Sat Mar 27 10:51:48 PDT 2010
12570  *   Add missing call to H5Tclose(o). Wouldn't have detected this without
12571  *   changing close degree setting based on DBShowErrors setting.
12572  *-------------------------------------------------------------------------
12573  */
12574 SILO_CALLBACK int
db_hdf5_PutMultimeshadj(DBfile * _dbfile,char const * name,int nmesh,int const * meshtypes,int const * nneighbors,int const * neighbors,int const * back,int const * lnodelists,int const * const * nodelists,int const * lzonelists,int const * const * zonelists,DBoptlist const * optlist)12575 db_hdf5_PutMultimeshadj(DBfile *_dbfile, char const *name, int nmesh,
12576                   int const *meshtypes, int const *nneighbors,
12577                   int const *neighbors, int const *back,
12578                   int const *lnodelists, int const * const *nodelists,
12579                   int const *lzonelists, int const * const *zonelists,
12580                   DBoptlist const *optlist)
12581 {
12582     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
12583     DBmultimeshadj_mt   m;
12584     int                 i, len, lneighbors, zoff, noff;
12585     char                *s=NULL;
12586     hid_t               o=-1, attr=-1, nldset=-1, zldset=-1;
12587     hid_t               mtype=-1, fspace=-1, mspace=-1;
12588     static char         *me = "db_hdf5_PutMultimeshadj";
12589     int                 _objtype;
12590 
12591     memset(&m, 0, sizeof m);
12592 
12593     /* compute expected size of neighbors array */
12594     lneighbors = 0;
12595     for (i = 0; i < nmesh; i++)
12596        lneighbors += nneighbors[i];
12597 
12598     PROTECT {
12599 
12600        H5E_BEGIN_TRY {
12601            o = H5Topen(dbfile->cwg, name);
12602        } H5E_END_TRY;
12603 
12604        if (o >= 0)
12605        {
12606             /* Object exists, do some simple sanity checking */
12607             if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
12608                 H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
12609                 H5Aclose(attr)<0) {
12610                 db_perror((char*)name, E_CALLFAIL, me);
12611                 UNWIND();
12612             }
12613             if (DB_MULTIMESHADJ!=(DBObjectType)_objtype) {
12614                 db_perror("not a DBmultimeshadj object", E_BADARGS, me);
12615                 UNWIND();
12616             }
12617 
12618             /* Read meta data into memory */
12619             if ((attr=H5Aopen_name(o, "silo"))<0 ||
12620                 H5Aread(attr, DBmultimeshadj_mt5, &m)<0 ||
12621                 H5Aclose(attr)<0) {
12622                 db_perror((char*)name, E_CALLFAIL, me);
12623                 UNWIND();
12624             }
12625 
12626             /* should add correct sanity checks here */
12627 
12628             H5Tclose(o);
12629 
12630        }
12631        else
12632        {
12633 
12634            /* Object doesn't exist, allocate space in the file for the datasets */
12635            db_ResetGlobalData_MultiMesh();
12636            db_ProcessOptlist(DB_MULTIMESH, optlist);
12637 
12638            /* Initialize meta data */
12639            m.nblocks = nmesh;
12640            m.blockorigin = _mm._blockorigin;
12641            m.lneighbors = lneighbors;
12642 
12643            /* compute length of neighbors, back, lnodelists, nodelists,
12644               lzonelists, zonelists arrays */
12645            lneighbors = 0;
12646            for (i = 0; i < nmesh; i++)
12647                lneighbors += nneighbors[i];
12648 
12649            db_hdf5_compwr(dbfile, DB_INT, 1, &nmesh, (void*)meshtypes,
12650                m.meshtypes/*out*/, friendly_name(name, "_meshtypes",0));
12651            db_hdf5_compwr(dbfile, DB_INT, 1, &nmesh, (void*)nneighbors,
12652                m.nneighbors/*out*/, friendly_name(name,"_nneighbors",0));
12653            db_hdf5_compwr(dbfile, DB_INT, 1, &lneighbors, (void*)neighbors,
12654                m.neighbors/*out*/, friendly_name(name,"_neighbors",0));
12655            if (back)
12656            {
12657                db_hdf5_compwr(dbfile, DB_INT, 1, &lneighbors, (void*)back,
12658                    m.back/*out*/, friendly_name(name,"_back",0));
12659            }
12660            if (lnodelists)
12661            {
12662                db_hdf5_compwr(dbfile, DB_INT, 1, &lneighbors, (void*)lnodelists,
12663                    m.lnodelists/*out*/, friendly_name(name,"_lnodelists",0));
12664            }
12665            if (lzonelists)
12666            {
12667                db_hdf5_compwr(dbfile, DB_INT, 1, &lneighbors, (void*)lzonelists,
12668                    m.lzonelists/*out*/, friendly_name(name,"_lzonelists",0));
12669            }
12670 
12671            /* All object components up to here are invariant and *should*
12672               be identical in repeated calls. Now, handle the parts of the
12673               object that can vary from call to call. Reserve space for
12674               the entire nodelists and/or zonelists arrays */
12675 
12676            if (lnodelists && nodelists) {
12677 
12678                /* compute total length of nodelists array */
12679                len = 0;
12680                for (i = 0; i < lneighbors; i++)
12681                    len += lnodelists[i];
12682                m.totlnodelists = len;
12683 
12684                /* reserve space for the nodelists array in the file */
12685                /* negative rank means to reserve space */
12686                if (db_hdf5_compwr(dbfile, DB_INT, -1, &len, NULL,
12687                        m.nodelists/*out*/, friendly_name(name,"_nodelists",0))<0) {
12688                   db_perror ("db_hdf5_compwr", E_CALLFAIL, me) ;
12689                   UNWIND();
12690                }
12691            }
12692 
12693            if (lzonelists && zonelists) {
12694 
12695                /* compute total length of nodelists array */
12696                len = 0;
12697                for (i = 0; i < lneighbors; i++)
12698                    len += lzonelists[i];
12699                m.totlzonelists = len;
12700 
12701                /* reserve space for the zonelists array in the file */
12702                /* negative rank means to reserve space */
12703                if (db_hdf5_compwr(dbfile, DB_INT, -1, &len, NULL,
12704                        m.zonelists/*out*/, friendly_name(name, "_zonelists",0))<0) {
12705                   db_perror ("db_hdf5_compwr", E_CALLFAIL, me) ;
12706                   UNWIND();
12707                }
12708            }
12709 
12710            /* hack to maintain backward compatibility with pdb driver */
12711            db_hdf5_handle_ctdt(dbfile, _mm._time_set, _mm._time,
12712                _mm._dtime_set, _mm._dtime, _mm._cycle);
12713 
12714            /* Write meta data to file */
12715            STRUCT(DBmultimeshadj) {
12716                MEMBER_S(int, nblocks);
12717                MEMBER_S(int, blockorigin);
12718                MEMBER_S(int, lneighbors);
12719                if (m.totlnodelists) MEMBER_S(int, totlnodelists);
12720                if (m.totlzonelists) MEMBER_S(int, totlzonelists);
12721                MEMBER_S(str(m.meshtypes), meshtypes);
12722                MEMBER_S(str(m.nneighbors), nneighbors);
12723                MEMBER_S(str(m.neighbors), neighbors);
12724                if (m.back[0]) MEMBER_S(str(m.back), back);
12725                if (m.lnodelists[0]) MEMBER_S(str(m.lnodelists), lnodelists);
12726                if (m.nodelists[0]) MEMBER_S(str(m.nodelists), nodelists);
12727                if (m.lzonelists[0]) MEMBER_S(str(m.lzonelists), lzonelists);
12728                if (m.zonelists[0]) MEMBER_S(str(m.zonelists), zonelists);
12729            } OUTPUT(dbfile, DB_MULTIMESHADJ, name, &m);
12730        }
12731 
12732        if (m.nodelists[0] &&
12733            (nldset = H5Dopen(dbfile->cwg, m.nodelists)) < 0) {
12734            db_perror((char*)name, E_CALLFAIL, me);
12735            UNWIND();
12736        }
12737 
12738        if (m.zonelists[0] &&
12739            (zldset = H5Dopen(dbfile->cwg, m.zonelists)) < 0) {
12740            db_perror((char*)name, E_CALLFAIL, me);
12741            UNWIND();
12742        }
12743 
12744        if ((mtype=silom2hdfm_type(DB_INT))<0) {
12745            db_perror("datatype", E_BADARGS, me);
12746            UNWIND();
12747        }
12748 
12749        /* Ok, now write contents of nodelists and/or zonelists */
12750        noff = 0;
12751        zoff = 0;
12752        for (i = 0; i < lneighbors; i++)
12753        {
12754           hsize_t ds_size[H5S_MAX_RANK];
12755 
12756           if (nodelists && lnodelists)
12757           {
12758              if (nodelists[i] && lnodelists[i])
12759              {
12760                 int offset = noff;
12761                 int length = lnodelists[i];
12762                 int stride = 1;
12763 
12764                 /* Build the file space selection */
12765                 if ((fspace=build_fspace(nldset, 1, &offset, &length, &stride,
12766                                         ds_size/*out*/))<0) {
12767                    db_perror("file data space", E_CALLFAIL, me);
12768                    UNWIND();
12769                }
12770 
12771                /* Build the memory data space */
12772                if ((mspace=H5Screate_simple(1, ds_size, NULL))<0) {
12773                    db_perror("memory data space", E_CALLFAIL, me);
12774                    UNWIND();
12775                }
12776 
12777                /* Write data */
12778                if (H5Dwrite(nldset, mtype, mspace, fspace, H5P_DEFAULT, nodelists[i])<0) {
12779                    db_perror("partial write", E_CALLFAIL, me);
12780                    UNWIND();
12781                }
12782 
12783                /* Close everything */
12784                H5Sclose(fspace);
12785                H5Sclose(mspace);
12786              }
12787              noff += lnodelists[i];
12788           }
12789 
12790           if (zonelists && lzonelists)
12791           {
12792              if (zonelists[i] && lzonelists[i])
12793              {
12794                 int offset = zoff;
12795                 int length = lzonelists[i];
12796                 int stride = 1;
12797 
12798                /* Build the file space selection */
12799                if ((fspace=build_fspace(zldset, 1, &offset, &length, &stride,
12800                                         ds_size/*out*/))<0) {
12801                    db_perror("file data space", E_CALLFAIL, me);
12802                    UNWIND();
12803                }
12804 
12805                /* Build the memory data space */
12806                if ((mspace=H5Screate_simple(1, ds_size, NULL))<0) {
12807                    db_perror("memory data space", E_CALLFAIL, me);
12808                    UNWIND();
12809                }
12810 
12811                /* Write data */
12812                if (H5Dwrite(zldset, mtype, mspace, fspace, H5P_DEFAULT, zonelists[i])<0) {
12813                    db_perror("partial write", E_CALLFAIL, me);
12814                    UNWIND();
12815                }
12816 
12817                /* Close everything */
12818                H5Sclose(fspace);
12819                H5Sclose(mspace);
12820 
12821              }
12822              zoff += lzonelists[i];
12823           }
12824        }
12825 
12826        if (nldset != -1)
12827            H5Dclose(nldset);
12828        if (zldset != -1)
12829            H5Dclose(zldset);
12830 
12831     } CLEANUP {
12832     } END_PROTECT;
12833     return 0;
12834 }
12835 
12836 /*-------------------------------------------------------------------------
12837  * Function:    db_hdf5_GetMultimeshadj
12838  *
12839  * Purpose:     Reads a multimesh adjacency object from the file.
12840  *
12841  * Return:      Success:        Ptr to new multimesh adjacency object
12842  *
12843  *              Failure:        NULL
12844  *
12845  * Programmer:  Mark C. Miller
12846  *              Thursday, September 8, 2005
12847  *-------------------------------------------------------------------------
12848  */
12849 SILO_CALLBACK DBmultimeshadj *
db_hdf5_GetMultimeshadj(DBfile * _dbfile,char const * name,int nmesh,int const * block_map)12850 db_hdf5_GetMultimeshadj(DBfile *_dbfile, char const *name, int nmesh,
12851                         int const *block_map)
12852 {
12853     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
12854     static char         *me = "db_hdf5_GetMultimesh";
12855     hid_t               o=-1, attr=-1, nldset = -1, zldset = -1;
12856     hid_t               mtype=-1, fspace=-1, mspace=-1;
12857     DBmultimeshadj_mt   m;
12858     DBmultimeshadj      *mmadj=NULL;
12859     char                *typestring = NULL;
12860     int                 i, j, tmpnmesh, _objtype;
12861     int                 *offsetmap, *offsetmapn=0, *offsetmapz=0, lneighbors, tmpoff;
12862 
12863     PROTECT {
12864         /* Open object and make sure it's a multimesh */
12865         if ((o=H5Topen(dbfile->cwg, name))<0) {
12866             db_perror((char*)name, E_NOTFOUND, me);
12867             UNWIND();
12868         }
12869         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
12870             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
12871             H5Aclose(attr)<0) {
12872             db_perror((char*)name, E_CALLFAIL, me);
12873             UNWIND();
12874         }
12875         if (DB_MULTIMESHADJ!=(DBObjectType)_objtype) {
12876             db_perror((char*)name, E_CALLFAIL, me);
12877             UNWIND();
12878         }
12879 
12880         /* Read meta data into memory */
12881         memset(&m, 0, sizeof m);
12882         if ((attr=H5Aopen_name(o, "silo"))<0 ||
12883             H5Aread(attr, DBmultimeshadj_mt5, &m)<0 ||
12884             H5Aclose(attr)<0) {
12885             db_perror((char*)name, E_CALLFAIL, me);
12886             UNWIND();
12887         }
12888 
12889         /* Create object and initialize meta data */
12890         if (NULL==(mmadj=DBAllocMultimeshadj(0))) return NULL;
12891         mmadj->nblocks = m.nblocks;
12892         mmadj->blockorigin = m.blockorigin;
12893         mmadj->lneighbors = m.lneighbors;
12894 
12895         /* Read the raw data */
12896         mmadj->meshtypes = (int *)db_hdf5_comprd(dbfile, m.meshtypes, 1);
12897         mmadj->nneighbors = (int *)db_hdf5_comprd(dbfile, m.nneighbors, 1);
12898         mmadj->neighbors = (int *)db_hdf5_comprd(dbfile, m.neighbors, 1);
12899         mmadj->back = (int *)db_hdf5_comprd(dbfile, m.back, 1);
12900         mmadj->lnodelists = (int *)db_hdf5_comprd(dbfile, m.lnodelists, 1);
12901         mmadj->lzonelists = (int *)db_hdf5_comprd(dbfile, m.lzonelists, 1);
12902 
12903         offsetmap = ALLOC_N(int, mmadj->nblocks);
12904         lneighbors = 0;
12905         for (i = 0; (i < mmadj->nblocks) && mmadj->nneighbors; i++)
12906         {
12907             offsetmap[i] = lneighbors;
12908             lneighbors += mmadj->nneighbors[i];
12909         }
12910 
12911         if (offsetmap && mmadj->lnodelists && mmadj->nneighbors &&
12912             (SILO_Globals.dataReadMask & DBMMADJNodelists))
12913         {
12914            mmadj->nodelists = ALLOC_N(int *, lneighbors);
12915            offsetmapn = ALLOC_N(int, mmadj->nblocks);
12916            tmpoff = 0;
12917            for (i = 0; i < mmadj->nblocks; i++)
12918            {
12919                offsetmapn[i] = tmpoff;
12920                for (j = 0; j < mmadj->nneighbors[i]; j++)
12921                   tmpoff += mmadj->lnodelists[offsetmap[i]+j];
12922            }
12923            mmadj->totlnodelists = m.totlnodelists;
12924         }
12925 
12926         if (offsetmap && mmadj->lzonelists && mmadj->nneighbors &&
12927             (SILO_Globals.dataReadMask & DBMMADJZonelists))
12928         {
12929            mmadj->zonelists = ALLOC_N(int *, lneighbors);
12930            offsetmapz = ALLOC_N(int, mmadj->nblocks);
12931            tmpoff = 0;
12932            for (i = 0; i < mmadj->nblocks; i++)
12933            {
12934                offsetmapz[i] = tmpoff;
12935                for (j = 0; j < mmadj->nneighbors[i]; j++)
12936                   tmpoff += mmadj->lzonelists[offsetmap[i]+j];
12937            }
12938            mmadj->totlzonelists = m.totlzonelists;
12939         }
12940 
12941         tmpnmesh = nmesh;
12942         if (nmesh <= 0 || !block_map)
12943             tmpnmesh = mmadj->nblocks;
12944 
12945         if (m.nodelists[0] &&
12946             (nldset = H5Dopen(dbfile->cwg, m.nodelists)) < 0) {
12947             db_perror((char*)name, E_CALLFAIL, me);
12948             UNWIND();
12949         }
12950 
12951         if (m.zonelists[0] &&
12952             (zldset = H5Dopen(dbfile->cwg, m.zonelists)) < 0) {
12953             db_perror((char*)name, E_CALLFAIL, me);
12954             UNWIND();
12955         }
12956 
12957         if ((mtype=silom2hdfm_type(DB_INT))<0) {
12958             FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
12959             DBFreeMultimeshadj(mmadj);
12960             db_perror("datatype", E_BADARGS, me);
12961             UNWIND();
12962         }
12963 
12964         /* This loop could be optimized w.r.t. number of I/O requests
12965            it makes. The nodelists and/or zonelists could be read in
12966            a single call. But then we'd have to split it into separate
12967            arrays duplicating memory */
12968         for (i = 0; (i < tmpnmesh) &&
12969                     (SILO_Globals.dataReadMask & (DBMMADJNodelists|DBMMADJZonelists)); i++)
12970         {
12971            hsize_t ds_size[H5S_MAX_RANK];
12972            int blockno = block_map ? block_map[i] : i;
12973 
12974            if (offsetmapn && mmadj->lnodelists && mmadj->nodelists &&
12975                mmadj->nneighbors && (SILO_Globals.dataReadMask & DBMMADJNodelists))
12976            {
12977               tmpoff = offsetmapn[blockno];
12978               for (j = 0; j < mmadj->nneighbors[blockno]; j++)
12979               {
12980                  int stride = 1;
12981                  int len = mmadj->lnodelists[offsetmap[blockno]+j];
12982                  int *nlist = ALLOC_N(int, len);
12983 
12984                  /* Build the file space selection */
12985                  if ((fspace=build_fspace(nldset, 1, &tmpoff, &len, &stride,
12986                                           ds_size/*out*/))<0) {
12987                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
12988                      DBFreeMultimeshadj(mmadj);
12989                      db_perror("file data space", E_CALLFAIL, me);
12990                      UNWIND();
12991                  }
12992 
12993                  /* Build the memory data space */
12994                  if ((mspace=H5Screate_simple(1, ds_size, NULL))<0) {
12995                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
12996                      DBFreeMultimeshadj(mmadj);
12997                      db_perror("memory data space", E_CALLFAIL, me);
12998                      UNWIND();
12999                  }
13000 
13001                  P_rdprops = H5P_DEFAULT;
13002                  if (!SILO_Globals.enableChecksums)
13003                      P_rdprops = P_ckrdprops;
13004 
13005                  /* Read data */
13006                  if (H5Dread(nldset, mtype, mspace, fspace, P_rdprops, nlist)<0) {
13007                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
13008                      DBFreeMultimeshadj(mmadj);
13009                      hdf5_to_silo_error(name, me);
13010                      UNWIND();
13011                  }
13012 
13013                  /* Close everything */
13014                  H5Sclose(fspace);
13015                  H5Sclose(mspace);
13016 
13017                  mmadj->nodelists[offsetmap[blockno]+j] = nlist;
13018                  tmpoff += len;
13019               }
13020            }
13021 
13022            if (offsetmap && offsetmapz && mmadj->lzonelists && mmadj->zonelists &&
13023                mmadj->nneighbors && (SILO_Globals.dataReadMask & DBMMADJZonelists))
13024            {
13025               tmpoff = offsetmapz[blockno];
13026               for (j = 0; j < mmadj->nneighbors[blockno]; j++)
13027               {
13028                  int stride = 1;
13029                  int len = mmadj->lzonelists[offsetmap[blockno]+j];
13030                  int *zlist = ALLOC_N(int, len);
13031 
13032                  /* Build the file space selection */
13033                  if ((fspace=build_fspace(zldset, 1, &tmpoff, &len, &stride,
13034                                           ds_size/*out*/))<0) {
13035                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
13036                      DBFreeMultimeshadj(mmadj);
13037                      db_perror("file data space", E_CALLFAIL, me);
13038                      UNWIND();
13039                  }
13040 
13041                  /* Build the memory data space */
13042                  if ((mspace=H5Screate_simple(1, ds_size, NULL))<0) {
13043                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
13044                      DBFreeMultimeshadj(mmadj);
13045                      db_perror("memory data space", E_CALLFAIL, me);
13046                      UNWIND();
13047                  }
13048 
13049                  P_rdprops = H5P_DEFAULT;
13050                  if (!SILO_Globals.enableChecksums)
13051                      P_rdprops = P_ckrdprops;
13052 
13053                  /* Read data */
13054                  if (H5Dread(zldset, mtype, mspace, fspace, P_rdprops, zlist)<0) {
13055                      FREE(offsetmap); FREE(offsetmapn); FREE(offsetmapz);
13056                      DBFreeMultimeshadj(mmadj);
13057                      hdf5_to_silo_error(name, me);
13058                      UNWIND();
13059                  }
13060 
13061                  /* Close everything */
13062                  H5Sclose(fspace);
13063                  H5Sclose(mspace);
13064 
13065                  mmadj->zonelists[offsetmap[blockno]+j] = zlist;
13066                  tmpoff += len;
13067               }
13068            }
13069         }
13070 
13071         FREE(offsetmap);
13072         FREE(offsetmapn);
13073         FREE(offsetmapz);
13074         if (nldset != -1)
13075             H5Dclose(nldset);
13076         if (zldset != -1)
13077             H5Dclose(zldset);
13078         H5Tclose(o);
13079 
13080     } CLEANUP {
13081         H5E_BEGIN_TRY {
13082             H5Aclose(attr);
13083             H5Tclose(o);
13084         } H5E_END_TRY;
13085         DBFreeMultimeshadj(mmadj);
13086     } END_PROTECT;
13087 
13088     return mmadj;
13089 }
13090 
13091 /*-------------------------------------------------------------------------
13092  * Function:    db_hdf5_PutMultivar
13093  *
13094  * Purpose:     Writes a multivar object to the file.
13095  *
13096  * Return:      Success:        0
13097  *
13098  *              Failure:        -1
13099  *
13100  * Programmer:  Robb Matzke
13101  *              Tuesday, April  6, 1999
13102  *
13103  * Modifications:
13104  *              Robb Matzke, 1999-07-13
13105  *              Added `ngroups', `blockorigin', and `grouporigin' to
13106  *              duplicate changes to the PDB driver.
13107  *
13108  *              Eric Brugger, 2004-03-12
13109  *              Split the declaration and initialization of sizes
13110  *              into multiple statements so that it compiles on old
13111  *              sgi compilers.
13112  *
13113  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
13114  *              Added call to reset global data
13115  *
13116  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
13117  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
13118  *
13119  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
13120  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
13121  *
13122  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
13123  *   Added support for conserved/extensive options.
13124  *
13125  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
13126  *   Refactored logic to handle time, dtime and cycle to a new method,
13127  *   db_hdf5_handle_ctdt().
13128  *
13129  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13130  *   Added support for namescheme/empty_list options for multi-block objs.
13131  *-------------------------------------------------------------------------
13132  */
13133 SILO_CALLBACK int
db_hdf5_PutMultivar(DBfile * _dbfile,char const * name,int nvars,char const * const * varnames,int const * vartypes,DBoptlist const * optlist)13134 db_hdf5_PutMultivar(DBfile *_dbfile, char const *name, int nvars, char const * const *varnames,
13135                     int const *vartypes, DBoptlist const *optlist)
13136 {
13137     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13138     DBmultivar_mt       m;
13139     int                 i, len;
13140     char                *s=NULL;
13141 
13142     memset(&m, 0, sizeof m);
13143     PROTECT {
13144 
13145         /* Set global options */
13146         db_ResetGlobalData_MultiMesh();
13147         db_ProcessOptlist(DB_MULTIMESH, optlist);
13148 
13149         /* hack to maintain backward compatibility with pdb driver */
13150         db_hdf5_handle_ctdt(dbfile, _mm._time_set, _mm._time,
13151             _mm._dtime_set, _mm._dtime, _mm._cycle);
13152 
13153         /*
13154          * Create a character string which is a semi-colon separated list of
13155          * variable names.
13156          */
13157         if (varnames)
13158         {
13159             for (i=len=0; i<nvars; i++) len += strlen(varnames[i])+1;
13160             s = (char *)malloc(len+1);
13161             for (i=len=0; i<nvars; i++) {
13162                 if (i) s[len++] = ';';
13163                 strcpy(s+len, varnames[i]);
13164                 len += strlen(varnames[i]);
13165             }
13166             len++; /*count null*/
13167             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s,
13168                 m.varnames/*out*/, friendly_name(name, "_varnames", 0));
13169         }
13170 
13171         /* Write raw data arrays */
13172         if (vartypes)
13173             db_hdf5_compwr(dbfile, DB_INT, 1, &nvars, vartypes,
13174                 m.vartypes/*out*/, friendly_name(name, "_vartypes", 0));
13175         if (_mm._extents && _mm._extentssize) {
13176             int sizes[2];
13177             sizes[0] = nvars;
13178             sizes[1] = _mm._extentssize;
13179             db_hdf5_compwr(dbfile, DB_DOUBLE, 2, sizes, _mm._extents,
13180                 m.extents/*out*/, friendly_name(name, "_extents", 0));
13181         }
13182 
13183         /* output mrgtree info if we have it */
13184         if (_mm._region_pnames != NULL) {
13185             int len;
13186             DBStringArrayToStringList((char const * const *)_mm._region_pnames, -1, &s, &len);
13187             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.region_pnames/*out*/,
13188                 friendly_name(name, "_region_pnames", 0));
13189             FREE(s);
13190         }
13191 
13192         /* output nameschemes if we have 'em */
13193         if (_mm._file_ns)
13194         {
13195            len = strlen(_mm._file_ns)+1;
13196            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._file_ns,
13197                 m.file_ns_name/*out*/, friendly_name(name,"_file_ns",0));
13198         }
13199         if (_mm._block_ns)
13200         {
13201            len = strlen(_mm._block_ns)+1;
13202            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._block_ns,
13203                 m.block_ns_name/*out*/, friendly_name(name,"_block_ns",0));
13204         }
13205         if (_mm._empty_list && _mm._empty_cnt>0) {
13206             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._empty_cnt, _mm._empty_list,
13207                 m.empty_list/*out*/, friendly_name(name,"_empty_list",0));
13208         }
13209 
13210         /* Initialize meta data */
13211         m.nvars = nvars;
13212         m.cycle = _mm._cycle;
13213         m.time = _mm._time;
13214         m.dtime = _mm._dtime;
13215         m.ngroups = _mm._ngroups;
13216         m.blockorigin = _mm._blockorigin;
13217         m.grouporigin = _mm._grouporigin;
13218         m.extentssize = _mm._extentssize;
13219         m.guihide = _mm._guihide;
13220         strcpy(m.mmesh_name, OPT(_mm._mmesh_name));
13221         m.tensor_rank = _mm._tensor_rank;
13222         m.conserved = _mm._conserved;
13223         m.extensive = _mm._extensive;
13224         m.block_type = _mm._block_type;
13225         m.empty_cnt = _mm._empty_cnt;
13226         m.repr_block_idx = _mm._repr_block_idx;
13227         db_SetMissingValueForPut(m.missing_value, _mm._missing_value);
13228 
13229         /* Write meta data to file */
13230         STRUCT(DBmultivar) {
13231             if (m.nvars)        MEMBER_S(int, nvars);
13232             if (m.cycle)        MEMBER_S(int, cycle);
13233             if (m.ngroups)      MEMBER_S(int, ngroups);
13234             if (m.blockorigin)  MEMBER_S(int, blockorigin);
13235             if (m.grouporigin)  MEMBER_S(int, grouporigin);
13236             if (_mm._time_set)  MEMBER_S(float, time);
13237             if (_mm._dtime_set) MEMBER_S(double, dtime);
13238             if (m.extentssize)  MEMBER_S(int, extentssize);
13239             if (m.guihide)      MEMBER_S(int, guihide);
13240             if (m.tensor_rank)  MEMBER_S(int, tensor_rank);
13241             if (m.conserved)    MEMBER_S(int, conserved);
13242             if (m.extensive)    MEMBER_S(int, extensive);
13243             if (m.missing_value)MEMBER_S(double, missing_value);
13244             MEMBER_S(str(m.vartypes), vartypes);
13245             MEMBER_S(str(m.varnames), varnames);
13246             MEMBER_S(str(m.extents), extents);
13247             MEMBER_S(str(m.region_pnames), region_pnames);
13248             MEMBER_S(str(m.mmesh_name), mmesh_name);
13249             MEMBER_S(str(m.file_ns_name), file_ns_name);
13250             MEMBER_S(str(m.block_ns_name), block_ns_name);
13251             if (m.block_type)   MEMBER_S(int, block_type);
13252             MEMBER_S(str(m.empty_list), empty_list);
13253             if (m.empty_cnt)   MEMBER_S(int, empty_cnt);
13254             if (m.repr_block_idx)   MEMBER_S(int, repr_block_idx);
13255         } OUTPUT(dbfile, DB_MULTIVAR, name, &m);
13256 
13257         /* Free resources */
13258         FREE(s);
13259 
13260     } CLEANUP {
13261         FREE(s);
13262     } END_PROTECT;
13263     return 0;
13264 }
13265 
13266 /*-------------------------------------------------------------------------
13267  * Function:    db_hdf5_GetMultivar
13268  *
13269  * Purpose:     Reads a multivar object from the file.
13270  *
13271  * Return:      Success:        Ptr to new multivar object.
13272  *
13273  *              Failure:        NULL
13274  *
13275  * Programmer:  Robb Matzke
13276  *              Tuesday, April  6, 1999
13277  *
13278  * Modifications:
13279  *              Robb Matzke, 1999-07-13
13280  *              Added `ngroups', `blockorigin', and `grouporigin' to
13281  *              duplicate changes to the PDB driver.
13282  *
13283  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
13284  *              Removed erroneous code setting vartypes
13285  *
13286  *              Mark C. Miller, Wed Feb  2 07:52:22 PST 2005
13287  *              Added code to temporarily disable force single when
13288  *              reading extents
13289  *
13290  *   Mark C. Miller, Tue Feb 15 14:53:29 PST 2005
13291  *   Changed how force_single was handled to deal with possible throw
13292  *
13293  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
13294  *   Added support for conserved/extensive options.
13295  *
13296  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
13297  *   Added logic to control behavior of slash character swapping for
13298  *   windows/linux and skipping of first semicolon in calls to
13299  *   db_StringListToStringArray.
13300  *
13301  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13302  *   Added support for namescheme/empty_list options for multi-block objs.
13303  *-------------------------------------------------------------------------
13304  */
13305 SILO_CALLBACK DBmultivar *
db_hdf5_GetMultivar(DBfile * _dbfile,char const * name)13306 db_hdf5_GetMultivar(DBfile *_dbfile, char const *name)
13307 {
13308     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13309     static char         *me = "db_hdf5_GetMultivar";
13310     hid_t               o=-1, attr=-1;
13311     int                 _objtype;
13312     DBmultivar_mt       m;
13313     DBmultivar          *mv=NULL;
13314     char                *s=NULL;
13315     char                *mvnames=NULL;
13316 
13317     PROTECT {
13318         /* Open object and make sure it's a multivar */
13319         if ((o=H5Topen(dbfile->cwg, name))<0) {
13320             db_perror(name, E_NOTFOUND, me);
13321             UNWIND();
13322         }
13323         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
13324             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
13325             H5Aclose(attr)<0) {
13326             db_perror(name, E_CALLFAIL, me);
13327             UNWIND();
13328         }
13329         if (DB_MULTIVAR!=(DBObjectType)_objtype) {
13330             db_perror(name, E_CALLFAIL, me);
13331             UNWIND();
13332         }
13333 
13334         /* Read meta data into memory */
13335         memset(&m, 0, sizeof m);
13336         if ((attr=H5Aopen_name(o, "silo"))<0 ||
13337             H5Aread(attr, DBmultivar_mt5, &m)<0 ||
13338             H5Aclose(attr)<0) {
13339             db_perror(name, E_CALLFAIL, me);
13340             UNWIND();
13341         }
13342 
13343         /* Create object and initialize meta data */
13344         if (NULL==(mv=DBAllocMultivar(0))) return NULL;
13345         mv->nvars = m.nvars;
13346         mv->ngroups = m.ngroups;
13347         mv->blockorigin = m.blockorigin;
13348         mv->grouporigin = m.grouporigin;
13349         mv->extentssize = m.extentssize;
13350         mv->guihide = m.guihide;
13351         mv->tensor_rank = m.tensor_rank;
13352         mv->mmesh_name = OPTDUP(m.mmesh_name);
13353         mv->conserved = m.conserved;
13354         mv->extensive = m.extensive;
13355         db_SetMissingValueForGet(mv->missing_value, m.missing_value);
13356 
13357         /* Read the raw data variable types and convert to mem types*/
13358         if (mv->extentssize>0)
13359            mv->extents = (double *)db_hdf5_comprd(dbfile, m.extents, 1);
13360         mv->vartypes = (int *)db_hdf5_comprd(dbfile, m.vartypes, 1);
13361 
13362         /* Read the raw data variable names */
13363         mvnames = (char *)db_hdf5_comprd(dbfile, m.varnames, 1);
13364         db_StringListToStringArrayMBOpt(mvnames, &(mv->varnames), &(mv->varnames_alloc), m.nvars);
13365 
13366         s = (char *)db_hdf5_comprd(dbfile, m.region_pnames, 1);
13367         if (s) mv->region_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
13368         FREE(s);
13369 
13370         mv->file_ns =  (char *)db_hdf5_comprd(dbfile, m.file_ns_name, 1);
13371         mv->block_ns =  (char *)db_hdf5_comprd(dbfile, m.block_ns_name, 1);
13372         mv->block_type = m.block_type;
13373         mv->empty_list =  (int *)db_hdf5_comprd(dbfile, m.empty_list, 1);
13374         mv->empty_cnt = m.empty_cnt;
13375         mv->repr_block_idx = m.repr_block_idx - 1;
13376 
13377         H5Tclose(o);
13378 
13379     } CLEANUP {
13380         H5E_BEGIN_TRY {
13381             H5Aclose(attr);
13382             H5Tclose(o);
13383         } H5E_END_TRY;
13384         DBFreeMultivar(mv);
13385         FREE(s);
13386     } END_PROTECT;
13387     return mv;
13388 }
13389 
13390 /*-------------------------------------------------------------------------
13391  * Function:    db_hdf5_PutMultimat
13392  *
13393  * Purpose:     Write a multimat object into the file.
13394  *
13395  * Return:      Success:        0
13396  *
13397  *              Failure:        -1
13398  *
13399  * Programmer:  Robb Matzke
13400  *              Tuesday, April  6, 1999
13401  *
13402  * Modifications:
13403  *              Robb Matzke, 1999-07-13
13404  *              Added `ngroups', `blockorigin', and `grouporigin' to
13405  *              duplicate changes to the PDB driver.
13406  *
13407  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
13408  *              Added call to reset global data
13409  *
13410  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
13411  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
13412  *
13413  *   Mark C. Miller, Mon Aug  7 17:03:51 PDT 2006
13414  *   Added material names and matcolors options
13415  *
13416  *   Thoamas R. Treadway, Tue Aug 15 14:05:59 PDT 2006
13417  *   Added DBOPT_ALLOWMAT0
13418  *
13419  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
13420  *   Refactored logic to handle time, dtime and cycle to a new method,
13421  *   db_hdf5_handle_ctdt().
13422  *
13423  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13424  *   Added support for namescheme/empty_list options for multi-block objs.
13425  *-------------------------------------------------------------------------
13426  */
13427 SILO_CALLBACK int
db_hdf5_PutMultimat(DBfile * _dbfile,char const * name,int nmats,char const * const * matnames,DBoptlist const * optlist)13428 db_hdf5_PutMultimat(DBfile *_dbfile, char const *name, int nmats, char const * const *matnames,
13429                     DBoptlist const *optlist)
13430 {
13431     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13432     DBmultimat_mt       m;
13433     int                 i, len;
13434     char                *s=NULL;
13435 
13436     memset(&m, 0, sizeof m);
13437     PROTECT {
13438         /* Set global options */
13439         db_ResetGlobalData_MultiMesh();
13440         db_ProcessOptlist(DB_MULTIMESH, optlist);
13441 
13442         /* hack to maintain backward compatibility with pdb driver */
13443         db_hdf5_handle_ctdt(dbfile, _mm._time_set, _mm._time,
13444             _mm._dtime_set, _mm._dtime, _mm._cycle);
13445 
13446         /*
13447          * Create a character string which is a semi-colon separated list of
13448          * material names.
13449          */
13450         /* Write raw data arrays */
13451         if (matnames)
13452         {
13453             for (i=len=0; i<nmats; i++) len += strlen(matnames[i])+1;
13454             s = (char *)malloc(len+1);
13455             for (i=len=0; i<nmats; i++) {
13456                 if (i) s[len++] = ';';
13457                 strcpy(s+len, matnames[i]);
13458                 len += strlen(matnames[i]);
13459             }
13460             len++; /*count null*/
13461 
13462             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.matnames/*out*/,
13463                 friendly_name(name, "_matnames", 0));
13464         }
13465         if (_mm._matnos && _mm._nmatnos > 0) {
13466             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._nmatnos, _mm._matnos,
13467                 m.matnos/*out*/, friendly_name(name,"_matnos", 0));
13468         }
13469         if (_mm._mixlens) {
13470             db_hdf5_compwr(dbfile, DB_INT, 1, &nmats, _mm._mixlens,
13471                 m.mixlens/*out*/, friendly_name(name,"_mixlens", 0));
13472         }
13473         if (_mm._matcounts && _mm._matlists) {
13474             db_hdf5_compwr(dbfile, DB_INT, 1, &nmats, _mm._matcounts,
13475                 m.matcounts/*out*/, friendly_name(name,"_matcounts", 0));
13476             for (i=len=0; i<nmats; i++)
13477                len += _mm._matcounts[i];
13478             db_hdf5_compwr(dbfile, DB_INT, 1, &len, _mm._matlists,
13479                 m.matlists/*out*/, friendly_name(name,"_matlists", 0));
13480         }
13481         if (_mm._matcolors && _mm._nmatnos > 0) {
13482             int len; char *tmp;
13483             DBStringArrayToStringList((char const * const *)_mm._matcolors,
13484                 _mm._nmatnos, &tmp, &len);
13485             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
13486                 m.mat_colors/*out*/, friendly_name(name,"_matcolors", 0));
13487             FREE(tmp);
13488         }
13489         if (_mm._matnames && _mm._nmatnos > 0) {
13490             int len; char *tmp;
13491             DBStringArrayToStringList((char const * const *)_mm._matnames,
13492                 _mm._nmatnos, &tmp, &len);
13493             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
13494                 m.material_names/*out*/, friendly_name(name,"_material_names", 0));
13495             FREE(tmp);
13496         }
13497         /* output nameschemes if we have 'em */
13498         if (_mm._file_ns)
13499         {
13500            len = strlen(_mm._file_ns)+1;
13501            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._file_ns,
13502                 m.file_ns_name/*out*/, friendly_name(name,"_file_ns",0));
13503         }
13504         if (_mm._block_ns)
13505         {
13506            len = strlen(_mm._block_ns)+1;
13507            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._block_ns,
13508                 m.block_ns_name/*out*/, friendly_name(name,"_block_ns",0));
13509         }
13510         if (_mm._empty_list && _mm._empty_cnt>0) {
13511             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._empty_cnt, _mm._empty_list,
13512                 m.empty_list/*out*/, friendly_name(name,"_empty_list",0));
13513         }
13514 
13515         /* Initialize meta data */
13516         m.nmats = nmats;
13517         m.cycle = _mm._cycle;
13518         m.time = _mm._time;
13519         m.dtime = _mm._dtime;
13520         m.ngroups = _mm._ngroups;
13521         m.blockorigin = _mm._blockorigin;
13522         m.grouporigin = _mm._grouporigin;
13523         m.nmatnos = _mm._nmatnos;
13524         m.allowmat0 = _mm._allowmat0;
13525         m.guihide = _mm._guihide;
13526         strcpy(m.mmesh_name, OPT(_mm._mmesh_name));
13527         m.empty_cnt = _mm._empty_cnt;
13528         m.repr_block_idx = _mm._repr_block_idx;
13529 
13530         /* Write meta data to file */
13531         STRUCT(DBmultimat) {
13532             if (m.nmats)        MEMBER_S(int, nmats);
13533             if (m.cycle)        MEMBER_S(int, cycle);
13534             if (m.ngroups)      MEMBER_S(int, ngroups);
13535             if (m.blockorigin)  MEMBER_S(int, blockorigin);
13536             if (m.grouporigin)  MEMBER_S(int, grouporigin);
13537             if (_mm._time_set)  MEMBER_S(float, time);
13538             if (_mm._dtime_set) MEMBER_S(double, dtime);
13539             MEMBER_S(str(m.matnames), matnames);
13540             MEMBER_S(str(m.matnos), matnos);
13541             MEMBER_S(str(m.mixlens), mixlens);
13542             MEMBER_S(str(m.matcounts), matcounts);
13543             MEMBER_S(str(m.matlists), matlists);
13544             if (m.nmatnos)      MEMBER_S(int, nmatnos);
13545             if (m.allowmat0)    MEMBER_S(int, allowmat0);
13546             if (m.guihide)      MEMBER_S(int, guihide);
13547             MEMBER_S(str(m.material_names), material_names);
13548             MEMBER_S(str(m.mat_colors), mat_colors);
13549             MEMBER_S(str(m.mmesh_name), mmesh_name);
13550             MEMBER_S(str(m.file_ns_name), file_ns_name);
13551             MEMBER_S(str(m.block_ns_name), block_ns_name);
13552             MEMBER_S(str(m.empty_list), empty_list);
13553             if (m.empty_cnt)   MEMBER_S(int, empty_cnt);
13554             if (m.repr_block_idx)   MEMBER_S(int, repr_block_idx);
13555         } OUTPUT(dbfile, DB_MULTIMAT, name, &m);
13556 
13557         /* Free resources */
13558         FREE(s);
13559 
13560     } CLEANUP {
13561         FREE(s);
13562     } END_PROTECT;
13563     return 0;
13564 }
13565 
13566 /*-------------------------------------------------------------------------
13567  * Function:    db_hdf5_GetMultimat
13568  *
13569  * Purpose:     Reads a multimat object from the file.
13570  *
13571  * Return:      Success:        Ptr to new multimat object.
13572  *
13573  *              Failure:        NULL
13574  *
13575  * Programmer:  Robb Matzke
13576  *              Tuesday, April  6, 1999
13577  *
13578  * Modifications:
13579  *              Robb Matzke, 1999-07-13
13580  *              Added `ngroups', `blockorigin', and `grouporigin' to
13581  *              duplicate changes to the PDB driver.
13582  *
13583  *    Mark C. Miller, Mon Aug  7 17:03:51 PDT 2006
13584  *    Added material names and material colors options as well as nmatnos
13585  *    and matnos
13586  *
13587  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
13588  *   Added logic to control behavior of slash character swapping for
13589  *   windows/linux and skipping of first semicolon in calls to
13590  *   db_StringListToStringArray.
13591  *
13592  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13593  *   Added support for namescheme/empty_list options for multi-block objs.
13594  *-------------------------------------------------------------------------
13595  */
13596 SILO_CALLBACK DBmultimat *
db_hdf5_GetMultimat(DBfile * _dbfile,char const * name)13597 db_hdf5_GetMultimat(DBfile *_dbfile, char const *name)
13598 {
13599     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13600     static char         *me = "db_hdf5_GetMultimat";
13601     hid_t               o=-1, attr=-1;
13602     int                 _objtype;
13603     DBmultimat_mt       m;
13604     DBmultimat          *mm=NULL;
13605     char                *matnames=NULL;
13606 
13607     PROTECT {
13608         /* Open object and make sure it's a multimat */
13609         if ((o=H5Topen(dbfile->cwg, name))<0) {
13610             db_perror(name, E_NOTFOUND, me);
13611             UNWIND();
13612         }
13613         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
13614             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
13615             H5Aclose(attr)<0) {
13616             db_perror(name, E_CALLFAIL, me);
13617             UNWIND();
13618         }
13619         if (DB_MULTIMAT!=(DBObjectType)_objtype) {
13620             db_perror(name, E_CALLFAIL, me);
13621             UNWIND();
13622         }
13623 
13624         /* Read meta data into memory */
13625         memset(&m, 0, sizeof m);
13626         if ((attr=H5Aopen_name(o, "silo"))<0 ||
13627             H5Aread(attr, DBmultimat_mt5, &m)<0 ||
13628             H5Aclose(attr)<0) {
13629             db_perror(name, E_CALLFAIL, me);
13630             UNWIND();
13631         }
13632 
13633         /* Create object and initialize meta data */
13634         if (NULL==(mm=DBAllocMultimat(0))) return NULL;
13635         mm->nmats = m.nmats;
13636         mm->ngroups = m.ngroups;
13637         mm->blockorigin = m.blockorigin;
13638         mm->grouporigin = m.grouporigin;
13639         mm->allowmat0 = m.allowmat0;
13640         mm->guihide = m.guihide;
13641         mm->nmatnos = m.nmatnos;
13642         mm->mmesh_name = OPTDUP(m.mmesh_name);
13643 
13644         /* Read the raw data */
13645         mm->mixlens = (int *)db_hdf5_comprd(dbfile, m.mixlens, 1);
13646         mm->matcounts = (int *)db_hdf5_comprd(dbfile, m.matcounts, 1);
13647         mm->matlists = (int *)db_hdf5_comprd(dbfile, m.matlists, 1);
13648         mm->matnos = (int *)db_hdf5_comprd(dbfile, m.matnos, 1);
13649         matnames = (char *)db_hdf5_comprd(dbfile, m.matnames, 1);
13650         db_StringListToStringArrayMBOpt(matnames, &(mm->matnames), &(mm->matnames_alloc), m.nmats);
13651 
13652         if (m.nmatnos > 0) {
13653             char *tmpmaterial_names = (char *)db_hdf5_comprd(dbfile, m.material_names, 1);
13654             char *tmpmat_colors = (char *)db_hdf5_comprd(dbfile, m.mat_colors, 1);
13655             if (tmpmaterial_names)
13656                 mm->material_names = DBStringListToStringArray(tmpmaterial_names,
13657                     &m.nmatnos, !skipFirstSemicolon);
13658             if (tmpmat_colors)
13659                 mm->matcolors = DBStringListToStringArray(tmpmat_colors,
13660                     &m.nmatnos, !skipFirstSemicolon);
13661             FREE(tmpmaterial_names);
13662             FREE(tmpmat_colors);
13663         }
13664 
13665         mm->file_ns =  (char *)db_hdf5_comprd(dbfile, m.file_ns_name, 1);
13666         mm->block_ns =  (char *)db_hdf5_comprd(dbfile, m.block_ns_name, 1);
13667         mm->empty_list =  (int *)db_hdf5_comprd(dbfile, m.empty_list, 1);
13668         mm->empty_cnt = m.empty_cnt;
13669         mm->repr_block_idx = m.repr_block_idx - 1;
13670 
13671         H5Tclose(o);
13672 
13673     } CLEANUP {
13674         H5E_BEGIN_TRY {
13675             H5Aclose(attr);
13676             H5Tclose(o);
13677         } H5E_END_TRY;
13678         DBFreeMultimat(mm);
13679     } END_PROTECT;
13680     return mm;
13681 }
13682 
13683 /*-------------------------------------------------------------------------
13684  * Function:    db_hdf5_PutMultimatspecies
13685  *
13686  * Purpose:     Write a multi-mat species object to the file.
13687  *
13688  * Return:      Success:        0
13689  *
13690  *              Failure:        -1
13691  *
13692  * Programmer:  Robb Matzke
13693  *              Tuesday, April  6, 1999
13694  *
13695  * Modifications:
13696  *              Robb Matzke, 1999-07-13
13697  *              Added `ngroups', `blockorigin', and `grouporigin' to
13698  *              duplicate changes to the PDB driver.
13699  *
13700  *              Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
13701  *              Added call to reset global data
13702  *
13703  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
13704  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
13705  *
13706  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
13707  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
13708  *
13709  *   Mark C. Miller, Tue Sep  8 15:40:51 PDT 2009
13710  *   Added names and colors for species.
13711  *
13712  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
13713  *   Refactored logic to handle time, dtime and cycle to a new method,
13714  *   db_hdf5_handle_ctdt().
13715  *
13716  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13717  *   Added support for namescheme/empty_list options for multi-block objs.
13718  *-------------------------------------------------------------------------
13719  */
13720 SILO_CALLBACK int
db_hdf5_PutMultimatspecies(DBfile * _dbfile,char const * name,int nspec,char const * const * specnames,DBoptlist const * optlist)13721 db_hdf5_PutMultimatspecies(DBfile *_dbfile, char const *name, int nspec,
13722                            char const * const *specnames, DBoptlist const *optlist)
13723 {
13724     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13725     DBmultimatspecies_mt m;
13726     int                 i, len, nstrs = 0;
13727     char                *s=NULL;
13728 
13729     memset(&m, 0, sizeof m);
13730     PROTECT {
13731         /* Set global options */
13732         db_ResetGlobalData_MultiMesh();
13733         db_ProcessOptlist(DB_MULTIMESH, optlist);
13734 
13735         /* hack to maintain backward compatibility with pdb driver */
13736         db_hdf5_handle_ctdt(dbfile, _mm._time_set, _mm._time,
13737             _mm._dtime_set, _mm._dtime, _mm._cycle);
13738 
13739         /*
13740          * Create a character string which is a semi-colon separated list of
13741          * material names.
13742          */
13743         /* Write raw data arrays */
13744         if (specnames)
13745         {
13746             for (i=len=0; i<nspec; i++) len += strlen(specnames[i])+1;
13747             s = (char *)malloc(len+1);
13748             for (i=len=0; i<nspec; i++) {
13749                 if (i) s[len++] = ';';
13750                 strcpy(s+len, specnames[i]);
13751                 len += strlen(specnames[i]);
13752             }
13753             len++; /*count null*/
13754 
13755             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.specnames/*out*/,
13756                 friendly_name(name, "_specnames", 0));
13757         }
13758 
13759         if (_mm._nmat>0 && _mm._nmatspec) {
13760 
13761             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._nmat, _mm._nmatspec,
13762                 m.nmatspec/*out*/, friendly_name(name, "_nmatspec", 0));
13763 
13764             if (_mm._specnames) {
13765                 int len; char *tmp;
13766                 for (i=0; i < _mm._nmat; i++)
13767                     nstrs += _mm._nmatspec[i];
13768                 DBStringArrayToStringList((char const * const *)_mm._specnames, nstrs, &tmp, &len);
13769                 db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
13770                     m.species_names/*out*/, friendly_name(name,"_species_names", 0));
13771                 FREE(tmp);
13772             }
13773 
13774             if (_mm._speccolors) {
13775                 int len; char *tmp;
13776                 if (nstrs == 0)
13777                 {
13778                     for (i=0; i < _mm._nmat; i++)
13779                         nstrs += _mm._nmatspec[i];
13780                 }
13781                 DBStringArrayToStringList((char const * const *)_mm._speccolors, nstrs, &tmp, &len);
13782                 db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
13783                     m.speccolors/*out*/, friendly_name(name,"_speccolors", 0));
13784                 FREE(tmp);
13785             }
13786         }
13787         /* output nameschemes if we have 'em */
13788         if (_mm._file_ns)
13789         {
13790            len = strlen(_mm._file_ns)+1;
13791            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._file_ns,
13792                 m.file_ns_name/*out*/, friendly_name(name,"_file_ns",0));
13793         }
13794         if (_mm._block_ns)
13795         {
13796            len = strlen(_mm._block_ns)+1;
13797            db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, _mm._block_ns,
13798                 m.block_ns_name/*out*/, friendly_name(name,"_block_ns",0));
13799         }
13800         if (_mm._empty_list && _mm._empty_cnt>0) {
13801             db_hdf5_compwr(dbfile, DB_INT, 1, &_mm._empty_cnt, _mm._empty_list,
13802                 m.empty_list/*out*/, friendly_name(name,"_empty_list",0));
13803         }
13804 
13805         /* Initialize meta data */
13806         m.nspec = nspec;
13807         m.nmat = _mm._nmat;
13808         m.cycle = _mm._cycle;
13809         m.time = _mm._time;
13810         m.dtime = _mm._dtime;
13811         m.ngroups = _mm._ngroups;
13812         m.blockorigin = _mm._blockorigin;
13813         m.grouporigin = _mm._grouporigin;
13814         m.guihide = _mm._guihide;
13815         strcpy(m.matname, OPT(_mm._matname));
13816         m.empty_cnt = _mm._empty_cnt;
13817         m.repr_block_idx = _mm._repr_block_idx;
13818 
13819         /* Write meta data to file */
13820         STRUCT(DBmultimatspecies) {
13821             if (m.nspec)        MEMBER_S(int, nspec);
13822             if (m.cycle)        MEMBER_S(int, cycle);
13823             if (m.ngroups)      MEMBER_S(int, ngroups);
13824             if (m.blockorigin)  MEMBER_S(int, blockorigin);
13825             if (m.grouporigin)  MEMBER_S(int, grouporigin);
13826             if (m.guihide)      MEMBER_S(int, guihide);
13827             if (_mm._time_set)  MEMBER_S(float, time);
13828             if (_mm._dtime_set) MEMBER_S(double, dtime);
13829             if (_mm._nmat>0 && _mm._nmatspec) MEMBER_S(int, nmat);
13830             MEMBER_S(str(m.specnames), specnames);
13831             MEMBER_S(str(m.nmatspec), nmatspec);
13832             MEMBER_S(str(m.matname), matname);
13833             MEMBER_S(str(m.species_names), species_names);
13834             MEMBER_S(str(m.speccolors), speccolors);
13835             MEMBER_S(str(m.file_ns_name), file_ns_name);
13836             MEMBER_S(str(m.block_ns_name), block_ns_name);
13837             MEMBER_S(str(m.empty_list), empty_list);
13838             if (m.empty_cnt)   MEMBER_S(int, empty_cnt);
13839             if (m.repr_block_idx)   MEMBER_S(int, repr_block_idx);
13840         } OUTPUT(dbfile, DB_MULTIMATSPECIES, name, &m);
13841 
13842         /* Free resources */
13843         FREE(s);
13844 
13845     } CLEANUP {
13846         FREE(s);
13847     } END_PROTECT;
13848     return 0;
13849 }
13850 
13851 /*-------------------------------------------------------------------------
13852  * Function:    db_hdf5_GetMultimatspecies
13853  *
13854  * Purpose:     Reads a multimat species object from the file.
13855  *
13856  * Return:      Success:        Ptr to new multimatspecies.
13857  *
13858  *              Failure:        NULL
13859  *
13860  * Programmer:  Robb Matzke
13861  *              Tuesday, April  6, 1999
13862  *
13863  * Modifications:
13864  *              Robb Matzke, 1999-07-13
13865  *              Added `ngroups', `blockorigin', and `grouporigin' to
13866  *              duplicate changes to the PDB driver.
13867  *
13868  *              Mark C. Miller, Tue Sep  8 15:40:51 PDT 2009
13869  *              Added names and colors for species.
13870  *
13871  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
13872  *   Added logic to control behavior of slash character swapping for
13873  *   windows/linux and skipping of first semicolon in calls to
13874  *   db_StringListToStringArray.
13875  *
13876  *   Mark C. Miller, Wed Jul 14 20:48:15 PDT 2010
13877  *   Added support for namescheme/empty_list options for multi-block objs.
13878  *-------------------------------------------------------------------------
13879  */
13880 SILO_CALLBACK DBmultimatspecies *
db_hdf5_GetMultimatspecies(DBfile * _dbfile,char const * name)13881 db_hdf5_GetMultimatspecies(DBfile *_dbfile, char const *name)
13882 {
13883     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
13884     static char         *me = "db_hdf5_GetMultimatspecies";
13885     hid_t               o=-1, attr=-1;
13886     int                 _objtype, i, nstrs=0;
13887     DBmultimatspecies_mt m;
13888     DBmultimatspecies   *mm=NULL;
13889     char                *specnames=NULL;
13890 
13891     PROTECT {
13892         /* Open object and make sure it's a multimatspecies */
13893         if ((o=H5Topen(dbfile->cwg, name))<0) {
13894             db_perror(name, E_NOTFOUND, me);
13895             UNWIND();
13896         }
13897         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
13898             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
13899             H5Aclose(attr)<0) {
13900             db_perror(name, E_CALLFAIL, me);
13901             UNWIND();
13902         }
13903         if (DB_MULTIMATSPECIES!=(DBObjectType)_objtype) {
13904             db_perror(name, E_CALLFAIL, me);
13905             UNWIND();
13906         }
13907 
13908         /* Read meta data into memory */
13909         memset(&m, 0, sizeof m);
13910         if ((attr=H5Aopen_name(o, "silo"))<0 ||
13911             H5Aread(attr, DBmultimatspecies_mt5, &m)<0 ||
13912             H5Aclose(attr)<0) {
13913             db_perror(name, E_CALLFAIL, me);
13914             UNWIND();
13915         }
13916 
13917         /* Create object and initialize meta data */
13918         if (NULL==(mm=DBAllocMultimatspecies(0))) return NULL;
13919         mm->nspec = m.nspec;
13920         mm->ngroups = m.ngroups;
13921         mm->blockorigin = m.blockorigin;
13922         mm->grouporigin = m.grouporigin;
13923         mm->guihide = m.guihide;
13924         mm->nmat = m.nmat;
13925         mm->nmatspec = (int *)db_hdf5_comprd(dbfile, m.nmatspec, 1);
13926 
13927         /* Read the raw data */
13928         specnames = (char *)db_hdf5_comprd(dbfile, m.specnames, 1);
13929         db_StringListToStringArrayMBOpt(specnames, &(mm->specnames), &(mm->specnames_alloc), m.nspec);
13930 
13931         if (mm->nmat > 0 && mm->nmatspec) {
13932             char *tmpspecies_names = (char *)db_hdf5_comprd(dbfile, m.species_names, 1);
13933             char *tmpspeccolors = (char *)db_hdf5_comprd(dbfile, m.speccolors, 1);
13934 
13935             if (tmpspecies_names)
13936             {
13937                 for (i = 0; i < mm->nmat; i++)
13938                     nstrs += mm->nmatspec[i];
13939                 mm->species_names = DBStringListToStringArray(tmpspecies_names, &nstrs, !skipFirstSemicolon);
13940             }
13941             if (tmpspeccolors)
13942             {
13943                 if (nstrs == 0)
13944                 {
13945                     for (i = 0; i < mm->nmat; i++)
13946                         nstrs += mm->nmatspec[i];
13947                 }
13948                 mm->speccolors = DBStringListToStringArray(tmpspeccolors, &nstrs, !skipFirstSemicolon);
13949             }
13950             FREE(tmpspecies_names);
13951             FREE(tmpspeccolors);
13952         }
13953 
13954         mm->file_ns =  (char *)db_hdf5_comprd(dbfile, m.file_ns_name, 1);
13955         mm->block_ns =  (char *)db_hdf5_comprd(dbfile, m.block_ns_name, 1);
13956         mm->empty_list =  (int *)db_hdf5_comprd(dbfile, m.empty_list, 1);
13957         mm->empty_cnt = m.empty_cnt;
13958         mm->repr_block_idx = m.repr_block_idx;
13959 
13960         H5Tclose(o);
13961 
13962     } CLEANUP {
13963         H5E_BEGIN_TRY {
13964             H5Aclose(attr);
13965             H5Tclose(o);
13966         } H5E_END_TRY;
13967         DBFreeMultimatspecies(mm);
13968     } END_PROTECT;
13969     return mm;
13970 }
13971 
13972 /*-------------------------------------------------------------------------
13973  * Function:    db_hdf5_PutPointmesh
13974  *
13975  * Purpose:     Writes a pointmesh object to the file.
13976  *
13977  * Return:      Success:        0
13978  *
13979  *              Failure:        -1
13980  *
13981  * Programmer:  Robb Matzke
13982  *              Tuesday, April  6, 1999
13983  *
13984  * Modifications:
13985  *              Robb Matzke, 1999-07-13
13986  *              Added `group_no' property to duplicate changes made to the
13987  *              PDB driver.
13988  *
13989  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
13990  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
13991  *
13992  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
13993  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
13994  *
13995  *   Mark C. Miller, Thu Jan 17 21:41:52 PST 2008
13996  *   Fixed missing origin member
13997  *
13998  *   Mark C. Miller, Sat Nov 14 20:28:34 PST 2009
13999  *   Changed how long long global node/zone numbers are supported
14000  *   from a int (bool), "llong_gnode|zoneno" to an int holding
14001  *   the actual datatype. The type is assumed int if it its
14002  *   value is zero or it does not exist. Otherwise, the type is
14003  *   is whatever is stored in gnznodtype member.
14004  *
14005  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
14006  *   Refactored logic to handle time, dtime and cycle to a new method,
14007  *   db_hdf5_handle_ctdt().
14008  *-------------------------------------------------------------------------
14009  */
14010 SILO_CALLBACK int
db_hdf5_PutPointmesh(DBfile * _dbfile,char const * name,int ndims,DBVCP2_t _coords,int nels,int datatype,DBoptlist const * optlist)14011 db_hdf5_PutPointmesh(DBfile *_dbfile, char const *name, int ndims, DBVCP2_t _coords,
14012                      int nels, int datatype, DBoptlist const *optlist)
14013 {
14014     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14015     static char         *me = "db_hdf5_PutPointmesh";
14016     DBpointmesh_mt      m;
14017     int                 i;
14018     void const * const *coords = (void const * const *) _coords;
14019 
14020     memset(&m, 0, sizeof m);
14021     PROTECT {
14022         /* Check datatype */
14023         if (DB_FLOAT!=datatype && DB_DOUBLE!=datatype) {
14024             db_perror("invalid floating-point datatype", E_BADARGS, me);
14025             UNWIND();
14026         }
14027 
14028         /* Set global options */
14029         memset(&_pm, 0, sizeof _pm);
14030         _pm._ndims = _pm._nspace = ndims;
14031         _pm._group_no = -1;
14032         db_ProcessOptlist(DB_POINTMESH, optlist);
14033         _pm._nels = nels;
14034         _pm._minindex = _pm._lo_offset;
14035         _pm._maxindex = nels - _pm._hi_offset - 1;
14036 
14037         /* hack to maintain backward compatibility with pdb driver */
14038         db_hdf5_handle_ctdt(dbfile, _pm._time_set, _pm._time,
14039             _pm._dtime_set, _pm._dtime, _pm._cycle);
14040 
14041         /* Write raw data arrays */
14042         for (i=0; i<ndims && nels>0; i++) {
14043             db_hdf5_compwr(dbfile, datatype, 1, &nels, coords[i],
14044                 m.coord[i]/*out*/, friendly_name(name, "_coord%d", &i));
14045         }
14046 
14047         /* Find the mesh extents from the coordinate arrays */
14048         if (nels>0)
14049         {
14050             if (DB_DOUBLE==datatype) {
14051                 for (i=0; i<ndims; i++) {
14052                     _DBdarrminmax(((double**)coords)[i], nels,
14053                                   m.min_extents+i, m.max_extents+i);
14054                 }
14055             } else {
14056                 for (i=0; i<ndims; i++) {
14057                     float min_extents, max_extents;
14058                     _DBarrminmax((float*)coords[i], nels, &min_extents, &max_extents);
14059                     m.min_extents[i] = min_extents;
14060                     m.max_extents[i] = max_extents;
14061                 }
14062             }
14063         }
14064 
14065         /* Global node numbers */
14066         if (nels>0 && _pm._gnodeno)
14067         {
14068             if (_pm._llong_gnodeno)
14069                 db_hdf5_compwr(dbfile, DB_LONG_LONG, 1, &nels, _pm._gnodeno,
14070                     m.gnodeno/*out*/, friendly_name(name, "_gnodeno", 0));
14071             else
14072                 db_hdf5_compwr(dbfile, DB_INT, 1, &nels, _pm._gnodeno,
14073                     m.gnodeno/*out*/, friendly_name(name, "_gnodeno", 0));
14074         }
14075 
14076         if (nels>0 && _pm._ghost_node_labels)
14077         {
14078             db_hdf5_compwr(dbfile, DB_CHAR, 1, &nels, _pm._ghost_node_labels,
14079                     m.ghost_node_labels/*out*/, friendly_name(name, "_ghost_node_labels", 0));
14080         }
14081 
14082         if (_pm._alt_nodenum_vars) {
14083             int len, nvars=-1; char *tmp;
14084             DBStringArrayToStringList((char const * const *)_pm._alt_nodenum_vars, nvars, &tmp, &len);
14085             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, tmp,
14086                 m.alt_nodenum_vars/*out*/, friendly_name(name, "_alt_nodenum_vars",0));
14087             FREE(tmp);
14088         }
14089 
14090         /* Build header in memory */
14091         m.ndims = ndims;
14092         m.nspace = _pm._nspace;
14093         m.nels = _pm._nels;
14094         m.cycle = _pm._cycle;
14095         m.origin = _pm._origin;
14096         m.min_index = _pm._minindex;
14097         m.max_index = _pm._maxindex;
14098         m.time = _pm._time;
14099         m.dtime = _pm._dtime;
14100         m.group_no = _pm._group_no;
14101         m.guihide = _pm._guihide;
14102         for (i=0; i<ndims; i++) {
14103             strcpy(m.label[i], OPT(_pm._labels[i]));
14104             strcpy(m.units[i], OPT(_pm._units[i]));
14105         }
14106         strcpy(m.mrgtree_name, OPT(_pm._mrgtree_name));
14107         m.gnznodtype = _pm._llong_gnodeno?DB_LONG_LONG:0;
14108 
14109         /* Write header to file */
14110         STRUCT(DBpointmesh) {
14111             if (m.ndims)        MEMBER_S(int, ndims);
14112             if (m.nspace)       MEMBER_S(int, nspace);
14113             if (m.nels)         MEMBER_S(int, nels);
14114             if (m.cycle)        MEMBER_S(int, cycle);
14115             if (_pm._time_set)  MEMBER_S(float, time);
14116             if (_pm._dtime_set) MEMBER_S(double, dtime);
14117             if (m.min_index)    MEMBER_S(int, min_index);
14118             if (m.max_index)    MEMBER_S(int, max_index);
14119             if (m.group_no)     MEMBER_S(int, group_no);
14120             if (m.guihide)      MEMBER_S(int, guihide);
14121             if (m.origin)       MEMBER_S(int, origin);
14122             MEMBER_3(double, min_extents);
14123             MEMBER_3(double, max_extents);
14124             MEMBER_R(str(m.coord[_j]), coord, ndims);
14125             MEMBER_R(str(m.label[_j]), label, ndims);
14126             MEMBER_R(str(m.units[_j]), units, ndims);
14127             MEMBER_S(str(m.gnodeno), gnodeno);
14128             MEMBER_S(str(m.mrgtree_name), mrgtree_name);
14129             if (m.gnznodtype    )MEMBER_S(int, gnznodtype);
14130             MEMBER_S(str(m.ghost_node_labels), ghost_node_labels);
14131             MEMBER_S(str(m.alt_nodenum_vars), alt_nodenum_vars);
14132         } OUTPUT(dbfile, DB_POINTMESH, name, &m);
14133 
14134     } CLEANUP {
14135         /*void*/
14136     } END_PROTECT;
14137     return 0;
14138 }
14139 
14140 /*-------------------------------------------------------------------------
14141  * Function:    db_hdf5_GetPointmesh
14142  *
14143  * Purpose:     Reads a pointmesh object from the file.
14144  *
14145  * Return:      Success:        Ptr to new pointmesh.
14146  *
14147  *              Failure:        NULL
14148  *
14149  * Programmer:  Robb Matzke
14150  *              Wednesday, April  7, 1999
14151  *
14152  * Modifications:
14153  *              Robb Matzke, 1999-07-13
14154  *              Added `group_no' to duplicate changes to the PDB driver.
14155  *
14156  *              Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
14157  *              Made it set datatype correctly. Added support for dataReadMask
14158  *
14159  *              Mark C. Miller, Thu Jan 17 21:41:52 PST 2008
14160  *              Fixed missing origin member
14161  *-------------------------------------------------------------------------
14162  */
14163 SILO_CALLBACK DBpointmesh *
db_hdf5_GetPointmesh(DBfile * _dbfile,char const * name)14164 db_hdf5_GetPointmesh(DBfile *_dbfile, char const *name)
14165 {
14166     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14167     static char         *me = "db_hdf5_GetPointmesh";
14168     hid_t               o=-1, attr=-1;
14169     int                 _objtype, i;
14170     DBpointmesh_mt      m;
14171     DBpointmesh         *pm=NULL;
14172 
14173     PROTECT {
14174         /* Open object and make sure it's a pointmesh */
14175         if ((o=H5Topen(dbfile->cwg, name))<0) {
14176             db_perror(name, E_NOTFOUND, me);
14177             UNWIND();
14178         }
14179         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
14180             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
14181             H5Aclose(attr)<0) {
14182             db_perror(name, E_CALLFAIL, me);
14183             UNWIND();
14184         }
14185         if (DB_POINTMESH!=(DBObjectType)_objtype) {
14186             db_perror(name, E_CALLFAIL, me);
14187             UNWIND();
14188         }
14189 
14190         /* Read meta data into memory */
14191         memset(&m, 0, sizeof m);
14192         if ((attr=H5Aopen_name(o, "silo"))<0 ||
14193             H5Aread(attr, DBpointmesh_mt5, &m)<0 ||
14194             H5Aclose(attr)<0) {
14195             db_perror(name, E_CALLFAIL, me);
14196             UNWIND();
14197         }
14198 
14199         /* Create object and initialize meta data */
14200         if (NULL==(pm=DBAllocPointmesh())) return NULL;
14201         pm->name = BASEDUP(name);
14202         pm->cycle = m.cycle;
14203         pm->time = m.time;
14204         pm->dtime = m.dtime;
14205         if ((pm->datatype = db_hdf5_GetVarType(_dbfile, m.coord[0])) < 0)
14206             pm->datatype = DB_FLOAT;
14207         if (force_single_g) pm->datatype = DB_FLOAT;
14208         pm->ndims = m.ndims;
14209         pm->nels = m.nels;
14210         pm->group_no = m.group_no;
14211         pm->guihide = m.guihide;
14212         pm->origin = m.origin;
14213         pm->mrgtree_name = OPTDUP(m.mrgtree_name);
14214         for (i=0; i<m.ndims; i++) {
14215             pm->units[i] = OPTDUP(m.units[i]);
14216             pm->labels[i] = OPTDUP(m.label[i]);
14217             if (pm->datatype == DB_DOUBLE)
14218             {
14219                 ((double*)pm->min_extents)[i] = m.min_extents[i];
14220                 ((double*)pm->max_extents)[i] = m.max_extents[i];
14221             }
14222             else
14223             {
14224                 pm->min_extents[i] = m.min_extents[i];
14225                 pm->max_extents[i] = m.max_extents[i];
14226             }
14227         }
14228 
14229         /* Read raw data */
14230         if (SILO_Globals.dataReadMask & DBPMCoords)
14231         {
14232             for (i=0; i<m.ndims; i++) {
14233                 pm->coords[i] = db_hdf5_comprd(dbfile, m.coord[i], 0);
14234             }
14235         }
14236         if (SILO_Globals.dataReadMask & DBPMGlobNodeNo)
14237             pm->gnodeno = db_hdf5_comprd(dbfile, m.gnodeno, 1);
14238         pm->gnznodtype = m.gnznodtype?m.gnznodtype:DB_INT;
14239 
14240         if (SILO_Globals.dataReadMask & DBPMGhostNodeLabels)
14241         {
14242             pm->ghost_node_labels = (char *)db_hdf5_comprd(dbfile, m.ghost_node_labels, 0);
14243         }
14244 
14245         /* alternate node number variables */
14246         {
14247             int nvars = -1;
14248             char *tmpnames = (char *)db_hdf5_comprd(dbfile, m.alt_nodenum_vars, 1);
14249             if (tmpnames)
14250                 pm->alt_nodenum_vars = DBStringListToStringArray(tmpnames, &nvars, !skipFirstSemicolon);
14251             FREE(tmpnames);
14252         }
14253 
14254         H5Tclose(o);
14255     } CLEANUP {
14256         H5E_BEGIN_TRY {
14257             H5Aclose(attr);
14258             H5Tclose(o);
14259         } H5E_END_TRY;
14260         DBFreePointmesh(pm);
14261     } END_PROTECT;
14262     return pm;
14263 }
14264 
14265 /*-------------------------------------------------------------------------
14266  * Function:    db_hdf5_PutPointvar
14267  *
14268  * Purpose:     Write a pointvar object to the file.
14269  *
14270  * Return:      Success:        0
14271  *
14272  *              Failure:        -1
14273  *
14274  * Programmer:  Robb Matzke
14275  *              Wednesday, April  7, 1999
14276  *
14277  * Modifications:
14278  *
14279  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
14280  *   Added Hack to make HDF5 driver deal with cycle/time same as PDB driver
14281  *
14282  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
14283  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
14284  *
14285  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
14286  *   Added support for conserved/extensive options.
14287  *
14288  *   Mark C. Miller, Thu Feb  4 11:25:00 PST 2010
14289  *   Refactored logic to handle time, dtime and cycle to a new method,
14290  *   db_hdf5_handle_ctdt().
14291  *-------------------------------------------------------------------------
14292  */
14293 SILO_CALLBACK int
db_hdf5_PutPointvar(DBfile * _dbfile,char const * name,char const * meshname,int nvars,DBVCP2_t _vars,int nels,int datatype,DBoptlist const * optlist)14294 db_hdf5_PutPointvar(DBfile *_dbfile, char const *name, char const *meshname, int nvars,
14295                     DBVCP2_t _vars, int nels, int datatype, DBoptlist const *optlist)
14296 {
14297     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14298     DBpointvar_mt       m;
14299     int                 i, saved_ndims;
14300     char               *s = 0;
14301     void const * const *vars = (void const * const *) _vars;
14302 
14303     memset(&m, 0, sizeof m);
14304     PROTECT {
14305         /* Set global options */
14306         saved_ndims = _pm._ndims;
14307         memset(&_pm, 0, sizeof _pm);
14308         _pm._ndims = saved_ndims;
14309         _pm._group_no = -1;
14310         _pm._missing_value = DB_MISSING_VALUE_NOT_SET;
14311         db_ProcessOptlist(DB_POINTMESH, optlist);
14312         _pm._nels = nels;
14313         _pm._minindex = _pm._lo_offset;
14314         _pm._maxindex = nels - _pm._hi_offset - 1;
14315 
14316         if (nvars>MAX_VARS) {
14317             db_perror("too many variables", E_BADARGS, "db_hdf5_PutPointvar");
14318             UNWIND();
14319         }
14320 
14321         /* hack to maintain backward compatibility with pdb driver */
14322         db_hdf5_handle_ctdt(dbfile, _pm._time_set, _pm._time,
14323             _pm._dtime_set, _pm._dtime, _pm._cycle);
14324 
14325         /* Write raw data arrays */
14326         for (i=0; i<nvars && nels; i++) {
14327             db_hdf5_compwr(dbfile, datatype, 1, &nels, vars[i],
14328                 m.data[i]/*out*/, friendly_name(name, nvars==1?"_data":"%d_data", &i));
14329         }
14330 
14331         /* output mrgtree info if we have it */
14332         if (_pm._region_pnames != NULL) {
14333             int len;
14334             DBStringArrayToStringList((char const * const *)_pm._region_pnames, -1, &s, &len);
14335             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.region_pnames/*out*/,
14336                 friendly_name(name, "_region_pnames", 0));
14337             FREE(s);
14338         }
14339 
14340         /* Build header in memory */
14341         m.nvals = nvars;
14342         m.nels = nels;
14343         m.ndims = _pm._ndims;
14344         m.nspace = _pm._nspace;
14345         m.origin = _pm._origin;
14346         m.min_index = _pm._minindex;
14347         m.max_index = _pm._maxindex;
14348         m.cycle = _pm._cycle;
14349         m.guihide = _pm._guihide;
14350         m.time = _pm._time;
14351         m.dtime = _pm._dtime;
14352         m.ascii_labels = _pm._ascii_labels;
14353         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
14354         m.conserved = _pm._conserved;
14355         m.extensive = _pm._extensive;
14356         db_SetMissingValueForPut(m.missing_value, _pm._missing_value);
14357         strcpy(m.meshid, OPT(meshname));
14358         strcpy(m.label, OPT(_pm._label));
14359         strcpy(m.units, OPT(_pm._unit));
14360 
14361         /* Write header to file */
14362         STRUCT(DBpointvar) {
14363             if (m.nvals)        MEMBER_S(int, nvals);
14364             if (m.nels)         MEMBER_S(int, nels);
14365             if (m.ndims)        MEMBER_S(int, ndims);
14366             if (m.nspace)       MEMBER_S(int, nspace);
14367             if (m.origin)       MEMBER_S(int, origin);
14368             if (m.datatype)     MEMBER_S(int, datatype);
14369             if (m.min_index)    MEMBER_S(int, min_index);
14370             if (m.max_index)    MEMBER_S(int, max_index);
14371             if (m.cycle)        MEMBER_S(int, cycle);
14372             if (m.guihide)      MEMBER_S(int, guihide);
14373             if (m.ascii_labels) MEMBER_S(int, ascii_labels);
14374             if (_pm._time_set)  MEMBER_S(float, time);
14375             if (_pm._dtime_set) MEMBER_S(double, dtime);
14376             if (m.conserved)    MEMBER_S(int, conserved);
14377             if (m.extensive)    MEMBER_S(int, extensive);
14378             if (m.missing_value) MEMBER_S(double, missing_value);
14379             MEMBER_S(str(m.meshid), meshid);
14380             MEMBER_S(str(m.label), label);
14381             MEMBER_S(str(m.units), units);
14382             MEMBER_R(str(m.data[_j]), data, m.nvals);
14383             MEMBER_S(str(m.region_pnames), region_pnames);
14384         } OUTPUT(dbfile, DB_POINTVAR, name, &m);
14385 
14386     } CLEANUP {
14387         /*void*/
14388     } END_PROTECT;
14389     return 0;
14390 }
14391 
14392 /*-------------------------------------------------------------------------
14393  * Function:    db_hdf5_GetPointvar
14394  *
14395  * Purpose:     Reads a pointvar object from the file.
14396  *
14397  * Return:      Success:        Ptr to new pointvar object.
14398  *
14399  *              Failure:        NULL
14400  *
14401  * Programmer:  Robb Matzke
14402  *              Thursday, April  8, 1999
14403  *
14404  * Modifications:
14405  *
14406  *   Mark C. Miller, Thu Jul 29 11:26:24 PDT 2004
14407  *   Made it set datatype correctly. Added support for dataReadMask
14408  *
14409  *   Mark C. Miller, Thu Nov  5 16:15:49 PST 2009
14410  *   Added support for conserved/extensive options.
14411  *
14412  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
14413  *   Added logic to control behavior of slash character swapping for
14414  *   windows/linux and skipping of first semicolon in calls to
14415  *   db_StringListToStringArray.
14416  *-------------------------------------------------------------------------
14417  */
14418 SILO_CALLBACK DBmeshvar *
db_hdf5_GetPointvar(DBfile * _dbfile,char const * name)14419 db_hdf5_GetPointvar(DBfile *_dbfile, char const *name)
14420 {
14421     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14422     static char         *me = "db_hdf5_GetPointvar";
14423     char                *s = 0;
14424     hid_t               o=-1, attr=-1;
14425     int                 _objtype, i;
14426     DBpointvar_mt       m;
14427     DBmeshvar           *pv=NULL;
14428 
14429     PROTECT {
14430         /* Open object and make sure it's a pointvar */
14431         if ((o=H5Topen(dbfile->cwg, name))<0) {
14432             db_perror(name, E_NOTFOUND, me);
14433             UNWIND();
14434         }
14435         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
14436             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
14437             H5Aclose(attr)<0) {
14438             db_perror(name, E_CALLFAIL, me);
14439             UNWIND();
14440         }
14441         if (DB_POINTVAR!=(DBObjectType)_objtype) {
14442             db_perror(name, E_CALLFAIL, me);
14443             UNWIND();
14444         }
14445 
14446         /* Read meta data into memory */
14447         memset(&m, 0, sizeof m);
14448         if ((attr=H5Aopen_name(o, "silo"))<0 ||
14449             H5Aread(attr, DBpointvar_mt5, &m)<0 ||
14450             H5Aclose(attr)<0) {
14451             db_perror(name, E_CALLFAIL, me);
14452             UNWIND();
14453         }
14454 
14455         /* Create object and initialize meta data */
14456         if (NULL==(pv=DBAllocMeshvar())) return NULL;
14457         pv->name = BASEDUP(name);
14458         pv->units = OPTDUP(m.units);
14459         pv->meshname = OPTDUP(m.meshid);
14460         pv->label = OPTDUP(m.label);
14461         pv->cycle = m.cycle;
14462         if ((pv->datatype = db_hdf5_GetVarType(_dbfile, m.data[0])) < 0)
14463             pv->datatype = silo2silo_type(m.datatype);
14464         if (force_single_g) pv->datatype = DB_FLOAT;
14465         pv->nels = m.nels;
14466         pv->nvals = m.nvals;
14467         pv->nspace = m.nspace;
14468         pv->ndims = m.ndims;
14469         pv->origin = m.origin;
14470         pv->time = m.time;
14471         pv->dtime = m.dtime;
14472         pv->min_index[0] = m.min_index;
14473         pv->max_index[0] = m.max_index;
14474         pv->guihide = m.guihide;
14475         pv->ascii_labels = m.ascii_labels;
14476         pv->conserved = m.conserved;
14477         pv->extensive = m.extensive;
14478         db_SetMissingValueForGet(pv->missing_value, m.missing_value);
14479 
14480         if (pv->nvals>MAX_VARS) {
14481             db_perror("too many variables", E_BADARGS, me);
14482             UNWIND();
14483         }
14484 
14485         /* Read raw data */
14486         if (SILO_Globals.dataReadMask & DBPVData && m.nvals && m.nels)
14487         {
14488             pv->vals = (void **)calloc(m.nvals, sizeof(void*));
14489             for (i=0; i<m.nvals; i++) {
14490                 pv->vals[i] = db_hdf5_comprd(dbfile, m.data[i], 0);
14491             }
14492         }
14493 
14494         s = (char *)db_hdf5_comprd(dbfile, m.region_pnames, 1);
14495         if (s) pv->region_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
14496         FREE(s);
14497 
14498         H5Tclose(o);
14499     } CLEANUP {
14500         H5E_BEGIN_TRY {
14501             H5Aclose(attr);
14502             H5Tclose(o);
14503         } H5E_END_TRY;
14504         DBFreeMeshvar(pv);
14505     } END_PROTECT;
14506     return pv;
14507 }
14508 
14509 /*-------------------------------------------------------------------------
14510  * Function:    db_hdf5_PutCompoundarray
14511  *
14512  * Purpose:     Writes a compound array object to the file.
14513  *
14514  * Return:      Success:        0
14515  *
14516  *              Failure:        -1
14517  *
14518  * Programmer:  Robb Matzke
14519  *              Thursday, April  8, 1999
14520  *
14521  * Modifications:
14522  *
14523  *   Mark C. Miller, Thu Apr 19 19:16:11 PDT 2007
14524  *   Modifed db_hdf5_compwr interface for friendly hdf5 dataset names
14525  *-------------------------------------------------------------------------
14526  */
14527 /*ARGSUSED*/
14528 SILO_CALLBACK int
db_hdf5_PutCompoundarray(DBfile * _dbfile,char const * name,char const * const * elmtnames,int const * elmtlen,int nelmts,void const * values,int nvalues,int datatype,DBoptlist const * optlist)14529 db_hdf5_PutCompoundarray(
14530     DBfile *_dbfile,
14531     char const *name,
14532     char const * const *elmtnames,
14533     int const *elmtlen,
14534     int nelmts,
14535     void const *values,
14536     int nvalues,
14537     int datatype,
14538     DBoptlist const *optlist
14539 )
14540 {
14541     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14542     DBcompoundarray_mt  m;
14543     int                 i, len;
14544     char                *s=NULL;
14545 
14546     memset(&m, 0, sizeof m);
14547     PROTECT {
14548         /*
14549          * Create a character string which is a semi-colon separated list of
14550          * component names.
14551          */
14552         for (i=len=0; i<nelmts; i++) len += strlen(elmtnames[i])+1;
14553         s = (char *)malloc(len+1);
14554         for (i=len=0; i<nelmts; i++) {
14555             if (i) s[len++] = ';';
14556             strcpy(s+len, elmtnames[i]);
14557             len += strlen(elmtnames[i]);
14558         }
14559         len++; /*count null*/
14560 
14561         /* Write raw data arrays */
14562         db_hdf5_compwr(dbfile, datatype, 1, &nvalues, values, m.values,
14563             friendly_name(name, "_values", 0));
14564         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.elemnames,
14565             friendly_name(name, "_elemnames", 0));
14566         db_hdf5_compwr(dbfile, DB_INT, 1, &nelmts, elmtlen, m.elemlengths,
14567             friendly_name(name, "_elemlengths", 0));
14568 
14569         /* Initialize meta data */
14570         m.nelems = nelmts;
14571         m.nvalues = nvalues;
14572         m.datatype = (DB_FLOAT==datatype || DB_DOUBLE==datatype)?0:datatype;
14573 
14574         /* Write meta data to file */
14575         STRUCT(DBcompoundarray) {
14576             if (m.nelems)       MEMBER_S(int, nelems);
14577             if (m.nvalues)      MEMBER_S(int, nvalues);
14578             if (m.datatype)     MEMBER_S(int, datatype);
14579             MEMBER_S(str(m.values), values);
14580             MEMBER_S(str(m.elemnames), elemnames);
14581             MEMBER_S(str(m.elemlengths), elemlengths);
14582         } OUTPUT(dbfile, DB_ARRAY, name, &m);
14583 
14584         /* Free resources */
14585         FREE(s);
14586 
14587     } CLEANUP {
14588         FREE(s);
14589     } END_PROTECT;
14590     return 0;
14591 }
14592 
14593 /*-------------------------------------------------------------------------
14594  * Function:    db_hdf5_GetCompoundarray
14595  *
14596  * Purpose:     Reads a compound array object from the file.
14597  *
14598  * Return:      Success:        Ptr to new compound array.
14599  *
14600  *              Failure:        NULL
14601  *
14602  * Programmer:  Robb Matzke
14603  *              Thursday, April  8, 1999
14604  *
14605  * Modifications:
14606  *
14607  *   Mark C. Miller, Mon Aug  2 15:06:57 PDT 2004
14608  *   Made it set datatype correctly
14609  *
14610  *-------------------------------------------------------------------------
14611  */
14612 SILO_CALLBACK DBcompoundarray *
db_hdf5_GetCompoundarray(DBfile * _dbfile,char const * name)14613 db_hdf5_GetCompoundarray(DBfile *_dbfile, char const *name)
14614 {
14615     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14616     static char         *me = "db_hdf5_GetCompoundarray";
14617     hid_t               o=-1, attr=-1;
14618     int                 _objtype, i;
14619     DBcompoundarray_mt m;
14620     DBcompoundarray     *ca=NULL;
14621     char                *s=NULL;
14622 
14623     PROTECT {
14624         /* Open object and make sure it's a compund array */
14625         if ((o=H5Topen(dbfile->cwg, name))<0) {
14626             db_perror(name, E_NOTFOUND, me);
14627             UNWIND();
14628         }
14629         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
14630             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
14631             H5Aclose(attr)<0) {
14632             db_perror(name, E_CALLFAIL, me);
14633             UNWIND();
14634         }
14635         if (DB_ARRAY!=(DBObjectType)_objtype) {
14636             db_perror(name, E_CALLFAIL, me);
14637             UNWIND();
14638         }
14639 
14640         /* Read meta data into memory */
14641         memset(&m, 0, sizeof m);
14642         if ((attr=H5Aopen_name(o, "silo"))<0 ||
14643             H5Aread(attr, DBcompoundarray_mt5, &m)<0 ||
14644             H5Aclose(attr)<0) {
14645             db_perror(name, E_CALLFAIL, me);
14646             UNWIND();
14647         }
14648 
14649         /* Create object and initialize meta data */
14650         if (NULL==(ca=DBAllocCompoundarray())) return NULL;
14651         ca->name = BASEDUP(name);
14652         ca->nelems = m.nelems;
14653         ca->nvalues = m.nvalues;
14654         if ((ca->datatype = db_hdf5_GetVarType(_dbfile, m.values)) < 0)
14655             ca->datatype = silo2silo_type(m.datatype);
14656         if (force_single_g) ca->datatype = DB_FLOAT;
14657 
14658         /* Read the raw data */
14659         ca->elemlengths = (int *)db_hdf5_comprd(dbfile, m.elemlengths, 1);
14660         ca->values = db_hdf5_comprd(dbfile, m.values, 1);
14661         ca->elemnames = (char **)calloc(m.nelems, sizeof(char*));
14662         s = (char *)db_hdf5_comprd(dbfile, m.elemnames, 1);
14663         for (i=0; i<m.nelems; i++) {
14664             char *tok = strtok(i?NULL:s, ";");
14665             ca->elemnames[i] = STRDUP(tok);
14666         }
14667 
14668         H5Tclose(o);
14669         FREE(s);
14670 
14671     } CLEANUP {
14672         H5E_BEGIN_TRY {
14673             H5Aclose(attr);
14674             H5Tclose(o);
14675         } H5E_END_TRY;
14676         DBFreeCompoundarray(ca);
14677         FREE(s);
14678     } END_PROTECT;
14679     return ca;
14680 }
14681 
14682 /*-------------------------------------------------------------------------
14683  * Function:    db_hdf5_InqVarType
14684  *
14685  * Purpose:     Returns the object type for an object.
14686  *
14687  * Return:      Success:        Object type
14688  *
14689  *              Failure:        DB_INVALID_OBJECT
14690  *
14691  * Programmer:  Robb Matzke
14692  *              Thursday, April  8, 1999
14693  *
14694  * Modifications:
14695  *
14696  *   Mark C. Miller, Tue Feb  1 13:48:33 PST 2005
14697  *   Fixed return of variable type for case of QUAD_RECT | QUAD_CURV
14698  *
14699  *   Mark C. Miller, Mon Feb 14 20:16:50 PST 2005
14700  *   Undid fix above
14701  *
14702  *   Mark C. Miller, Wed Apr 20 16:05:23 PDT 2005
14703  *   Made it return DB_VARIABLE for any inquiry where it couldn't
14704  *   get actual variable type from the object
14705  *
14706  *   Mark C. Miller, Mon Jul 17 18:07:57 PDT 2006
14707  *   Improved fix, above, for inquries on "/.silo/#000XXXX" datasets
14708  *   for silex
14709  *
14710  *-------------------------------------------------------------------------
14711  */
14712 SILO_CALLBACK DBObjectType
db_hdf5_InqVarType(DBfile * _dbfile,char const * name)14713 db_hdf5_InqVarType(DBfile *_dbfile, char const *name)
14714 {
14715     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14716     static char         *me = "db_hdf5_InqVarType";
14717     hid_t               o=-1, attr=-1;
14718     int                 _objtype = DB_INVALID_OBJECT;
14719 
14720     PROTECT {
14721 
14722         /* Open object */
14723         if ((o=H5Topen(dbfile->cwg, name))<0) {
14724             if ((o=H5Gopen(dbfile->cwg, name))<0) {
14725                 _objtype = DB_VARIABLE;
14726             }
14727             else
14728             {
14729                 _objtype = DB_DIR;
14730                 H5Gclose(o);
14731             }
14732         }
14733         else
14734         {
14735             /* Read the `silo_type' attribute */
14736             if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
14737                 H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
14738                 H5Aclose(attr)<0) {
14739                 _objtype = DB_VARIABLE;
14740             }
14741             H5Tclose(o);
14742         }
14743 
14744     } CLEANUP {
14745         H5E_BEGIN_TRY {
14746             H5Aclose(attr);
14747             H5Tclose(o);
14748         } H5E_END_TRY;
14749     } END_PROTECT;
14750     return (DBObjectType)_objtype;
14751 }
14752 
14753 /*-------------------------------------------------------------------------
14754  * Function:    db_hdf5_InqMeshName
14755  *
14756  * Purpose:     Returns the name of the mesh with which the specified
14757  *              variable is associated.
14758  *
14759  * Bugs:        The user must pass a large enough buffer for the `meshname'
14760  *              argument. This function will never copy more than 1024 bytes
14761  *              into the `meshname' array, counting the null termination.
14762  *
14763  * Return:      Success:        0
14764  *
14765  *              Failure:        -1
14766  *
14767  * Programmer:  Robb Matzke
14768  *              Friday, April  9, 1999
14769  *
14770  * Modifications:
14771  *
14772  *   Mark C. Miller, Tue Oct 17 08:16:13 PDT 2006
14773  *   Made it try either "meshid" or "meshname" data members
14774  *
14775  *-------------------------------------------------------------------------
14776  */
14777 SILO_CALLBACK int
db_hdf5_InqMeshName(DBfile * _dbfile,char const * name,char * meshname)14778 db_hdf5_InqMeshName(DBfile *_dbfile, char const *name, char *meshname/*out*/)
14779 {
14780     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14781     static char         *me = "db_hdf5_InqMeshName";
14782     int                  pass;
14783 
14784     for (pass = 0; pass < 2; pass++)
14785     {
14786         char   s[1024];
14787         hid_t  o=-1, attr=-1, type=-1, str_type=-1;
14788 
14789         s[0] = '\0';
14790         PROTECT {
14791             /* Describe memory */
14792             if ((str_type=H5Tcopy(H5T_C_S1))<0 ||
14793                 H5Tset_size(str_type, sizeof s)<0 ||
14794                 (type=H5Tcreate(H5T_COMPOUND, sizeof s))<0 ||
14795                 db_hdf5_put_cmemb(type, pass==0?"meshid":"meshname",
14796                                   0, 0, NULL, str_type)<0) {
14797                 db_perror(name, E_CALLFAIL, me);
14798                 UNWIND();
14799             }
14800 
14801             /* Open variable */
14802             if ((o=H5Topen(dbfile->cwg, name))<0 ||
14803                 (attr=H5Aopen_name(o, "silo"))<0) {
14804                 db_perror(name, E_NOTFOUND, me);
14805                 UNWIND();
14806             }
14807 
14808             /*
14809              * Read "silo" attribute. If the read fails it's probably because
14810              * there is no "meshid" field in the attribute, in which case we
14811              * haven't opened a mesh variable and we should fail.
14812              */
14813             if (H5Aread(attr, type, s)<0) {
14814                 db_perror(name, E_CALLFAIL, me);
14815                 UNWIND();
14816             }
14817 
14818             /* Copy result to output buffer and release resources */
14819             strcpy(meshname, s);
14820             H5Aclose(attr);
14821             H5Tclose(type);
14822             H5Tclose(str_type);
14823             H5Tclose(o);
14824 
14825         } CLEANUP {
14826             H5E_BEGIN_TRY {
14827                 H5Aclose(attr);
14828                 H5Tclose(type);
14829                 H5Tclose(str_type);
14830                 H5Tclose(o);
14831             } H5E_END_TRY;
14832         } END_PROTECT;
14833 
14834         if (s[0] != '\0')
14835             break;
14836     }
14837     return 0;
14838 }
14839 
14840 /*-------------------------------------------------------------------------
14841  * Function:    db_hdf5_PutMrgtree
14842  *
14843  * Purpose:     Write a mesh region grouping tree to a file.
14844  *
14845  * Programmer: Mark C. Miller
14846  *-------------------------------------------------------------------------
14847  */
14848 SILO_CALLBACK int
db_hdf5_PutMrgtree(DBfile * _dbfile,char const * name,char const * mesh_name,DBmrgtree const * tree,DBoptlist const * opts)14849 db_hdf5_PutMrgtree(DBfile *_dbfile, char const *name, char const *mesh_name,
14850     DBmrgtree const *tree, DBoptlist const *opts)
14851 {
14852     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
14853     DBmrgtree_mt        m;
14854     int                 i, j, n, len, pass, num_nodes = tree->num_nodes;
14855     int                 tot_children, tot_segs;
14856     char               *s = 0;
14857     DBmrgtnode        **ltree = 0;
14858     char              **strArray = 0;
14859     int                *intArray = 0;
14860 
14861     memset(&m, 0, sizeof m);
14862     PROTECT {
14863 
14864         /* Set global options */
14865         db_ResetGlobalData_Mrgtree();
14866         db_ProcessOptlist(DB_MRGTREE, opts);
14867 
14868         /* allocate an emtpy, linearized list of tree node pointers */
14869         ltree = (DBmrgtnode **) malloc(num_nodes * sizeof(DBmrgtnode*));
14870 
14871         /* walk tree to populate the linearized list of nodes ptrs */
14872         DBWalkMrgtree(tree, (DBmrgwalkcb) DBLinearizeMrgtree, ltree, DB_POSTORDER);
14873 
14874         /* form an array of the integer, scalar data at each node */
14875         intArray = (int *) malloc(num_nodes * sizeof(int) * 6);
14876         for (i = 0; i < num_nodes; i++)
14877         {
14878             intArray[i*6+0] = ltree[i]->narray;
14879             intArray[i*6+1] = ltree[i]->type_info_bits;
14880             intArray[i*6+2] = ltree[i]->max_children;
14881             intArray[i*6+3] = ltree[i]->nsegs;
14882             intArray[i*6+4] = ltree[i]->num_children;
14883             intArray[i*6+5] = ltree[i] != tree->root ? ltree[i]->parent->walk_order : -1;
14884         }
14885         len = num_nodes * 6;
14886         db_hdf5_compwr(dbfile, DB_INT, 1, &len, intArray,
14887             m.n_scalars/*out*/, friendly_name(name,"_scalars", 0));
14888         FREE(intArray);
14889 
14890         /* form an array of strings of the name data member */
14891         strArray = (char **) malloc(num_nodes * sizeof(char *));
14892         for (i = 0; i < num_nodes; i++)
14893             strArray[i] = ltree[i]->name;
14894 
14895         /* output all the node names as one long dataset */
14896         s = 0;
14897         DBStringArrayToStringList((char const * const *)strArray, num_nodes, &s, &len);
14898         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.n_name/*out*/,
14899             friendly_name(name, "_name", 0));
14900         FREE(s);
14901         FREE(strArray);
14902 
14903         /* form an array of strings of names data member */
14904         /* requires 2 passes; first pass only counts, 2nd pass builds the array */
14905         for (pass = 0; pass < 2; pass ++)
14906         {
14907             if (pass == 1)
14908             {
14909                 if (n == 0)
14910                     break;
14911                 strArray = (char **) malloc(n * sizeof(char *));
14912             }
14913             n = 0;
14914             for (i = 0; i < num_nodes; i++)
14915             {
14916                 if (ltree[i]->narray > 0)
14917                 {
14918                     if (strchr(ltree[i]->names[0], '%') == 0)
14919                     {
14920                         for (j = 0; j < ltree[i]->narray; j++)
14921                         {
14922                             if (pass == 1)
14923                                 strArray[n] = ltree[i]->names[j];
14924                             n++;
14925                         }
14926                     }
14927                     else
14928                     {
14929                         if (pass == 1)
14930                             strArray[n] = ltree[i]->names[0];
14931                         n++;
14932                     }
14933                 }
14934             }
14935         }
14936         if (n > 0)
14937         {
14938             s = 0;
14939             DBStringArrayToStringList((char const * const *)strArray, n, &s, &len);
14940             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.n_names/*out*/,
14941                 friendly_name(name, "_names", 0));
14942             FREE(s);
14943             FREE(strArray);
14944         }
14945 
14946         /* linearize and output map name data */
14947         strArray = (char **) malloc(num_nodes * sizeof(char*));
14948         for (i = 0; i < num_nodes; i++)
14949             strArray[i] = ltree[i]->maps_name;
14950         s = 0;
14951         len = 0;
14952         DBStringArrayToStringList((char const * const *)strArray, num_nodes, &s, &len);
14953         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.n_maps_name/*out*/,
14954             friendly_name(name, "_maps_name", 0));
14955         FREE(s);
14956         FREE(strArray);
14957 
14958         tot_segs = 0;
14959         for (i = 0; i < num_nodes; i++)
14960             tot_segs += ltree[i]->nsegs * (ltree[i]->narray?ltree[i]->narray:1);
14961 
14962         /* linearize and output map segment id data */
14963         if (tot_segs)
14964         {
14965             intArray = (int *) malloc(tot_segs * sizeof(int));
14966             n = 0;
14967             for (i = 0; i < num_nodes; i++)
14968                 for (j = 0; j < ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1); j++)
14969                     intArray[n++] = ltree[i]->seg_ids[j];
14970             db_hdf5_compwr(dbfile, DB_INT, 1, &tot_segs, intArray,
14971                 m.n_seg_ids/*out*/, friendly_name(name,"_seg_ids", 0));
14972             FREE(intArray);
14973 
14974             /* linearize and output seg len type data */
14975             intArray = (int *) malloc(tot_segs * sizeof(int));
14976             n = 0;
14977             for (i = 0; i < num_nodes; i++)
14978                 for (j = 0; j < ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1); j++)
14979                     intArray[n++] = ltree[i]->seg_lens[j];
14980             db_hdf5_compwr(dbfile, DB_INT, 1, &tot_segs, intArray,
14981                 m.n_seg_lens/*out*/, friendly_name(name,"_seg_lens", 0));
14982             FREE(intArray);
14983 
14984             /* linearize and output seg type data */
14985             intArray = (int *) malloc(tot_segs * sizeof(int));
14986             n = 0;
14987             for (i = 0; i < num_nodes; i++)
14988                 for (j = 0; j < ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1); j++)
14989                     intArray[n++] = ltree[i]->seg_types[j];
14990             db_hdf5_compwr(dbfile, DB_INT, 1, &tot_segs, intArray,
14991                 m.n_seg_types/*out*/, friendly_name(name,"_seg_types", 0));
14992             FREE(intArray);
14993         }
14994 
14995         /* form integer array for children data */
14996         tot_children = 0;
14997         for (i = 0; i < num_nodes; i++)
14998             tot_children += ltree[i]->num_children;
14999         if (tot_children)
15000         {
15001             intArray = (int *) malloc(tot_children * sizeof(int));
15002             n = 0;
15003             for (i = 0; i < num_nodes; i++)
15004                 for (j = 0; j < ltree[i]->num_children; j++)
15005                     intArray[n++] = ltree[i]->children[j]->walk_order;
15006             db_hdf5_compwr(dbfile, DB_INT, 1, &tot_children, intArray,
15007                 m.n_children/*out*/, friendly_name(name,"_children", 0));
15008             FREE(intArray);
15009         }
15010 
15011         FREE(ltree);
15012 
15013         if (_mrgt._mrgvar_onames)
15014         {
15015             s = 0;
15016             len = 0;
15017             DBStringArrayToStringList((char const * const *)_mrgt._mrgvar_onames, -1, &s, &len);
15018             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.mrgvar_onames/*out*/,
15019                 friendly_name(name, "_mrgvar_onames", 0));
15020             FREE(s);
15021         }
15022 
15023         if (_mrgt._mrgvar_rnames)
15024         {
15025             s = 0;
15026             len = 0;
15027             DBStringArrayToStringList((char const * const *)_mrgt._mrgvar_rnames, -1, &s, &len);
15028             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.mrgvar_rnames/*out*/,
15029                 friendly_name(name, "_mrgvar_rnames", 0));
15030             FREE(s);
15031         }
15032 
15033         /* Build header in memory */
15034         m.src_mesh_type = tree->src_mesh_type;
15035         strcpy(m.src_mesh_name, OPT(mesh_name));
15036         m.type_info_bits = tree->type_info_bits;
15037         m.num_nodes = tree->num_nodes;
15038         m.root = tree->root->walk_order;
15039 
15040         /* Write header to file */
15041         STRUCT(DBmrgtree) {
15042             if (m.src_mesh_type)    MEMBER_S(int, src_mesh_type);
15043             MEMBER_S(str(m.src_mesh_name), src_mesh_name);
15044             if (m.type_info_bits)   MEMBER_S(int, type_info_bits);
15045             if (m.num_nodes)        MEMBER_S(int, num_nodes);
15046             MEMBER_S(int, root);
15047             MEMBER_S(str(m.n_scalars), n_scalars);
15048             MEMBER_S(str(m.n_name), n_name);
15049             MEMBER_S(str(m.n_names), n_names);
15050             MEMBER_S(str(m.n_maps_name), n_maps_name);
15051             MEMBER_S(str(m.n_seg_ids), n_seg_ids);
15052             MEMBER_S(str(m.n_seg_lens), n_seg_lens);
15053             MEMBER_S(str(m.n_seg_types), n_seg_types);
15054             MEMBER_S(str(m.n_children), n_children);
15055             MEMBER_S(str(m.mrgvar_onames), mrgvar_onames);
15056             MEMBER_S(str(m.mrgvar_rnames), mrgvar_rnames);
15057         } OUTPUT(dbfile, DB_MRGTREE, name, &m);
15058 
15059     } CLEANUP {
15060         FREE(ltree);
15061         FREE(intArray);
15062         FREE(strArray);
15063         FREE(s);
15064     } END_PROTECT;
15065     return 0;
15066 }
15067 
15068 /*-------------------------------------------------------------------------
15069  * Function:    db_hdf5_GetMrgtree
15070  *
15071  * Purpose:     Read a mesh region grouping tree from a file.
15072  *
15073  * Programmer: Mark C. Miller
15074  *
15075  * Modifications:
15076  *
15077  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
15078  *   Added logic to control behavior of slash character swapping for
15079  *   windows/linux and skipping of first semicolon in calls to
15080  *   db_StringListToStringArray.
15081  *-------------------------------------------------------------------------
15082  */
15083 SILO_CALLBACK DBmrgtree *
db_hdf5_GetMrgtree(DBfile * _dbfile,char const * name)15084 db_hdf5_GetMrgtree(DBfile *_dbfile, char const *name)
15085 {
15086     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
15087     static char         *me = "db_hdf5_GetMrgtree";
15088     hid_t               o=-1, attr=-1;
15089     int                 _objtype, i, j, n, num_nodes;
15090     DBmrgtree_mt         m;
15091     int                 *intArray = 0;
15092     char               **strArray = 0;
15093     DBmrgtnode         **ltree = 0;
15094     char                *s = 0;
15095     DBmrgtree           *tree = 0;
15096 
15097     PROTECT {
15098         /* Open object and make sure it's a material */
15099         if ((o=H5Topen(dbfile->cwg, name))<0) {
15100             db_perror(name, E_NOTFOUND, me);
15101             UNWIND();
15102         }
15103         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
15104             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
15105             H5Aclose(attr)<0) {
15106             db_perror(name, E_CALLFAIL, me);
15107             UNWIND();
15108         }
15109         if (DB_MRGTREE!=(DBObjectType)_objtype) {
15110             db_perror(name, E_CALLFAIL, me);
15111             UNWIND();
15112         }
15113 
15114         /* Read meta data into memory */
15115         memset(&m, 0, sizeof m);
15116         if ((attr=H5Aopen_name(o, "silo"))<0 ||
15117             H5Aread(attr, DBmrgtree_mt5, &m)<0 ||
15118             H5Aclose(attr)<0) {
15119             db_perror(name, E_CALLFAIL, me);
15120             UNWIND();
15121         }
15122 
15123         /* Create object and initialize meta data */
15124         tree = (DBmrgtree*) malloc(sizeof(DBmrgtree));
15125         memset(tree, 0, sizeof(DBmrgtree));
15126         tree->name = BASEDUP(name);
15127         tree->src_mesh_name = OPTDUP(m.src_mesh_name);
15128         tree->type_info_bits = m.type_info_bits;
15129         tree->num_nodes = m.num_nodes;
15130         num_nodes = m.num_nodes;
15131         tree->root = 0;
15132         tree->cwr = 0;
15133 
15134         /* allocate all the nodes of the tree and a linear list of pointers
15135            to them */
15136         ltree = (DBmrgtnode **) malloc(num_nodes * sizeof(DBmrgtnode*));
15137         for (i = 0; i < num_nodes; i++)
15138             ltree[i] = (DBmrgtnode *) calloc(1,sizeof(DBmrgtnode));
15139 
15140         /* Read the nodal scalar data */
15141         intArray = (int *)db_hdf5_comprd(dbfile, m.n_scalars, 1);
15142         for (i = 0; (i < num_nodes) && intArray; i++)
15143         {
15144             ltree[i]->narray           = intArray[i*6+0];
15145             ltree[i]->type_info_bits   = intArray[i*6+1];
15146             ltree[i]->max_children     = intArray[i*6+2];
15147             ltree[i]->nsegs            = intArray[i*6+3];
15148             ltree[i]->num_children     = intArray[i*6+4];
15149             ltree[i]->parent           = intArray[i*6+5] >= 0 ? ltree[intArray[i*6+5]] : 0;
15150         }
15151         FREE(intArray);
15152 
15153         /* read the node 'name' member */
15154         s = (char *)db_hdf5_comprd(dbfile, m.n_name, 1);
15155         strArray = DBStringListToStringArray(s, &num_nodes, !skipFirstSemicolon);
15156         for (i = 0; (i < num_nodes) && strArray; i++)
15157             ltree[i]->name = strArray[i];
15158         FREE(s);
15159         FREE(strArray); /* free only top-level array of pointers */
15160 
15161         /* read the node 'names' member */
15162         s = (char *)db_hdf5_comprd(dbfile, m.n_names, 1);
15163         if (s)
15164         {
15165             strArray = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
15166             n = 0;
15167             for (i = 0; i < num_nodes; i++)
15168             {
15169                 if (ltree[i]->narray == 0)
15170                     continue;
15171 
15172                 if (strchr(strArray[n], '%') == 0)
15173                 {
15174                     ltree[i]->names = (char**) malloc(ltree[i]->narray * sizeof(char*));
15175                     for (j = 0; j < ltree[i]->narray; j++, n++)
15176                         ltree[i]->names[j] = strArray[n];
15177                 }
15178                 else
15179                 {
15180                     ltree[i]->names = (char**) malloc(1 * sizeof(char*));
15181                     ltree[i]->names[0] = strArray[n];
15182                     n++;
15183                 }
15184             }
15185         }
15186         FREE(s);
15187         FREE(strArray); /* free only top-level array of pointers */
15188 
15189         /* read the maps_name data */
15190         s = (char *)db_hdf5_comprd(dbfile, m.n_maps_name, 1);
15191         strArray = DBStringListToStringArray(s, &num_nodes, !skipFirstSemicolon);
15192         for (i = 0; i < num_nodes; i++)
15193             ltree[i]->maps_name = strArray[i];
15194         FREE(s);
15195         FREE(strArray); /* free only top-level array of pointers */
15196 
15197         /* read the map segment id data */
15198         intArray = (int *)db_hdf5_comprd(dbfile, m.n_seg_ids, 1);
15199         n = 0;
15200         for (i = 0; (i < num_nodes) && intArray; i++)
15201         {
15202             int ns = ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1);
15203             if (ns > 0)
15204             {
15205                 ltree[i]->seg_ids = (int*) malloc(ns * sizeof(int));
15206                 for (j = 0; j < ns; j++)
15207                     ltree[i]->seg_ids[j] = intArray[n++];
15208             }
15209         }
15210         FREE(intArray);
15211 
15212         /* read the map segment len data */
15213         intArray = (int *)db_hdf5_comprd(dbfile, m.n_seg_lens, 1);
15214         n = 0;
15215         for (i = 0; (i < num_nodes) && intArray; i++)
15216         {
15217             int ns = ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1);
15218             if (ns > 0)
15219             {
15220                 ltree[i]->seg_lens = (int*) malloc(ns * sizeof(int));
15221                 for (j = 0; j < ns; j++)
15222                     ltree[i]->seg_lens[j] = intArray[n++];
15223             }
15224         }
15225         FREE(intArray);
15226 
15227         /* read the map segment type data */
15228         intArray = (int *)db_hdf5_comprd(dbfile, m.n_seg_types, 1);
15229         n = 0;
15230         for (i = 0; (i < num_nodes) && intArray; i++)
15231         {
15232             int ns = ltree[i]->nsegs*(ltree[i]->narray?ltree[i]->narray:1);
15233             if (ns > 0)
15234             {
15235                 ltree[i]->seg_types = (int*) malloc(ns * sizeof(int));
15236                 for (j = 0; j < ns; j++)
15237                     ltree[i]->seg_types[j] = intArray[n++];
15238             }
15239         }
15240         FREE(intArray);
15241 
15242         /* read the child ids */
15243         intArray = (int *)db_hdf5_comprd(dbfile, m.n_children, 1);
15244         n = 0;
15245         for (i = 0; (i < num_nodes) && intArray; i++)
15246         {
15247             int nc = ltree[i]->num_children;
15248             if (nc > 0)
15249             {
15250                 ltree[i]->children = (DBmrgtnode**) malloc(nc * sizeof(DBmrgtnode*));
15251                 for (j = 0; j < nc; j++)
15252                     ltree[i]->children[j] = ltree[intArray[n++]];
15253             }
15254         }
15255         FREE(intArray);
15256 
15257         s = (char *)db_hdf5_comprd(dbfile, m.mrgvar_onames, 1);
15258         if (s) tree->mrgvar_onames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
15259         FREE(s);
15260 
15261         s = (char *)db_hdf5_comprd(dbfile, m.mrgvar_rnames, 1);
15262         if (s) tree->mrgvar_rnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
15263         FREE(s);
15264 
15265         tree->root = ltree[m.root];
15266         tree->cwr = tree->root;
15267 
15268         H5Tclose(o);
15269         FREE(ltree);
15270 
15271     } CLEANUP {
15272         H5E_BEGIN_TRY {
15273             H5Aclose(attr);
15274             H5Tclose(o);
15275         } H5E_END_TRY;
15276         FREE(strArray);
15277         FREE(intArray);
15278         FREE(ltree);
15279         FREE(tree);
15280         FREE(s);
15281     } END_PROTECT;
15282 
15283     return tree;
15284 }
15285 
15286 /*-------------------------------------------------------------------------
15287  * Function:    db_hdf5_PutGroupelmap
15288  *
15289  * Purpose:     Write a grouping element map to a file.
15290  *
15291  * Programmer: Mark C. Miller
15292  *-------------------------------------------------------------------------
15293  */
15294 SILO_CALLBACK int
db_hdf5_PutGroupelmap(DBfile * _dbfile,char const * name,int num_segments,int const * groupel_types,int const * segment_lengths,int const * segment_ids,int const * const * segment_data,void const * const * segment_fracs,int fracs_data_type,DBoptlist const * opts)15295 db_hdf5_PutGroupelmap(DBfile *_dbfile, char const *name,
15296     int num_segments, int const *groupel_types, int const *segment_lengths,
15297     int const *segment_ids, int const * const *segment_data, void const * const *segment_fracs,
15298     int fracs_data_type, DBoptlist const *opts)
15299 {
15300     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
15301     DBgroupelmap_mt      m;
15302     int                  i, j, tot_len;
15303     int                *intArray;
15304     char               *s = NULL;
15305 
15306     memset(&m, 0, sizeof m);
15307     PROTECT {
15308         /* Set global options */
15309         db_ProcessOptlist(DB_GROUPELMAP, opts);
15310 
15311         /* Write raw data arrays */
15312         db_hdf5_compwr(dbfile, DB_INT, 1, &num_segments, groupel_types,
15313             m.groupel_types/*out*/, friendly_name(name,"_groupel_types", 0));
15314         db_hdf5_compwr(dbfile, DB_INT, 1, &num_segments, segment_lengths,
15315             m.segment_lengths/*out*/, friendly_name(name,"_segment_lengths", 0));
15316         if (segment_ids)
15317             db_hdf5_compwr(dbfile, DB_INT, 1, &num_segments, segment_ids,
15318                 m.segment_ids/*out*/, friendly_name(name,"_segment_ids", 0));
15319 
15320         tot_len = 0;
15321         for (i = 0; i < num_segments; i++)
15322             tot_len += segment_lengths[i];
15323         if (tot_len)
15324         {
15325             intArray = (int *) malloc(tot_len * sizeof(int));
15326             tot_len = 0;
15327             for (i = 0; i < num_segments; i++)
15328                 for (j = 0; j < segment_lengths[i]; j++)
15329                     intArray[tot_len++] = segment_data[i][j];
15330             db_hdf5_compwr(dbfile, DB_INT, 1, &tot_len, intArray,
15331                 m.segment_data/*out*/, friendly_name(name,"_segment_data", 0));
15332             FREE(intArray);
15333         }
15334 
15335         /* write out fractional data if we have it */
15336         if (segment_fracs)
15337         {
15338             void *fracsArray;
15339 
15340             /* write array of frac lengths */
15341             tot_len = 0;
15342             intArray = (int *) malloc(num_segments * sizeof(int));
15343             for (i = 0; i < num_segments; i++)
15344             {
15345                 int len = segment_fracs[i] == 0 ? 0 : segment_lengths[i];
15346                 intArray[i] = len;
15347                 tot_len += len;
15348             }
15349             db_hdf5_compwr(dbfile, DB_INT, 1, &num_segments, intArray,
15350                 m.frac_lengths/*out*/, friendly_name(name,"_frac_lengths", 0));
15351             FREE(intArray);
15352 
15353             /* build and write out fractional data array */
15354             fracsArray = (void *) malloc(tot_len * ((fracs_data_type==DB_FLOAT)?sizeof(float):sizeof(double)));
15355             tot_len = 0;
15356             for (i = 0; i < num_segments; i++)
15357             {
15358                 if (segment_fracs[i] == 0)
15359                     continue;
15360 
15361                 for (j = 0; j < segment_lengths[i]; j++)
15362                 {
15363                     if (fracs_data_type == DB_FLOAT)
15364                     {
15365                         float *pfa = (float *) fracsArray;
15366                         float *psf = (float *) segment_fracs[i];
15367                         pfa[tot_len++] = psf[j];
15368                     }
15369                     else
15370                     {
15371                         double *pfa = (double *) fracsArray;
15372                         double *psf = (double *) segment_fracs[i];
15373                         pfa[tot_len++] = psf[j];
15374                     }
15375                 }
15376             }
15377             db_hdf5_compwr(dbfile, fracs_data_type, 1, &tot_len, fracsArray,
15378                 m.segment_fracs/*out*/, friendly_name(name,"_segment_fracs", 0));
15379             FREE(fracsArray);
15380         }
15381 
15382         /* Build header in memory */
15383         m.num_segments = num_segments;
15384         m.fracs_data_type = (DB_FLOAT==fracs_data_type || DB_DOUBLE==fracs_data_type)?0:fracs_data_type;
15385 
15386         /* Write header to file */
15387         STRUCT(DBgroupelmap) {
15388             if (m.num_segments)    MEMBER_S(int, num_segments);
15389             if (m.fracs_data_type) MEMBER_S(int, fracs_data_type);
15390             MEMBER_S(str(m.groupel_types), groupel_types);
15391             MEMBER_S(str(m.segment_lengths), segment_lengths);
15392             MEMBER_S(str(m.segment_ids), segment_ids);
15393             MEMBER_S(str(m.segment_data), segment_data);
15394             MEMBER_S(str(m.frac_lengths), frac_lengths);
15395             MEMBER_S(str(m.segment_fracs), segment_fracs);
15396         } OUTPUT(dbfile, DB_GROUPELMAP, name, &m);
15397     } CLEANUP {
15398     } END_PROTECT;
15399     return 0;
15400 }
15401 
15402 /*-------------------------------------------------------------------------
15403  * Function:    db_hdf5_GetGroupelmap
15404  *
15405  * Purpose:     Read a grouping element map from a file.
15406  *
15407  * Programmer: Mark C. Miller
15408  *
15409  * Modifications:
15410  *
15411  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
15412  *   Added logic to control behavior of slash character swapping for
15413  *   windows/linux and skipping of first semicolon in calls to
15414  *   db_StringListToStringArray.
15415  *-------------------------------------------------------------------------
15416  */
15417 SILO_CALLBACK DBgroupelmap *
db_hdf5_GetGroupelmap(DBfile * _dbfile,char const * name)15418 db_hdf5_GetGroupelmap(DBfile *_dbfile, char const *name)
15419 {
15420     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
15421     static char         *me = "db_hdf5_GetGroupelmap";
15422     hid_t               o=-1, attr=-1;
15423     int                 _objtype, i, j, n;
15424     int                *intArray = 0;
15425     void               *fracsArray = 0;
15426     DBgroupelmap        *gm=NULL;
15427     DBgroupelmap_mt      m;
15428 
15429     PROTECT {
15430         /* Open object and make sure it's a material */
15431         if ((o=H5Topen(dbfile->cwg, name))<0) {
15432             db_perror(name, E_NOTFOUND, me);
15433             UNWIND();
15434         }
15435         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
15436             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
15437             H5Aclose(attr)<0) {
15438             db_perror(name, E_CALLFAIL, me);
15439             UNWIND();
15440         }
15441         if (DB_GROUPELMAP!=(DBObjectType)_objtype) {
15442             db_perror(name, E_CALLFAIL, me);
15443             UNWIND();
15444         }
15445 
15446         /* Read meta data into memory */
15447         memset(&m, 0, sizeof m);
15448         if ((attr=H5Aopen_name(o, "silo"))<0 ||
15449             H5Aread(attr, DBgroupelmap_mt5, &m)<0 ||
15450             H5Aclose(attr)<0) {
15451             db_perror(name, E_CALLFAIL, me);
15452             UNWIND();
15453         }
15454 
15455         /* Create object and initialize meta data */
15456         gm = (DBgroupelmap *) malloc(sizeof(DBgroupelmap));
15457         gm->name = BASEDUP(name);
15458         gm->num_segments = m.num_segments;
15459         if ((gm->fracs_data_type = db_hdf5_GetVarType(_dbfile, m.segment_fracs)) < 0)
15460             gm->fracs_data_type = DB_DOUBLE;  /* PDB driver assumes double */
15461         if (gm->fracs_data_type == DB_DOUBLE && force_single_g)
15462             gm->fracs_data_type = DB_FLOAT;
15463 
15464         /* Read the raw data */
15465         gm->groupel_types = (int *)db_hdf5_comprd(dbfile, m.groupel_types, 1);
15466         gm->segment_lengths = (int *)db_hdf5_comprd(dbfile, m.segment_lengths, 1);
15467         gm->segment_ids = (int *)db_hdf5_comprd(dbfile, m.segment_ids, 1);
15468 
15469         /* read the map segment data */
15470         gm->segment_data = (int **) malloc(m.num_segments * sizeof(int*));
15471         intArray = (int *)db_hdf5_comprd(dbfile, m.segment_data, 1);
15472         n = 0;
15473         for (i = 0; (i < m.num_segments) && intArray && gm->segment_lengths; i++)
15474         {
15475             int sl = gm->segment_lengths[i];
15476             gm->segment_data[i] = 0;
15477             if (sl > 0)
15478             {
15479                 gm->segment_data[i] = (int*) malloc(sl * sizeof(int));
15480                 for (j = 0; j < sl; j++)
15481                     gm->segment_data[i][j] = intArray[n++];
15482             }
15483         }
15484         FREE(intArray);
15485 
15486         intArray = (int *)db_hdf5_comprd(dbfile, m.frac_lengths, 1);
15487         if (intArray)
15488         {
15489             gm->segment_fracs = (void **)malloc(m.num_segments * sizeof(void*));
15490             fracsArray = db_hdf5_comprd(dbfile, m.segment_fracs, 1);
15491             n = 0;
15492             for (i = 0; (i < m.num_segments) && fracsArray; i++)
15493             {
15494                 int len = intArray[i];
15495 
15496                 if (len <= 0)
15497                 {
15498                     gm->segment_fracs[i] = 0;
15499                     continue;
15500                 }
15501 
15502                 gm->segment_fracs[i] = malloc(len * ((gm->fracs_data_type==DB_FLOAT)?sizeof(float):sizeof(double)));
15503                 for (j = 0; j < len; j++)
15504                 {
15505                     if (gm->fracs_data_type == DB_FLOAT)
15506                     {
15507                         float *pfa = (float *) fracsArray;
15508                         float *psf = (float *) gm->segment_fracs[i];
15509                         psf[j] = pfa[n++];
15510                     }
15511                     else
15512                     {
15513                         double *pfa = (double *) fracsArray;
15514                         double *psf = (double *) gm->segment_fracs[i];
15515                         psf[j] = pfa[n++];
15516                     }
15517                 }
15518             }
15519         }
15520         else
15521         {
15522             gm->segment_fracs = 0;
15523         }
15524         FREE(intArray);
15525         FREE(fracsArray);
15526 
15527         H5Tclose(o);
15528 
15529     } CLEANUP {
15530         H5E_BEGIN_TRY {
15531             H5Aclose(attr);
15532             H5Tclose(o);
15533         } H5E_END_TRY;
15534         FREE(intArray);
15535         FREE(fracsArray);
15536     } END_PROTECT;
15537 
15538     return gm;
15539 }
15540 
15541 /*-------------------------------------------------------------------------
15542  * Function:    db_hdf5_PutMrgvar
15543  *
15544  * Purpose:     Write an mrgvar to a file
15545  *
15546  * Programmer: Mark C. Miller
15547  *-------------------------------------------------------------------------
15548  */
15549 SILO_CALLBACK int
db_hdf5_PutMrgvar(DBfile * _dbfile,char const * name,char const * mrgt_name,int ncomps,char const * const * compnames,int nregns,char const * const * reg_pnames,int datatype,void const * const * data,DBoptlist const * optlist)15550 db_hdf5_PutMrgvar(DBfile *_dbfile, char const *name,
15551     char const *mrgt_name,
15552     int ncomps, char const * const *compnames,
15553     int nregns, char const * const *reg_pnames,
15554     int datatype, void const * const *data, DBoptlist const *optlist)
15555 {
15556     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
15557     static char         *me = "db_hdf5_PutMrgvar";
15558     char                *s = 0;
15559     int                 i, len, nstrs;
15560     DBmrgvar_mt         m;
15561 
15562     memset(&m, 0, sizeof m);
15563 
15564     PROTECT {
15565 
15566         db_ProcessOptlist(DB_MRGVAR, optlist);
15567 
15568         /* Write variable arrays */
15569         if (ncomps>MAX_VARS) {
15570             db_perror("too many variables", E_BADARGS, me);
15571             UNWIND();
15572         }
15573         for (i=0; i<ncomps; i++) {
15574             char tmpname[256];
15575             char const *p = tmpname;
15576             if (compnames)
15577                 sprintf(tmpname, "%s_%s", name, compnames[i]);
15578             else
15579                 sprintf(tmpname, "%s_comp%d", name, i);
15580             db_hdf5_compwr(dbfile, datatype, 1, &nregns, data[i],
15581                 m.data[i]/*out*/, friendly_name(p, "_data", 0));
15582         }
15583 
15584         /* output reg_pnames */
15585         nstrs = nregns;
15586         if (strchr(reg_pnames[0], '%') != 0)
15587             nstrs = 1;
15588         DBStringArrayToStringList((char const * const *)reg_pnames, nstrs, &s, &len);
15589         db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.reg_pnames/*out*/,
15590                 friendly_name(name, "_reg_pnames", 0));
15591         FREE(s);
15592 
15593         if (compnames)
15594         {
15595             /* output compnames */
15596             DBStringArrayToStringList((char const * const *)compnames, ncomps, &s, &len);
15597             db_hdf5_compwr(dbfile, DB_CHAR, 1, &len, s, m.compnames/*out*/,
15598                     friendly_name(name, "_compnames", 0));
15599             FREE(s);
15600         }
15601 
15602         /* Build header in memory */
15603         m.ncomps = ncomps;
15604         m.nregns = nregns;
15605         m.datatype = datatype;
15606         strcpy(m.mrgt_name, OPT(mrgt_name));
15607 
15608         /* Write header to file */
15609         STRUCT(DBmrgvar) {
15610             MEMBER_R(str(m.data[_j]), data, ncomps);
15611             MEMBER_S(str(m.mrgt_name), mrgt_name);
15612             if (m.ncomps)       MEMBER_S(int, ncomps);
15613             if (m.nregns)       MEMBER_S(int, nregns);
15614             if (m.datatype)     MEMBER_S(int, datatype);
15615             MEMBER_S(str(m.compnames), compnames);
15616             MEMBER_S(str(m.reg_pnames), reg_pnames);
15617         } OUTPUT(dbfile, DB_MRGVAR, name, &m);
15618 
15619     } CLEANUP {
15620         /*void*/
15621     } END_PROTECT;
15622     return 0;
15623 }
15624 
15625 /*-------------------------------------------------------------------------
15626  * Function:    db_hdf5_GetMrgvar
15627  *
15628  * Purpose:     Read an mrgvar from a file.
15629  *
15630  * Programmer: Mark C. Miller
15631  *
15632  * Modifications:
15633  *
15634  *   Mark C. Miller, Tue Nov 10 09:14:01 PST 2009
15635  *   Added logic to control behavior of slash character swapping for
15636  *   windows/linux and skipping of first semicolon in calls to
15637  *   db_StringListToStringArray.
15638  *-------------------------------------------------------------------------
15639  */
15640 SILO_CALLBACK DBmrgvar *
db_hdf5_GetMrgvar(DBfile * _dbfile,char const * name)15641 db_hdf5_GetMrgvar(DBfile *_dbfile, char const *name)
15642 {
15643     DBfile_hdf5         *dbfile = (DBfile_hdf5*)_dbfile;
15644     static char         *me = "db_hdf5_GetMrgvar";
15645     char                *s = 0;
15646     hid_t               o=-1, attr=-1;
15647     int                 _objtype, i;
15648     DBmrgvar_mt         m;
15649     DBmrgvar           *mrgv=NULL;
15650 
15651     PROTECT {
15652         /* Open object and make sure it's a ucdvar */
15653         if ((o=H5Topen(dbfile->cwg, name))<0) {
15654             db_perror(name, E_NOTFOUND, me);
15655             UNWIND();
15656         }
15657         if ((attr=H5Aopen_name(o, "silo_type"))<0 ||
15658             H5Aread(attr, H5T_NATIVE_INT, &_objtype)<0 ||
15659             H5Aclose(attr)<0) {
15660             db_perror(name, E_CALLFAIL, me);
15661             UNWIND();
15662         }
15663         if (DB_MRGVAR!=(DBObjectType)_objtype) {
15664             db_perror(name, E_CALLFAIL, me);
15665             UNWIND();
15666         }
15667 
15668         /* Read ucdvar data into memory */
15669         memset(&m, 0, sizeof m);
15670         if ((attr=H5Aopen_name(o, "silo"))<0 ||
15671             H5Aread(attr, DBmrgvar_mt5, &m)<0 ||
15672             H5Aclose(attr)<0) {
15673             db_perror(name, E_CALLFAIL, me);
15674             UNWIND();
15675         }
15676 
15677         /* Create a mrgvar object and initialize meta data */
15678         mrgv = (DBmrgvar *) calloc(1,sizeof(DBmrgvar));
15679         mrgv->name = BASEDUP(name);
15680         mrgv->mrgt_name = OPTDUP(m.mrgt_name);
15681         mrgv->nregns = m.nregns;
15682         mrgv->ncomps = m.ncomps;
15683         if ((mrgv->datatype = db_hdf5_GetVarType(_dbfile, m.data[0])) < 0)
15684             mrgv->datatype = silo2silo_type(m.datatype);
15685         if (force_single_g) mrgv->datatype = DB_FLOAT;
15686 
15687         /* Read the raw data */
15688         if (m.ncomps>MAX_VARS) {
15689             db_perror(name, E_CALLFAIL, me);
15690             UNWIND();
15691         }
15692         mrgv->data = (void **)calloc(m.ncomps, sizeof(void*));
15693         for (i=0; i<m.ncomps; i++) {
15694             mrgv->data[i] = db_hdf5_comprd(dbfile, m.data[i], 0);
15695         }
15696 
15697         s = (char *)db_hdf5_comprd(dbfile, m.compnames, 1);
15698         if (s) mrgv->compnames = DBStringListToStringArray(s, &m.ncomps, !skipFirstSemicolon);
15699         FREE(s);
15700 
15701         s = (char *)db_hdf5_comprd(dbfile, m.reg_pnames, 1);
15702         if (s) mrgv->reg_pnames = DBStringListToStringArray(s, 0, !skipFirstSemicolon);
15703         FREE(s);
15704 
15705         H5Tclose(o);
15706 
15707     } CLEANUP {
15708         H5E_BEGIN_TRY {
15709             H5Aclose(attr);
15710             H5Tclose(o);
15711         } H5E_END_TRY;
15712         DBFreeMrgvar(mrgv);
15713     } END_PROTECT;
15714 
15715     return mrgv;
15716 }
15717 
15718 SILO_CALLBACK int
db_hdf5_FreeCompressionResources(DBfile * _dbfile,char const * meshname)15719 db_hdf5_FreeCompressionResources(DBfile *_dbfile, char const *meshname)
15720 {
15721     FreeNodelists((DBfile_hdf5*)_dbfile, meshname);
15722     return 0;
15723 }
15724 
15725 /*-------------------------------------------------------------------------
15726  * Function:    db_hdf5_SortObjectsByOffset
15727  *
15728  * Purpose:     Returned array of indexes into an array of object names
15729  *              sorted by offset within the file. This can be used by
15730  *              readers to 'schedule' reading of objects to minimize
15731  *              jumping around the file.
15732  *
15733  * Programmer: Mark C. Miller, Thu Jul 15 07:42:46 PDT 2010
15734  *
15735  *-------------------------------------------------------------------------
15736  */
15737 
15738 /* Support type for db_hdf5_SortObjectsByOffset */
15739 typedef struct _index_offset_pair_t {
15740     int index;
15741     haddr_t offset;
15742 } index_offset_pair_t;
15743 
15744 /* Support function for db_hdf5_SortObjectsByOffset */
compare_index_offset_pair(void const * a1,void const * a2)15745 static int compare_index_offset_pair(void const *a1, void const *a2)
15746 {
15747     index_offset_pair_t *p1 = (index_offset_pair_t*) a1;
15748     index_offset_pair_t *p2 = (index_offset_pair_t*) a2;
15749     if (p1->index == -1) return 1;
15750     if (p2->index == -1) return -1;
15751     if (p1->offset < p2->offset) return -1;
15752     else if (p1->offset > p2->offset) return 1;
15753     else return 0;
15754 }
15755 
15756 SILO_CALLBACK int
db_hdf5_SortObjectsByOffset(DBfile * _dbfile,int nobjs,char const * const * const names,int * ordering)15757 db_hdf5_SortObjectsByOffset(DBfile *_dbfile, int nobjs,
15758     char const *const *const names, int *ordering)
15759 {
15760     static char *me = "db_hdf5_SortObjectsByOffset";
15761 #if HDF5_VERSION_GE(1,8,0)
15762     DBfile_hdf5 *dbfile = (DBfile_hdf5*)_dbfile;
15763     index_offset_pair_t *iop = (index_offset_pair_t*)
15764         malloc(nobjs * sizeof(index_offset_pair_t));
15765     int i;
15766 
15767     /* Gather up object addresses. If object names contain colon, ':'
15768        this indicates the object is in a different file than current.
15769        These will always be pushed to the 'back' of the list */
15770     for (i = 0; i < nobjs; i++)
15771     {
15772         iop[i].index = i;
15773         if (strchr(names[i], ':')) iop[i].offset = HADDR_MAX;
15774         else
15775         {
15776             H5O_info_t oinfo;
15777             hid_t oid;
15778             if ((oid=H5Oopen(dbfile->cwg, names[i], H5P_DEFAULT))<0 ||
15779                  H5Oget_info(oid, &oinfo)<0 ||
15780                  H5Oclose(oid)<0)
15781                 iop[i].offset = HADDR_MAX;
15782             else
15783                 iop[i].offset = oinfo.addr;
15784         }
15785     }
15786 
15787     /* Ok, sort the index/offset pairs */
15788     qsort(iop, nobjs, sizeof(index_offset_pair_t), compare_index_offset_pair);
15789 
15790     /* Populate ordering array */
15791     for (i = 0; i < nobjs; i++)
15792         ordering[i] = iop[i].index;
15793 
15794     free(iop);
15795 
15796     return 0;
15797 #else
15798     return db_perror("H5O API for sort", E_NOTENABLEDINBUILD, me);
15799 #endif
15800 }
15801 
15802 #if HDF5_VERSION_GE(1,8,9)
15803 /* Definition of callbacks for file image operations. [ */
15804 
15805 /*-------------------------------------------------------------------------
15806 * Function: image_malloc
15807 *
15808 * Purpose: Simulates malloc() function to avoid copying file images.
15809 *          The application buffer is set to the buffer on only one FAPL.
15810 *          Then the FAPL buffer can be copied to other FAPL buffers or
15811 *          to only one VFD buffer.
15812 *
15813 * Return: Address of "allocated" buffer, if successful. Otherwise, it returns
15814 *         NULL.
15815 *
15816 * Programmer: Christian Chilan
15817 *
15818 * Date: October 3, 2011
15819 *
15820 *-------------------------------------------------------------------------
15821 */
15822 static void *
image_malloc(size_t size,H5FD_file_image_op_t file_image_op,void * _udata)15823 image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *_udata)
15824 {
15825     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
15826     void * return_value = NULL;
15827 
15828     /* callback is only used if the application buffer is not actually copied */
15829     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
15830         goto out;
15831 
15832     switch ( file_image_op ) {
15833         /* the app buffer is "copied" to only one FAPL. Afterwards, FAPLs can be "copied" */
15834         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
15835             if (udata->app_image_ptr == NULL)
15836                 goto out;
15837             if (udata->app_image_size != size)
15838                 goto out;
15839             if (udata->fapl_image_ptr != NULL)
15840                 goto out;
15841             if (udata->fapl_image_size != 0)
15842                 goto out;
15843             if (udata->fapl_ref_count != 0)
15844                 goto out;
15845 
15846             udata->fapl_image_ptr = udata->app_image_ptr;
15847             udata->fapl_image_size = udata->app_image_size;
15848             return_value = udata->fapl_image_ptr;
15849             udata->fapl_ref_count++;
15850 	    break;
15851 
15852 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
15853             if (udata->fapl_image_ptr == NULL)
15854                 goto out;
15855             if (udata->fapl_image_size != size)
15856                 goto out;
15857             if (udata->fapl_ref_count == 0)
15858                 goto out;
15859 
15860             return_value = udata->fapl_image_ptr;
15861             udata->fapl_ref_count++;
15862 	    break;
15863 
15864         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
15865             goto out;
15866 
15867         case H5FD_FILE_IMAGE_OP_FILE_OPEN:
15868             /* FAPL buffer is "copied" to only one VFD buffer */
15869             if (udata->vfd_image_ptr != NULL)
15870                 goto out;
15871             if (udata->vfd_image_size != 0)
15872                 goto out;
15873             if (udata->vfd_ref_count != 0)
15874                 goto out;
15875             if (udata->fapl_image_ptr == NULL)
15876                 goto out;
15877             if (udata->fapl_image_size != size)
15878                 goto out;
15879             if (udata->fapl_ref_count == 0)
15880                 goto out;
15881 
15882             udata->vfd_image_ptr = udata->fapl_image_ptr;
15883  	    udata->vfd_image_size = size;
15884             udata->vfd_ref_count++;
15885             return_value = udata->vfd_image_ptr;
15886             break;
15887 
15888 	/* added unused labels to shut the compiler up */
15889 	case H5FD_FILE_IMAGE_OP_NO_OP:
15890 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
15891 	case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
15892 	case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
15893         default:
15894             goto out;
15895     } /* end switch */
15896 
15897     return(return_value);
15898 
15899 out:
15900     return NULL;
15901 } /* end image_malloc() */
15902 
15903 /*-------------------------------------------------------------------------
15904 * Function: image_memcpy
15905 *
15906 * Purpose:  Simulates memcpy() function to avoid copying file images.
15907 *           The image buffer can be set to only one FAPL buffer, and
15908 *           "copied" to only one VFD buffer. The FAPL buffer can be
15909 *           "copied" to other FAPLs buffers.
15910 *
15911 * Return: The address of the destination buffer, if successful. Otherwise, it
15912 *         returns NULL.
15913 *
15914 * Programmer: Christian Chilan
15915 *
15916 * Date: October 3, 2011
15917 *
15918 *-------------------------------------------------------------------------
15919 */
15920 static void *
image_memcpy(void * dest,const void * src,size_t size,H5FD_file_image_op_t file_image_op,void * _udata)15921 image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op,
15922     void *_udata)
15923 {
15924     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
15925 
15926     /* callback is only used if the application buffer is not actually copied */
15927     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
15928         goto out;
15929 
15930     switch(file_image_op) {
15931         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
15932             if (dest != udata->fapl_image_ptr)
15933                 goto out;
15934             if (src != udata->app_image_ptr)
15935                 goto out;
15936             if (size != udata->fapl_image_size)
15937                 goto out;
15938             if (size != udata->app_image_size)
15939                 goto out;
15940             if (udata->fapl_ref_count == 0)
15941                 goto out;
15942             break;
15943 
15944         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
15945             if (dest != udata->fapl_image_ptr)
15946                 goto out;
15947             if (src != udata->fapl_image_ptr)
15948                 goto out;
15949             if (size != udata->fapl_image_size)
15950                 goto out;
15951             if (udata->fapl_ref_count < 2)
15952                 goto out;
15953             break;
15954 
15955         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
15956             goto out;
15957 
15958         case H5FD_FILE_IMAGE_OP_FILE_OPEN:
15959             if (dest != udata->vfd_image_ptr)
15960                 goto out;
15961             if (src != udata->fapl_image_ptr)
15962                 goto out;
15963             if (size != udata->vfd_image_size)
15964                 goto out;
15965             if (size != udata->fapl_image_size)
15966                 goto out;
15967             if (udata->fapl_ref_count == 0)
15968                 goto out;
15969             if (udata->vfd_ref_count != 1)
15970                 goto out;
15971             break;
15972 
15973 	/* added unused labels to shut the compiler up */
15974 	case H5FD_FILE_IMAGE_OP_NO_OP:
15975 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
15976 	case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
15977 	case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
15978         default:
15979             goto out;
15980     } /* end switch */
15981 
15982     return(dest);
15983 
15984 out:
15985     return NULL;
15986 } /* end image_memcpy() */
15987 
15988 /*-------------------------------------------------------------------------
15989 * Function: image_realloc
15990 *
15991 * Purpose: Reallocates the shared application image buffer and updates data
15992 *          structures that manage buffer "copying".
15993 *
15994 * Return: Address of reallocated buffer, if successful. Otherwise, it returns
15995 *         NULL.
15996 *
15997 * Programmer: Christian Chilan
15998 *
15999 * Date: October 3, 2011
16000 *
16001 *-------------------------------------------------------------------------
16002 */
16003 static void *
image_realloc(void * ptr,size_t size,H5FD_file_image_op_t file_image_op,void * _udata)16004 image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *_udata)
16005 {
16006     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
16007     void * return_value = NULL;
16008 
16009     /* callback is only used if the application buffer is not actually copied */
16010     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
16011         goto out;
16012 
16013     /* realloc() is not allowed when the HDF5 library won't release the image
16014        buffer because reallocation may change the address of the buffer. The
16015        new address cannot be communicated to the application to release it. */
16016     if (udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_RELEASE)
16017         goto out;
16018 
16019     /* realloc() is not allowed if the image is open in read-only mode */
16020     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_OPEN_RW))
16021         goto out;
16022 
16023     if (file_image_op == H5FD_FILE_IMAGE_OP_FILE_RESIZE) {
16024         if (udata->vfd_image_ptr != ptr)
16025             goto out;
16026 
16027         if (udata->vfd_ref_count != 1)
16028             goto out;
16029 
16030         if (NULL == (udata->vfd_image_ptr = realloc(ptr, size)))
16031             goto out;
16032 
16033         udata->vfd_image_size = size;
16034         return_value = udata->vfd_image_ptr;
16035     } /* end if */
16036     else
16037         goto out;
16038 
16039     return(return_value);
16040 
16041 out:
16042     return NULL;
16043 } /* end image_realloc() */
16044 
16045 
16046 /*-------------------------------------------------------------------------
16047 * Function: image_free
16048 *
16049 * Purpose: Simulates deallocation of FAPL and VFD buffers by decreasing
16050 *          reference counters. Shared application buffer is actually
16051 *          deallocated if there are no outstanding references.
16052 *
16053 * Return: SUCCEED or FAIL
16054 *
16055 * Programmer: Christian Chilan
16056 *
16057 * Date: October 3, 2011
16058 *
16059 *-------------------------------------------------------------------------
16060 */
16061 static herr_t
image_free(void * ptr,H5FD_file_image_op_t file_image_op,void * _udata)16062 image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *_udata)
16063 {
16064     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
16065 
16066     /* callback is only used if the application buffer is not actually copied */
16067     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
16068         goto out;
16069 
16070     switch(file_image_op) {
16071         case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
16072 	    if (udata->fapl_image_ptr != ptr)
16073                 goto out;
16074             if (udata->fapl_ref_count == 0)
16075                 goto out;
16076 
16077             udata->fapl_ref_count--;
16078 
16079             /* release the shared buffer only if indicated by the respective flag and there are no outstanding references */
16080             if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 &&
16081                     !(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_RELEASE)) {
16082                 free(udata->fapl_image_ptr);
16083                 udata->app_image_ptr = NULL;
16084                 udata->fapl_image_ptr = NULL;
16085                 udata->vfd_image_ptr = NULL;
16086             } /* end if */
16087             break;
16088 
16089         case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
16090             if (udata->vfd_image_ptr != ptr)
16091                 goto out;
16092             if (udata->vfd_ref_count != 1)
16093                 goto out;
16094 
16095             udata->vfd_ref_count--;
16096 
16097             /* release the shared buffer only if indicated by the respective flag and there are no outstanding references */
16098             if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 &&
16099                     !(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_RELEASE)) {
16100                 free(udata->vfd_image_ptr);
16101                 udata->app_image_ptr = NULL;
16102                 udata->fapl_image_ptr = NULL;
16103                 udata->vfd_image_ptr = NULL;
16104             } /* end if */
16105             break;
16106 
16107 	/* added unused labels to keep the compiler quite */
16108 	case H5FD_FILE_IMAGE_OP_NO_OP:
16109 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
16110 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
16111 	case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
16112 	case H5FD_FILE_IMAGE_OP_FILE_OPEN:
16113 	case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
16114 	default:
16115             goto out;
16116     } /* end switch */
16117 
16118     return(0);
16119 
16120 out:
16121     return(-1);
16122 } /* end image_free() */
16123 
16124 /*-------------------------------------------------------------------------
16125 * Function: udata_copy
16126 *
16127 * Purpose: Simulates the copying of the user data structure utilized in the
16128 *          management of the "copying" of file images.
16129 *
16130 * Return: Address of "newly allocated" structure, if successful. Otherwise, it
16131 *         returns NULL.
16132 *
16133 * Programmer: Christian Chilan
16134 *
16135 * Date: October 3, 2011
16136 *
16137 *-------------------------------------------------------------------------
16138 */
16139 static void *
udata_copy(void * _udata)16140 udata_copy(void *_udata)
16141 {
16142     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
16143 
16144     /* callback is only used if the application buffer is not actually copied */
16145     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
16146         goto out;
16147     if (udata->ref_count == 0)
16148         goto out;
16149 
16150     udata->ref_count++;
16151 
16152     return(udata);
16153 
16154 out:
16155     return NULL;
16156 } /* end udata_copy */
16157 
16158 
16159 /*-------------------------------------------------------------------------
16160 * Function: udata_free
16161 *
16162 * Purpose: Simulates deallocation of the user data structure utilized in the
16163 *          management of the "copying" of file images. The data structure is
16164 *          actually deallocated when there are no outstanding references.
16165 *
16166 * Return: SUCCEED or FAIL
16167 *
16168 * Programmer: Christian Chilan
16169 *
16170 * Date: October 3, 2011
16171 *
16172 *-------------------------------------------------------------------------
16173 */
16174 static herr_t
udata_free(void * _udata)16175 udata_free(void *_udata)
16176 {
16177     db_hdf5_H5LT_file_image_ud_t *udata = (db_hdf5_H5LT_file_image_ud_t *)_udata;
16178 
16179     /* callback is only used if the application buffer is not actually copied */
16180     if (!(udata->flags & db_hdf5_H5LT_FILE_IMAGE_DONT_COPY))
16181         goto out;
16182     if (udata->ref_count == 0)
16183         goto out;
16184 
16185     udata->ref_count--;
16186 
16187     /* checks that there are no references outstanding before deallocating udata */
16188     if (udata->ref_count == 0 && udata->fapl_ref_count == 0 &&
16189             udata->vfd_ref_count == 0)
16190         free(udata);
16191 
16192     return(0);
16193 
16194 out:
16195     return(-1);
16196 } /* end udata_free */
16197 #endif /* ] #if HDF5_VERSION_GE(1,8,9) */
16198 
16199 #else /* ] defined(HAVE_HDF5_H) && defined(HAVE_LIBHDF5) [ */
16200 
16201 /* Stub for when we don't have hdf5 */
16202 INTERNAL DBfile *
db_hdf5_Open(char const * name,int mode,int subtype)16203 db_hdf5_Open(char const *name, int mode, int subtype)
16204 {
16205     db_perror(name, E_NOTIMP, "db_hdf5_Open");
16206     return NULL;
16207 }
16208 
16209 /* Stub for when we don't have hdf5 */
16210 INTERNAL DBfile *
db_hdf5_Create(char const * name,int mode,int target,int subtype,char const * finfo)16211 db_hdf5_Create(char const *name, int mode, int target, int subtype, char const *finfo)
16212 {
16213     db_perror(name, E_NOTIMP, "db_hdf5_Create");
16214     return NULL;
16215 }
16216 
16217 /* Stub for when we don't have hdf5 */
16218 INTERNAL int
db_hdf5_ForceSingle(int satus)16219 db_hdf5_ForceSingle(int satus)
16220 {
16221     return 0; /*no-op, don't fail*/
16222 }
16223 
16224 #endif /* ] defined(HAVE_HDF5_H) && defined(HAVE_LIBHDF5) */
16225