1/** \file
2  This header file contains the definitions of structs used to hold
3  netCDF file metadata in memory.
4
5  Copyright 2005-2011 University Corporation for Atmospheric
6  Research/Unidata.
7*/
8
9#ifndef _NC4INTERNAL_
10#define _NC4INTERNAL_
11
12#include "config.h"
13#include <stdio.h>
14#include <stdlib.h>
15#include <ctype.h>
16#include <stdarg.h>
17#include <string.h>
18#include <hdf5.h>
19
20
21#include "ncdimscale.h"
22#include "nc_logging.h"
23
24#ifdef USE_PARALLEL
25#include "netcdf_par.h"
26#endif /* USE_PARALLEL */
27#include "netcdf.h"
28#include "netcdf_f.h"
29
30/* Always needed */
31#include "nc.h"
32
33#ifdef USE_HDF4
34#include <mfhdf.h>
35#endif
36
37#define FILE_ID_MASK (0xffff0000)
38#define GRP_ID_MASK (0x0000ffff)
39#define ID_SHIFT (16)
40
41typedef enum {GETPUTNC_PG_T;
42typedef enum {VARDIMATTNC_OBJ_T;
43
44#define NC_MAX_HDF5_NAME (NC_MAX_NAME + 10)
45#define NC_V2_ERR (-1)
46
47/* The name of the root group. */
48#define NC_GROUP_NAME "/"
49
50#define MEGABYTE 1048576
51
52/*
53 * limits of the external representation
54 */
55#define X_SCHAR_MIN (-128)
56#define X_SCHAR_MAX 127
57#define X_UCHAR_MAX 255U
58#define X_SHORT_MIN (-32768)
59#define X_SHRT_MIN X_SHORT_MIN /* alias compatible with limits.h */
60#define X_SHORT_MAX 32767
61#define X_SHRT_MAX X_SHORT_MAX /* alias compatible with limits.h */
62#define X_USHORT_MAX 65535U
63#define X_USHRT_MAX X_USHORT_MAX /* alias compatible with limits.h */
64#define X_INT_MIN (-2147483647-1)
65#define X_INT_MAX 2147483647
66#define X_LONG_MIN X_INT_MIN
67#define X_LONG_MAX X_INT_MAX
68#define X_UINT_MAX 4294967295U
69#ifdef WIN32 /* Windows, of course, has to be a *little* different. */
70#define X_FLOAT_MAX 3.402823466e+38f
71#else
72#define X_FLOAT_MAX 3.40282347e+38f
73#endif /* WIN32 */
74#define X_FLOAT_MIN (-X_FLOAT_MAX)
75#define X_DOUBLE_MAX 1.7976931348623157e+308
76#define X_DOUBLE_MIN (-X_DOUBLE_MAX)
77
78/* These have to do with creating chuncked datasets in HDF5. */
79#define NC_HDF5_UNLIMITED_DIMSIZE (0)
80#define NC_HDF5_CHUNKSIZE_FACTOR (10)
81#define NC_HDF5_MIN_CHUNK_SIZE (2)
82
83#define NC_EMPTY_SCALE "NC_EMPTY_SCALE"
84
85/* This is an attribute I had to add to handle multidimensional
86 * coordinate variables. */
87#define COORDINATES "_Netcdf4Coordinates"
88#define COORDINATES_LEN (NC_MAX_NAME * 5)
89
90/* This is used when the user defines a non-coordinate variable with
91 * same name as a dimension. */
92#define NON_COORD_PREPEND "_nc4_non_coord_"
93
94/* An attribute in the HDF5 root group of this name means that the
95 * file must follow strict netCDF classic format rules. */
96#define NC3_STRICT_ATT_NAME "_nc3_strict"
97
98/* If this attribute is present on a dimscale variable, use the value
99 * as the netCDF dimid. */
100#define NC_DIMID_ATT_NAME "_Netcdf4Dimid"
101
102/* Boolean type, to make the code easier to read */
103typedef enum {NC_FALSE = 0, NC_TRUE = 1} nc_bool_t;
104
105/*Forward*/
106struct NCFILEINFO;
107
108/* Generic doubly-linked list node */
109typedef struct NC_LIST_NODE
110{
111   void *next;
112   void *prev;
113NC_LIST_NODE_T;
114
115/* This is a struct to handle the dim metadata. */
116typedef struct NC_DIM_INFO
117{
118   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
119   char *name;
120   size_t len;
121   uint32_t hash;
122   int dimid;
123   nc_bool_t unlimited;         /* True if the dimension is unlimited */
124   nc_bool_t extended;          /* True if the dimension needs to be extended */
125   nc_bool_t too_long;          /* True if len is too big to fit in local size_t. */
126   hid_t hdf_dimscaleid;
127   HDF5_OBJID_T hdf5_objid;
128   struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */
129NC_DIM_INFO_T;
130
131typedef struct NC_ATT_INFO
132{
133   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
134   char *name;
135   int len;
136   nc_bool_t dirty;             /* True if attribute modified */
137   nc_bool_t created;           /* True if attribute already created */
138   nc_type nc_typeid;           /* netCDF type of attribute's data */
139   hid_t native_hdf_typeid;     /* Native HDF5 datatype for attribute's data */
140   int attnum;
141   void *data;
142   nc_vlen_t *vldata; /* only used for vlen */
143   char **stdata; /* only for string type. */
144NC_ATT_INFO_T;
145
146/* This is a struct to handle the var metadata. */
147typedef struct NC_VAR_INFO
148{
149   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
150   char *name;
151   char *hdf5_name; /* used if different from name */
152   int ndims;
153   int *dimids;
154   NC_DIM_INFO_T **dim;
155   int varid;
156   int natts;
157   uint32_t hash;
158   nc_bool_t is_new_var;        /* True if variable is newly created */
159   nc_bool_t was_coord_var;     /* True if variable was a coordinate var, but either the dim or var has been renamed */
160   nc_bool_t became_coord_var;  /* True if variable _became_ a coordinate var, because either the dim or var has been renamed */
161   nc_bool_t fill_val_changed;  /* True if variable's fill value changes after it has been created */
162   nc_bool_t attr_dirty;        /* True if variable's attributes are dirty and should be rewritten */
163   nc_bool_t created;           /* Variable has already been created (_not_ that it was just created) */
164   nc_bool_t written_to;        /* True if variable has data written to it */
165   struct NC_TYPE_INFO *type_info;
166   hid_t hdf_datasetid;
167   NC_ATT_INFO_T *att;
168   nc_bool_t no_fill;           /* True if no fill value is defined for var */
169   void *fill_value;
170   size_t *chunksizes;
171   nc_bool_t contiguous;        /* True if variable is stored contiguously in HDF5 file */
172   int parallel_access;         /* Type of parallel access for I/O on variable (collective or independent) */
173   nc_bool_t dimscale;          /* True if var is a dimscale */
174   nc_bool_t *dimscale_attached;        /* Array of flags that are true if dimscale is attached for that dim index */
175   HDF5_OBJID_T *dimscale_hdf5_objids;
176   nc_bool_t deflate;           /* True if var has deflate filter applied */
177   int deflate_level;
178   nc_bool_t shuffle;           /* True if var has shuffle filter applied */
179   nc_bool_t fletcher32;        /* True if var has fletcher32 filter applied */
180   nc_bool_t szip;              /* True if var has szip filter applied */
181   int options_mask;
182   int pixels_per_block;
183   size_t chunk_cache_sizechunk_cache_nelems;
184   float chunk_cache_preemption;
185#ifdef USE_HDF4
186   /* Stuff below is for hdf4 files. */
187   int sdsid;
188   int hdf4_data_type;
189#endif /* USE_HDF4 */
190   /* Stuff below for diskless data files. */
191   void *diskless_data;
192NC_VAR_INFO_T;
193
194typedef struct NC_FIELD_INFO
195{
196   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
197   nc_type nc_typeid;
198   hid_t hdf_typeid;
199   hid_t native_hdf_typeid;
200   size_t offset;
201   char *name;
202   int fieldid;                 /* ID (index?) of field */
203   int ndims;
204   int *dim_size;
205NC_FIELD_INFO_T;
206
207typedef struct NC_ENUM_MEMBER_INFO
208{
209   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
210   char *name;
211   void *value;
212NC_ENUM_MEMBER_INFO_T;
213
214typedef struct NC_TYPE_INFO
215{
216   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
217   char *name;
218   nc_type nc_typeid;           /* netCDF type ID, equivalent to a pre-defined type
219                                 * for atomic types, but a dynamically
220                                 * defined value for user-defined types (stored
221                                 * as named datatypes in the HDF5 file).
222                                 */
223   unsigned rc;                 /* Ref. count of objects using this type */
224   hid_t hdf_typeid;            /* HDF5 type ID, in the file */
225   hid_t native_hdf_typeid;     /* HDF5 type ID, in memory */
226   int endianness;              /* What endianness for the type? */
227                                /* (Set for integer types as well as "complex"
228                                 *  types, like compound/enum/vlen, used for the
229                                 *  endianness of the fields and/or base type)
230                                 */
231   size_t size;                 /* Size of the type in memory, in bytes */
232   nc_bool_t committed;         /* True when datatype is committed in the file */
233   nc_type nc_type_class;       /* NC_VLEN, NC_COMPOUND, NC_OPAQUE, or NC_ENUM
234                                 * NOTE: NC_INT is used for all integer types,
235                                 *      NC_FLOAT is used for all floating-point
236                                 *      types, and NC_STRING is also used for
237                                 *      fixed- and variable-length strings.
238                                 *      (NC_CHAR is used for characters though)
239                                 *
240                                 *      This is somewhat redundant with the
241                                 *      nc_type field, but allows the code to
242                                 *      have a single location to look at for
243                                 *      the "kind" of a type.
244                                 */
245
246   /* Information for each type or class */
247   union {
248      struct {
249         int num_members;
250         NC_ENUM_MEMBER_INFO_T *enum_member;
251         nc_type base_nc_typeid;
252         hid_t base_hdf_typeid;
253      } e;                      /* Enum */
254      struct {
255         int num_fields;
256         NC_FIELD_INFO_T *field;
257      } c;                      /* Compound */
258      struct {
259         nc_type base_nc_typeid;
260         hid_t base_hdf_typeid;
261      } v;                      /* Variable-length */
262   } u;                         /* Union of structs, for each type/class */
263NC_TYPE_INFO_T;
264
265/* This holds information for one group. Groups reproduce with
266 * parthenogenesis. */
267typedef struct NC_GRP_INFO
268{
269   NC_LIST_NODE_T l;            /* Use generic doubly-linked list (must be first) */
270   char *name;
271   hid_t hdf_grpid;
272   int nc_grpid;
273   struct NC_HDF5_FILE_INFO *nc4_info;
274   struct NC_GRP_INFO *parent;
275   struct NC_GRP_INFO *children;
276   NC_VAR_INFO_T *var;
277   NC_DIM_INFO_T *dim;
278   NC_ATT_INFO_T *att;
279   NC_TYPE_INFO_T *type;
280   int nvars;
281   int ndims;
282   int natts;
283NC_GRP_INFO_T;
284
285/* These constants apply to the cmode parameter in the
286 * HDF5_FILE_INFO_T defined below. */
287#define NC_CREAT 2 /* in create phase, cleared by ncendef */
288#define NC_INDEF 8 /* in define mode, cleared by ncendef */
289#define NC_NSYNC 0x10 /* synchronise numrecs on change */
290#define NC_HSYNC 0x20 /* synchronise whole header on change */
291#define NC_NDIRTY 0x40 /* numrecs has changed */
292#define NC_HDIRTY 0x80  /* header info has changed */
293
294
295/* This is the metadata we need to keep track of for each
296   netcdf-4/HDF5 file. */
297typedef struct  NC_HDF5_FILE_INFO
298{
299   NCcontroller;
300   hid_t hdfid;
301#ifdef USE_PARALLEL4
302   MPI_Comm comm;    /* Copy of MPI Communicator used to open the file */
303   MPI_Info info;    /* Copy of MPI Information Object used to open the file */
304#endif
305   int flags;
306   int cmode;
307   int nvars;
308   int ndims;
309   int natts;
310   nc_bool_t parallel;          /* True if file is open for parallel access */
311   nc_bool_t redef;             /* True if redefining an existing file */
312   int fill_mode;               /* Fill mode for vars - Unused internally currently */
313   nc_bool_t no_write;          /* true if nc_open has mode NC_NOWRITE. */
314   NC_GRP_INFO_T *root_grp;
315   short next_nc_grpid;
316   NC_TYPE_INFO_T *type;
317   int next_typeid;
318   int next_dimid;
319#ifdef USE_HDF4
320   nc_bool_t hdf4;              /* True for HDF4 file */
321   int sdid;
322#endif /* USE_HDF4 */
323   struct NCFILEINFOfileinfo;
324NC_HDF5_FILE_INFO_T;
325
326
327/* Defined in lookup3.c */
328extern uint32_t hash_fast(const void *key, size_t length);
329
330/* These functions convert between netcdf and HDF5 types. */
331int nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5nc_type xtype,
332 int is_long, size_t *len);
333int nc4_convert_type(const void *src, void *dest,
334      const nc_type src_type, const nc_type dest_type,
335      const size_t len, int *range_error,
336      const void *fill_value, int strict_nc3, int src_long,
337      int dest_long);
338
339/* These functions do HDF5 things. */
340int rec_detach_scales(NC_GRP_INFO_T *grp, int dimidhid_t dimscaleid);
341int rec_reattach_scales(NC_GRP_INFO_T *grp, int dimidhid_t dimscaleid);
342int nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varidhid_t *dataset);
343int nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
344  const size_t *countpnc_type xtype, int is_long, void *op);
345int nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
346  const size_t *countpnc_type xtype, int is_long, void *op);
347int nc4_rec_match_dimscales(NC_GRP_INFO_T *grp);
348int nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grpnc_bool_t *bad_coord_orderp);
349int nc4_rec_write_metadata(NC_GRP_INFO_T *grpnc_bool_t bad_coord_order);
350int nc4_rec_write_groups_types(NC_GRP_INFO_T *grp);
351int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5);
352int nc4_reopen_dataset(NC_GRP_INFO_T *grpNC_VAR_INFO_T *var);
353int nc4_adjust_var_cache(NC_GRP_INFO_T *grpNC_VAR_INFO_T * var);
354
355/* The following functions manipulate the in-memory linked list of
356   metadata, without using HDF calls. */
357int nc4_find_nc_grp_h5(int ncidNC **ncNC_GRP_INFO_T **grp,
358        NC_HDF5_FILE_INFO_T **h5);
359int nc4_find_grp_h5(int ncidNC_GRP_INFO_T **grpNC_HDF5_FILE_INFO_T **h5);
360int nc4_find_nc4_grp(int ncidNC_GRP_INFO_T **grp);
361NC_GRP_INFO_T *nc4_find_nc_grp(int ncid);
362NC_GRP_INFO_T *nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid);
363NC *nc4_find_nc_file(int ncidNC_HDF5_FILE_INFO_T**);
364int nc4_find_dim(NC_GRP_INFO_T *grp, int dimidNC_DIM_INFO_T **dimNC_GRP_INFO_T **dim_grp);
365int nc4_find_var(NC_GRP_INFO_T *grp, const char *nameNC_VAR_INFO_T **var);
366int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len);
367int nc4_find_type(const NC_HDF5_FILE_INFO_T *h5, int typeid1NC_TYPE_INFO_T **type);
368NC_TYPE_INFO_T *nc4_rec_find_nc_type(const NC_GRP_INFO_T *start_grpnc_type target_nc_typeid);
369NC_TYPE_INFO_T *nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grphid_t target_hdf_typeid);
370NC_TYPE_INFO_T *nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name);
371NC_TYPE_INFO_T *nc4_rec_find_equal_type(NC_GRP_INFO_T *start_grp, int ncid1NC_TYPE_INFO_T *type);
372int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
373     NC_ATT_INFO_T **att);
374int nc4_find_g_var_nc(NC *nc, int ncid, int varid,
375       NC_GRP_INFO_T **grpNC_VAR_INFO_T **var);
376int nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
377      NC_ATT_INFO_T **att);
378int nc4_get_hdf_typeid(NC_HDF5_FILE_INFO_T *h5nc_type xtype,
379        hid_t *hdf_typeid, int endianness);
380int nc4_get_typeclass(const NC_HDF5_FILE_INFO_T *h5nc_type xtype,
381                      int *type_class);
382
383/* Free various types */
384int nc4_type_free(NC_TYPE_INFO_T *type);
385
386/* These list functions add and delete vars, atts. */
387int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
388int nc4_var_list_add(NC_VAR_INFO_T **listNC_VAR_INFO_T **var);
389int nc4_var_list_del(NC_VAR_INFO_T **listNC_VAR_INFO_T *var);
390int nc4_dim_list_add(NC_DIM_INFO_T **listNC_DIM_INFO_T **dim);
391int nc4_dim_list_del(NC_DIM_INFO_T **listNC_DIM_INFO_T *dim);
392int nc4_att_list_add(NC_ATT_INFO_T **listNC_ATT_INFO_T **att);
393int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name,
394                  NC_TYPE_INFO_T **type);
395int nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name,
396        size_t offsethid_t field_hdf_typeidhid_t native_typeid,
397        nc_type xtype, int ndims, const int *dim_sizesp);
398void nc4_file_list_del(NC *nc);
399int nc4_att_list_del(NC_ATT_INFO_T **listNC_ATT_INFO_T *att);
400int nc4_grp_list_add(NC_GRP_INFO_T **list, int new_nc_grpidNC_GRP_INFO_T *parent_grp,
401      NC *nc, char *nameNC_GRP_INFO_T **grp);
402int nc4_rec_grp_del(NC_GRP_INFO_T **listNC_GRP_INFO_T *grp);
403int nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size,
404 const char *name, const void *value);
405
406/* Break & reform coordinate variables */
407int nc4_break_coord_var(NC_GRP_INFO_T *grpNC_VAR_INFO_T *coord_varNC_DIM_INFO_T *dim);
408int nc4_reform_coord_var(NC_GRP_INFO_T *grpNC_VAR_INFO_T *coord_varNC_DIM_INFO_T *dim);
409
410/* Check and normalize names. */
411int NC_check_name(const char *name);
412int nc4_check_name(const char *name, char *norm_name);
413int nc4_normalize_name(const char *name, char *norm_name);
414int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name);
415
416/* HDF5 initialization */
417extern int nc4_hdf5_initialized;
418extern void nc4_hdf5_initialize(void);
419
420/* This is only included if --enable-logging is used for configure; it
421   prints info about the metadata to stderr. */
422#ifdef LOGGING
423int log_metadata_nc(NC *nc);
424#endif
425
426/* Define accessors for the dispatchdata */
427#define NC4_DATA(nc) ((NC_HDF5_FILE_INFO_T*)(nc)->dispatchdata)
428#define NC4_DATA_SET(nc,data) ((nc)->dispatchdata = (void*)(data))
429
430/* Reserved Attributes */
431extern const char* NC_RESERVED_VARATT_LIST[];
432extern const char* NC_RESERVED_ATT_LIST[];
433extern const char* NC_RESERVED_SPECIAL_LIST[];
434#define NC_ATT_REFERENCE_LIST "REFERENCE_LIST"
435#define NC_ATT_CLASS "CLASS"
436#define NC_ATT_DIMENSION_LIST "DIMENSION_LIST"
437#define NC_ATT_NAME "NAME"
438#define NC_ATT_COORDINATES COORDINATES /*defined above*/
439#define NC_ATT_FORMAT "_Format"
440
441/**************************************************/
442/**
443For netcdf4 files, capture state information about the following:
4441. Global: netcdf library version
4452. Global: hdf5 library version
4463. Per file: superblock version
4474. Per File: was it created by netcdf-4?
4485. Per file: _NCProperties attribute
449*/
450
451#define NCPROPS "_NCProperties"
452#define NCPROPS_VERSION (1)
453#define NCPROPSSEP  '|'
454
455/* Currently used properties */
456#define NCPVERSION "version" /* Of the properties format */
457#define NCPHDF5LIBVERSION "hdf5libversion"
458#define NCPNCLIBVERSION "netcdflibversion"
459
460/* Other hidden attributes */
461#define ISNETCDF4ATT "_IsNetcdf4"
462#define SUPERBLOCKATT "_SuperblockVersion"
463
464struct NCFILEINFO {
465    int superblockversion;
466    /* Following is filled from NCPROPS attribute or from global version */
467    struct NCPROPINFO {
468        int version; /* 0 => not defined */
469        char hdf5ver[NC_MAX_NAME+1];
470        char netcdfver[NC_MAX_NAME+1];
471    } propattr;
472};
473
474extern struct NCPROPINFO globalpropinfo;
475
476extern int NC4_fileinfo_init(void); /*libsrc4/ncinfo.c*/
477extern int NC4_get_fileinfo(struct NC_HDF5_FILE_INFOinfo, struct NCPROPINFO*); /*libsrc4/ncinfo.c*/
478extern int NC4_put_propattr(struct NC_HDF5_FILE_INFOinfo); /*libsrc4/ncinfo.c*/
479extern int NC4_buildpropinfo(struct NCPROPINFOinfo,char** propdatap);
480
481extern int NC4_hdf5get_libversion(unsigned*,unsigned*,unsigned*);/*libsrc4/nc4hdf.c*/
482extern int NC4_hdf5get_superblock(struct NC_HDF5_FILE_INFO*, int*);/*libsrc4/nc4hdf.c*/
483extern int NC4_isnetcdf4(struct NC_HDF5_FILE_INFO*); /*libsrc4/nc4hdf.c*/
484
485#endif /* _NETCDF4_ */


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed