NetCDF  4.6.1
 All Data Structures Files Functions Variables Typedefs Macros Modules Pages
nc4var.c
Go to the documentation of this file.
1 
13 #include <nc4internal.h>
14 #include "nc4dispatch.h"
15 #include <math.h>
16 
17 /* Szip options. */
18 #define NC_SZIP_EC_OPTION_MASK 4
19 #define NC_SZIP_NN_OPTION_MASK 32
20 #define NC_SZIP_MAX_PIXELS_PER_BLOCK 32
23 #define DEFAULT_1D_UNLIM_SIZE (4096)
24 
25 #define NC_ARRAY_GROWBY 4
27 extern int nc4_get_default_fill_value(const NC_TYPE_INFO_T *type_info,
28  void *fill_value);
29 
41 int
42 nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
43 {
44  hid_t access_pid;
45 
46  if (var->hdf_datasetid)
47  {
48  if ((access_pid = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
49  return NC_EHDFERR;
50  if (H5Pset_chunk_cache(access_pid, var->chunk_cache_nelems,
51  var->chunk_cache_size,
52  var->chunk_cache_preemption) < 0)
53  return NC_EHDFERR;
54  if (H5Dclose(var->hdf_datasetid) < 0)
55  return NC_EHDFERR;
56  if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
57  access_pid)) < 0)
58  return NC_EHDFERR;
59  if (H5Pclose(access_pid) < 0)
60  return NC_EHDFERR;
61  }
62 
63  return NC_NOERR;
64 }
65 
84 int
85 NC4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
86  float preemption)
87 {
88  NC *nc;
89  NC_GRP_INFO_T *grp;
90  NC_HDF5_FILE_INFO_T *h5;
91  NC_VAR_INFO_T *var;
92  int retval;
93 
94  /* Check input for validity. */
95  if (preemption < 0 || preemption > 1)
96  return NC_EINVAL;
97 
98  /* Find info for this file and group, and set pointer to each. */
99  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
100  return retval;
101  assert(nc && grp && h5);
102 
103  /* Find the var. */
104  if (varid < 0 || varid >= grp->vars.nelems)
105  return NC_ENOTVAR;
106  var = grp->vars.value[varid];
107  assert(var && var->varid == varid);
108 
109  /* Set the values. */
110  var->chunk_cache_size = size;
111  var->chunk_cache_nelems = nelems;
112  var->chunk_cache_preemption = preemption;
113 
114  if ((retval = nc4_reopen_dataset(grp, var)))
115  return retval;
116 
117  return NC_NOERR;
118 }
119 
133 int
134 nc_set_var_chunk_cache_ints(int ncid, int varid, int size, int nelems,
135  int preemption)
136 {
137  size_t real_size = H5D_CHUNK_CACHE_NBYTES_DEFAULT;
138  size_t real_nelems = H5D_CHUNK_CACHE_NSLOTS_DEFAULT;
139  float real_preemption = CHUNK_CACHE_PREEMPTION;
140 
141  if (size >= 0)
142  real_size = ((size_t) size) * MEGABYTE;
143 
144  if (nelems >= 0)
145  real_nelems = nelems;
146 
147  if (preemption >= 0)
148  real_preemption = preemption / 100.;
149 
150  return NC4_set_var_chunk_cache(ncid, varid, real_size, real_nelems,
151  real_preemption);
152 }
153 
170 int
171 NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
172  size_t *nelemsp, float *preemptionp)
173 {
174  NC *nc;
175  NC_GRP_INFO_T *grp;
176  NC_HDF5_FILE_INFO_T *h5;
177  NC_VAR_INFO_T *var;
178  int retval;
179 
180  /* Find info for this file and group, and set pointer to each. */
181  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
182  return retval;
183  assert(nc && grp && h5);
184 
185  /* Find the var. */
186  if (varid < 0 || varid >= grp->vars.nelems)
187  return NC_ENOTVAR;
188  var = grp->vars.value[varid];
189  assert(var && var->varid == varid);
190 
191  /* Give the user what they want. */
192  if (sizep)
193  *sizep = var->chunk_cache_size;
194  if (nelemsp)
195  *nelemsp = var->chunk_cache_nelems;
196  if (preemptionp)
197  *preemptionp = var->chunk_cache_preemption;
198 
199  return NC_NOERR;
200 }
201 
218 int
219 nc_get_var_chunk_cache_ints(int ncid, int varid, int *sizep,
220  int *nelemsp, int *preemptionp)
221 {
222  size_t real_size, real_nelems;
223  float real_preemption;
224  int ret;
225 
226  if ((ret = NC4_get_var_chunk_cache(ncid, varid, &real_size,
227  &real_nelems, &real_preemption)))
228  return ret;
229 
230  if (sizep)
231  *sizep = real_size / MEGABYTE;
232  if (nelemsp)
233  *nelemsp = (int)real_nelems;
234  if(preemptionp)
235  *preemptionp = (int)(real_preemption * 100);
236 
237  return NC_NOERR;
238 }
239 
253 static int
254 check_chunksizes(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, const size_t *chunksizes)
255 {
256  double dprod;
257  size_t type_len;
258  int d;
259  int retval;
260 
261  if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->nc_typeid, 0, &type_len)))
262  return retval;
263  if (var->type_info->nc_type_class == NC_VLEN)
264  dprod = (double)sizeof(hvl_t);
265  else
266  dprod = (double)type_len;
267  for (d = 0; d < var->ndims; d++)
268  dprod *= (double)chunksizes[d];
269 
270  if (dprod > (double) NC_MAX_UINT)
271  return NC_EBADCHUNK;
272 
273  return NC_NOERR;
274 }
275 
287 static int
288 nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
289 {
290  int d;
291  size_t type_size;
292  float num_values = 1, num_unlim = 0;
293  int retval;
294  size_t suggested_size;
295 #ifdef LOGGING
296  double total_chunk_size;
297 #endif
298 
299  if (var->type_info->nc_type_class == NC_STRING)
300  type_size = sizeof(char *);
301  else
302  type_size = var->type_info->size;
303 
304 #ifdef LOGGING
305  /* Later this will become the total number of bytes in the default
306  * chunk. */
307  total_chunk_size = (double) type_size;
308 #endif
309 
310  /* How many values in the variable (or one record, if there are
311  * unlimited dimensions). */
312  for (d = 0; d < var->ndims; d++)
313  {
314  assert(var->dim[d]);
315  if (! var->dim[d]->unlimited)
316  num_values *= (float)var->dim[d]->len;
317  else {
318  num_unlim++;
319  var->chunksizes[d] = 1; /* overwritten below, if all dims are unlimited */
320  }
321  }
322  /* Special case to avoid 1D vars with unlim dim taking huge amount
323  of space (DEFAULT_CHUNK_SIZE bytes). Instead we limit to about
324  4KB */
325  if (var->ndims == 1 && num_unlim == 1) {
326  if (DEFAULT_CHUNK_SIZE / type_size <= 0)
327  suggested_size = 1;
328  else if (DEFAULT_CHUNK_SIZE / type_size > DEFAULT_1D_UNLIM_SIZE)
329  suggested_size = DEFAULT_1D_UNLIM_SIZE;
330  else
331  suggested_size = DEFAULT_CHUNK_SIZE / type_size;
332  var->chunksizes[0] = suggested_size / type_size;
333  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
334  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[0]));
335  }
336  if (var->ndims > 1 && var->ndims == num_unlim) { /* all dims unlimited */
337  suggested_size = pow((double)DEFAULT_CHUNK_SIZE/type_size, 1.0/(double)(var->ndims));
338  for (d = 0; d < var->ndims; d++)
339  {
340  var->chunksizes[d] = suggested_size ? suggested_size : 1;
341  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
342  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
343  }
344  }
345 
346  /* Pick a chunk length for each dimension, if one has not already
347  * been picked above. */
348  for (d = 0; d < var->ndims; d++)
349  if (!var->chunksizes[d])
350  {
351  suggested_size = (pow((double)DEFAULT_CHUNK_SIZE/(num_values * type_size),
352  1.0/(double)(var->ndims - num_unlim)) * var->dim[d]->len - .5);
353  if (suggested_size > var->dim[d]->len)
354  suggested_size = var->dim[d]->len;
355  var->chunksizes[d] = suggested_size ? suggested_size : 1;
356  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
357  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
358  }
359 
360 #ifdef LOGGING
361  /* Find total chunk size. */
362  for (d = 0; d < var->ndims; d++)
363  total_chunk_size *= (double) var->chunksizes[d];
364  LOG((4, "total_chunk_size %f", total_chunk_size));
365 #endif
366 
367  /* But did this result in a chunk that is too big? */
368  retval = check_chunksizes(grp, var, var->chunksizes);
369  if (retval)
370  {
371  /* Other error? */
372  if (retval != NC_EBADCHUNK)
373  return retval;
374 
375  /* Chunk is too big! Reduce each dimension by half and try again. */
376  for ( ; retval == NC_EBADCHUNK; retval = check_chunksizes(grp, var, var->chunksizes))
377  for (d = 0; d < var->ndims; d++)
378  var->chunksizes[d] = var->chunksizes[d]/2 ? var->chunksizes[d]/2 : 1;
379  }
380 
381  /* Do we have any big data overhangs? They can be dangerous to
382  * babies, the elderly, or confused campers who have had too much
383  * beer. */
384  for (d = 0; d < var->ndims; d++)
385  {
386  size_t num_chunks;
387  size_t overhang;
388  assert(var->chunksizes[d] > 0);
389  num_chunks = (var->dim[d]->len + var->chunksizes[d] - 1) / var->chunksizes[d];
390  if(num_chunks > 0) {
391  overhang = (num_chunks * var->chunksizes[d]) - var->dim[d]->len;
392  var->chunksizes[d] -= overhang / num_chunks;
393  }
394  }
395 
396  return NC_NOERR;
397 }
398 
409 int
410 nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
411 {
412  NC_VAR_INFO_T **vp = NULL;
413 
414  if (grp->vars.nalloc == 0) {
415  assert(grp->vars.nelems == 0);
416  vp = (NC_VAR_INFO_T **) malloc(NC_ARRAY_GROWBY * sizeof(NC_VAR_INFO_T *));
417  if(vp == NULL)
418  return NC_ENOMEM;
419  grp->vars.value = vp;
420  grp->vars.nalloc = NC_ARRAY_GROWBY;
421  }
422  else if(grp->vars.nelems +1 > grp->vars.nalloc) {
423  vp = (NC_VAR_INFO_T **) realloc(grp->vars.value,
424  (grp->vars.nalloc + NC_ARRAY_GROWBY) * sizeof(NC_VAR_INFO_T *));
425  if(vp == NULL)
426  return NC_ENOMEM;
427  grp->vars.value = vp;
428  grp->vars.nalloc += NC_ARRAY_GROWBY;
429  }
430 
431  assert(var->varid == grp->vars.nelems);
432  grp->vars.value[grp->vars.nelems] = var;
433  grp->vars.nelems++;
434 
435  return NC_NOERR;
436 }
437 
469 int
470 NC4_def_var(int ncid, const char *name, nc_type xtype,
471  int ndims, const int *dimidsp, int *varidp)
472 {
473  NC_GRP_INFO_T *grp;
474  NC_VAR_INFO_T *var;
475  NC_DIM_INFO_T *dim;
476  NC_HDF5_FILE_INFO_T *h5;
477  NC_TYPE_INFO_T *type_info = NULL;
478  char norm_name[NC_MAX_NAME + 1];
479  int d;
480  int retval;
481 
482  /* Find info for this file and group, and set pointer to each. */
483  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
484  BAIL(retval);
485  assert(grp && h5);
486 
487  /* If it's not in define mode, strict nc3 files error out,
488  * otherwise switch to define mode. This will also check that the
489  * file is writable. */
490  if (!(h5->flags & NC_INDEF))
491  {
492  if (h5->cmode & NC_CLASSIC_MODEL)
493  BAIL(NC_ENOTINDEFINE);
494  if ((retval = NC4_redef(ncid)))
495  BAIL(retval);
496  }
497  assert(!h5->no_write);
498 
499  /* Check and normalize the name. */
500  if ((retval = nc4_check_name(name, norm_name)))
501  BAIL(retval);
502 
503  /* Not a Type is, well, not a type.*/
504  if (xtype == NC_NAT)
505  BAIL(NC_EBADTYPE);
506 
507  /* For classic files, only classic types are allowed. */
508  if (h5->cmode & NC_CLASSIC_MODEL && xtype > NC_DOUBLE)
509  BAIL(NC_ESTRICTNC3);
510 
511  /* For classic files */
512  if (h5->cmode & NC_CLASSIC_MODEL && ndims > NC_MAX_VAR_DIMS)
513  BAIL(NC_EMAXDIMS);
514 
515  /* cast needed for braindead systems with signed size_t */
516  if((unsigned long) ndims > X_INT_MAX) /* Backward compat */
517  BAIL(NC_EINVAL);
518 
519  /* Check that this name is not in use as a var, grp, or type. */
520  if ((retval = nc4_check_dup_name(grp, norm_name)))
521  BAIL(retval);
522 
523  /* For non-scalar vars, dim IDs must be provided. */
524  if (ndims && !dimidsp)
525  BAIL(NC_EINVAL);
526 
527  /* Check all the dimids to make sure they exist. */
528  for (d = 0; d < ndims; d++)
529  if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, NULL)))
530  BAIL(retval);
531 
532  /* These degrubbing messages sure are handy! */
533  LOG((2, "%s: name %s type %d ndims %d", __func__, norm_name, xtype, ndims));
534 #ifdef LOGGING
535  {
536  int dd;
537  for (dd = 0; dd < ndims; dd++)
538  LOG((4, "dimid[%d] %d", dd, dimidsp[dd]));
539  }
540 #endif
541 
542  /* If this is a user-defined type, there is a type_info struct with
543  * all the type information. For atomic types, fake up a type_info
544  * struct. */
545  if (xtype <= NC_STRING)
546  {
547  if (!(type_info = calloc(1, sizeof(NC_TYPE_INFO_T))))
548  BAIL(NC_ENOMEM);
549  type_info->nc_typeid = xtype;
550  type_info->endianness = NC_ENDIAN_NATIVE;
551  if ((retval = nc4_get_hdf_typeid(h5, xtype, &type_info->hdf_typeid,
552  type_info->endianness)))
553  BAIL(retval);
554  if ((type_info->native_hdf_typeid = H5Tget_native_type(type_info->hdf_typeid,
555  H5T_DIR_DEFAULT)) < 0)
556  BAIL(NC_EHDFERR);
557  if ((retval = nc4_get_typelen_mem(h5, type_info->nc_typeid, 0,
558  &type_info->size)))
559  BAIL(retval);
560 
561  /* Set the "class" of the type */
562  if (xtype == NC_CHAR)
563  type_info->nc_type_class = NC_CHAR;
564  else
565  {
566  H5T_class_t class;
567 
568  if ((class = H5Tget_class(type_info->hdf_typeid)) < 0)
569  BAIL(NC_EHDFERR);
570  switch(class)
571  {
572  case H5T_STRING:
573  type_info->nc_type_class = NC_STRING;
574  break;
575 
576  case H5T_INTEGER:
577  type_info->nc_type_class = NC_INT;
578  break;
579 
580  case H5T_FLOAT:
581  type_info->nc_type_class = NC_FLOAT;
582  break;
583 
584  default:
585  BAIL(NC_EBADTYPID);
586  }
587  }
588  }
589  /* If this is a user defined type, find it. */
590  else
591  {
592  if (nc4_find_type(grp->nc4_info, xtype, &type_info))
593  BAIL(NC_EBADTYPE);
594  }
595 
596  /* Create a new var and fill in some HDF5 cache setting values. */
597  if ((retval = nc4_var_add(&var)))
598  BAIL(retval);
599 
600  /* Now fill in the values in the var info structure. */
601  if (!(var->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
602  BAIL(NC_ENOMEM);
603  strcpy(var->name, norm_name);
604  var->hash = hash_fast(norm_name, strlen(norm_name));
605  var->varid = grp->nvars++;
606  var->ndims = ndims;
607  var->is_new_var = NC_TRUE;
608 
609  /* Add a var to the variable array, growing it as needed. */
610  if ((retval = nc4_vararray_add(grp, var)))
611  BAIL(retval);
612 
613  /* Point to the type, and increment its ref. count */
614  var->type_info = type_info;
615  var->type_info->rc++;
616  type_info = NULL;
617 
618  /* Allocate space for dimension information. */
619  if (ndims)
620  {
621  if (!(var->dim = calloc(ndims, sizeof(NC_DIM_INFO_T *))))
622  BAIL(NC_ENOMEM);
623  if (!(var->dimids = calloc(ndims, sizeof(int))))
624  BAIL(NC_ENOMEM);
625  }
626 
627  /* Set variables no_fill to match the database default
628  * unless the variable type is variable length (NC_STRING or NC_VLEN)
629  * or is user-defined type.
630  */
631  if (var->type_info->nc_type_class < NC_STRING)
632  var->no_fill = h5->fill_mode;
633 
634  /* Assign dimensions to the variable */
635  /* At the same time, check to see if this is a coordinate
636  * variable. If so, it will have the same name as one of its
637  * dimensions. If it is a coordinate var, is it a coordinate var in
638  * the same group as the dim? */
639  /* Also, check whether we should use contiguous or chunked storage */
640  var->contiguous = NC_TRUE;
641  for (d = 0; d < ndims; d++)
642  {
643  NC_GRP_INFO_T *dim_grp;
644 
645  /* Look up each dimension */
646  if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, &dim_grp)))
647  BAIL(retval);
648 
649  /* Check for dim index 0 having the same name, in the same group */
650  if (d == 0 && dim_grp == grp && dim->hash == var->hash && strcmp(dim->name, norm_name) == 0)
651  {
652  var->dimscale = NC_TRUE;
653  dim->coord_var = var;
654 
655  /* Use variable's dataset ID for the dimscale ID. So delete
656  * the HDF5 DIM_WITHOUT_VARIABLE dataset that was created for
657  * this dim. */
658  if (dim->hdf_dimscaleid)
659  {
660  /* Detach dimscale from any variables using it */
661  if ((retval = rec_detach_scales(grp, dimidsp[d], dim->hdf_dimscaleid)) < 0)
662  BAIL(retval);
663 
664  /* Close the HDF5 DIM_WITHOUT_VARIABLE dataset. */
665  if (H5Dclose(dim->hdf_dimscaleid) < 0)
666  BAIL(NC_EHDFERR);
667  dim->hdf_dimscaleid = 0;
668 
669  /* Now delete the DIM_WITHOUT_VARIABLE dataset (it will be
670  * recreated later, if necessary). */
671  if (H5Gunlink(grp->hdf_grpid, dim->name) < 0)
672  BAIL(NC_EDIMMETA);
673  }
674  }
675 
676  /* Check for unlimited dimension and turn off contiguous storage. */
677  if (dim->unlimited)
678  var->contiguous = NC_FALSE;
679 
680  /* Track dimensions for variable */
681  var->dimids[d] = dimidsp[d];
682  var->dim[d] = dim;
683  }
684 
685  /* Determine default chunksizes for this variable. (Even for
686  * variables which may be contiguous.) */
687  LOG((4, "allocating array of %d size_t to hold chunksizes for var %s",
688  var->ndims, var->name));
689  if (var->ndims)
690  if (!(var->chunksizes = calloc(var->ndims, sizeof(size_t))))
691  BAIL(NC_ENOMEM);
692 
693  if ((retval = nc4_find_default_chunksizes2(grp, var)))
694  BAIL(retval);
695 
696  /* Is this a variable with a chunksize greater than the current
697  * cache size? */
698  if ((retval = nc4_adjust_var_cache(grp, var)))
699  BAIL(retval);
700 
701  /* If the user names this variable the same as a dimension, but
702  * doesn't use that dimension first in its list of dimension ids,
703  * is not a coordinate variable. I need to change its HDF5 name,
704  * because the dimension will cause a HDF5 dataset to be created,
705  * and this var has the same name. */
706  for (dim = grp->dim; dim; dim = dim->l.next)
707  if (dim->hash == var->hash && !strcmp(dim->name, norm_name) &&
708  (!var->ndims || dimidsp[0] != dim->dimid))
709  {
710  /* Set a different hdf5 name for this variable to avoid name
711  * clash. */
712  if (strlen(norm_name) + strlen(NON_COORD_PREPEND) > NC_MAX_NAME)
713  BAIL(NC_EMAXNAME);
714  if (!(var->hdf5_name = malloc((strlen(NON_COORD_PREPEND) +
715  strlen(norm_name) + 1) * sizeof(char))))
716  BAIL(NC_ENOMEM);
717 
718  sprintf(var->hdf5_name, "%s%s", NON_COORD_PREPEND, norm_name);
719  }
720 
721  /* If this is a coordinate var, it is marked as a HDF5 dimension
722  * scale. (We found dim above.) Otherwise, allocate space to
723  * remember whether dimension scales have been attached to each
724  * dimension. */
725  if (!var->dimscale && ndims)
726  if (!(var->dimscale_attached = calloc(ndims, sizeof(nc_bool_t))))
727  BAIL(NC_ENOMEM);
728 
729  /* Return the varid. */
730  if (varidp)
731  *varidp = var->varid;
732  LOG((4, "new varid %d", var->varid));
733 
734 exit:
735  if (type_info)
736  if ((retval = nc4_type_free(type_info)))
737  BAIL2(retval);
738 
739  return retval;
740 }
741 
779 int
780 NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
781  int *ndimsp, int *dimidsp, int *nattsp,
782  int *shufflep, int *deflatep, int *deflate_levelp,
783  int *fletcher32p, int *contiguousp, size_t *chunksizesp,
784  int *no_fill, void *fill_valuep, int *endiannessp,
785  unsigned int* idp, size_t* nparamsp, unsigned int* params
786  )
787 {
788  NC *nc;
789  NC_GRP_INFO_T *grp;
790  NC_HDF5_FILE_INFO_T *h5;
791  NC_VAR_INFO_T *var;
792  NC_ATT_INFO_T *att;
793  int natts=0;
794  int d;
795  int retval;
796 
797  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
798 
799  /* Find info for this file and group, and set pointer to each. */
800  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
801  return retval;
802 
803  assert(nc);
804  assert(grp && h5);
805 
806  /* Walk through the list of vars, and return the info about the one
807  with a matching varid. If the varid is -1, find the global
808  atts and call it a day. */
809  if (varid == NC_GLOBAL)
810  {
811  if (nattsp)
812  {
813  for (att = grp->att; att; att = att->l.next)
814  natts++;
815  *nattsp = natts;
816  }
817  return NC_NOERR;
818  }
819 
820  /* Find the var. */
821  if (varid < 0 || varid >= grp->vars.nelems)
822  return NC_ENOTVAR;
823  var = grp->vars.value[varid];
824  assert(var && var->varid == varid);
825 
826  /* Copy the data to the user's data buffers. */
827  if (name)
828  strcpy(name, var->name);
829  if (xtypep)
830  *xtypep = var->type_info->nc_typeid;
831  if (ndimsp)
832  *ndimsp = var->ndims;
833  if (dimidsp)
834  for (d = 0; d < var->ndims; d++)
835  dimidsp[d] = var->dimids[d];
836  if (nattsp)
837  {
838  for (att = var->att; att; att = att->l.next)
839  natts++;
840  *nattsp = natts;
841  }
842 
843  /* Chunking stuff. */
844  if (!var->contiguous && chunksizesp)
845  for (d = 0; d < var->ndims; d++)
846  {
847  chunksizesp[d] = var->chunksizes[d];
848  LOG((4, "chunksizesp[%d]=%d", d, chunksizesp[d]));
849  }
850 
851  if (contiguousp)
852  *contiguousp = var->contiguous ? NC_CONTIGUOUS : NC_CHUNKED;
853 
854  /* Filter stuff. */
855  if (deflatep)
856  *deflatep = (int)var->deflate;
857  if (deflate_levelp)
858  *deflate_levelp = var->deflate_level;
859  if (shufflep)
860  *shufflep = (int)var->shuffle;
861  if (fletcher32p)
862  *fletcher32p = (int)var->fletcher32;
863 
864  if (idp)
865  *idp = var->filterid;
866  if (nparamsp)
867  *nparamsp = (var->params == NULL ? 0 : var->nparams);
868  if (params && var->params != NULL)
869  memcpy(params,var->params,var->nparams*sizeof(unsigned int));
870 
871  /* Fill value stuff. */
872  if (no_fill)
873  *no_fill = (int)var->no_fill;
874 
875  /* Don't do a thing with fill_valuep if no_fill mode is set for
876  * this var, or if fill_valuep is NULL. */
877  if (!var->no_fill && fill_valuep)
878  {
879  /* Do we have a fill value for this var? */
880  if (var->fill_value)
881  {
882  if (var->type_info->nc_type_class == NC_STRING)
883  {
884  assert(*(char **)var->fill_value);
885  /* This will allocate memeory and copy the string. */
886  if (!(*(char **)fill_valuep = strdup(*(char **)var->fill_value)))
887  {
888  free(*(char **)fill_valuep);
889  return NC_ENOMEM;
890  }
891  }
892  else
893  {
894  assert(var->type_info->size);
895  memcpy(fill_valuep, var->fill_value, var->type_info->size);
896  }
897  }
898  else
899  {
900  if (var->type_info->nc_type_class == NC_STRING)
901  {
902  if (!(*(char **)fill_valuep = calloc(1, sizeof(char *))))
903  return NC_ENOMEM;
904 
905  if ((retval = nc4_get_default_fill_value(var->type_info, (char **)fill_valuep)))
906  {
907  free(*(char **)fill_valuep);
908  return retval;
909  }
910  }
911  else
912  {
913  if ((retval = nc4_get_default_fill_value(var->type_info, fill_valuep)))
914  return retval;
915  }
916  }
917  }
918 
919  /* Does the user want the endianness of this variable? */
920  if (endiannessp)
921  *endiannessp = var->type_info->endianness;
922 
923  return NC_NOERR;
924 }
925 
957 static int
958 nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
959  int *deflate_level, int *fletcher32, int *contiguous,
960  const size_t *chunksizes, int *no_fill,
961  const void *fill_value, int *endianness)
962 {
963  NC *nc;
964  NC_GRP_INFO_T *grp;
965  NC_HDF5_FILE_INFO_T *h5;
966  NC_VAR_INFO_T *var;
967  int d;
968  int retval;
969 
970  /* All or none of these will be provided. */
971  assert((deflate && deflate_level && shuffle) ||
972  (!deflate && !deflate_level && !shuffle));
973 
974  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
975 
976  /* Find info for this file and group, and set pointer to each. */
977  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
978  return retval;
979  assert(nc && grp && h5);
980 
981  /* Trying to write to a read-only file? No way, Jose! */
982  if (h5->no_write)
983  return NC_EPERM;
984 
985  /* Find the var. */
986  if (varid < 0 || varid >= grp->vars.nelems)
987  return NC_ENOTVAR;
988  var = grp->vars.value[varid];
989  assert(var && var->varid == varid);
990 
991  /* Can't turn on parallel and deflate/fletcher32/szip/shuffle. */
992  if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
993  if (deflate || fletcher32 || shuffle)
994  return NC_EINVAL;
995  }
996 
997  /* If the HDF5 dataset has already been created, then it is too
998  * late to set all the extra stuff. */
999  if (var->created)
1000  return NC_ELATEDEF;
1001 
1002  /* Check compression options. */
1003  if (deflate && !deflate_level)
1004  return NC_EINVAL;
1005 
1006  /* Valid deflate level? */
1007  if (deflate)
1008  {
1009  if (*deflate)
1010  if (*deflate_level < NC_MIN_DEFLATE_LEVEL ||
1011  *deflate_level > NC_MAX_DEFLATE_LEVEL)
1012  return NC_EINVAL;
1013 
1014  /* For scalars, just ignore attempt to deflate. */
1015  if (!var->ndims)
1016  return NC_NOERR;
1017 
1018  /* Well, if we couldn't find any errors, I guess we have to take
1019  * the users settings. Darn! */
1020  var->contiguous = NC_FALSE;
1021  var->deflate = *deflate;
1022  if (*deflate)
1023  var->deflate_level = *deflate_level;
1024  LOG((3, "%s: *deflate_level %d", __func__, *deflate_level));
1025  }
1026 
1027  /* Shuffle filter? */
1028  if (shuffle)
1029  {
1030  var->shuffle = *shuffle;
1031  var->contiguous = NC_FALSE;
1032  }
1033 
1034  /* Fletcher32 checksum error protection? */
1035  if (fletcher32)
1036  {
1037  var->fletcher32 = *fletcher32;
1038  var->contiguous = NC_FALSE;
1039  }
1040 
1041  /* Does the user want a contiguous dataset? Not so fast! Make sure
1042  * that there are no unlimited dimensions, and no filters in use
1043  * for this data. */
1044  if (contiguous && *contiguous)
1045  {
1046  if (var->deflate || var->fletcher32 || var->shuffle)
1047  return NC_EINVAL;
1048 
1049  for (d = 0; d < var->ndims; d++)
1050  if (var->dim[d]->unlimited)
1051  return NC_EINVAL;
1052  var->contiguous = NC_TRUE;
1053  }
1054 
1055  /* Chunksizes anyone? */
1056  if (contiguous && *contiguous == NC_CHUNKED)
1057  {
1058  var->contiguous = NC_FALSE;
1059 
1060  /* If the user provided chunksizes, check that they are not too
1061  * big, and that their total size of chunk is less than 4 GB. */
1062  if (chunksizes)
1063  {
1064 
1065  if ((retval = check_chunksizes(grp, var, chunksizes)))
1066  return retval;
1067 
1068  /* Ensure chunksize is smaller than dimension size */
1069  for (d = 0; d < var->ndims; d++)
1070  if(!var->dim[d]->unlimited && var->dim[d]->len > 0 && chunksizes[d] > var->dim[d]->len)
1071  return NC_EBADCHUNK;
1072 
1073  /* Set the chunksizes for this variable. */
1074  for (d = 0; d < var->ndims; d++)
1075  var->chunksizes[d] = chunksizes[d];
1076  }
1077  }
1078 
1079  /* Is this a variable with a chunksize greater than the current
1080  * cache size? */
1081  if (!var->contiguous && (deflate || contiguous))
1082  {
1083  /* Determine default chunksizes for this variable (do nothing
1084  * for scalar vars). */
1085  if (var->chunksizes && !var->chunksizes[0])
1086  if ((retval = nc4_find_default_chunksizes2(grp, var)))
1087  return retval;
1088 
1089  /* Adjust the cache. */
1090  if ((retval = nc4_adjust_var_cache(grp, var)))
1091  return retval;
1092  }
1093 
1094  /* Are we setting a fill modes? */
1095  if (no_fill)
1096  {
1097  if (*no_fill)
1098  {
1099  /* NC_STRING types may not turn off fill mode. It's disallowed
1100  * by HDF5 and will cause a HDF5 error later. */
1101  if (*no_fill)
1102  if (var->type_info->nc_typeid == NC_STRING)
1103  return NC_EINVAL;
1104 
1105  /* Set the no-fill mode. */
1106  var->no_fill = NC_TRUE;
1107  }
1108  else
1109  var->no_fill = NC_FALSE;
1110  }
1111 
1112  /* Are we setting a fill value? */
1113  if (fill_value && !var->no_fill)
1114  {
1115  /* Copy the fill_value. */
1116  LOG((4, "Copying fill value into metadata for variable %s",
1117  var->name));
1118 
1119  /* If there's a _FillValue attribute, delete it. */
1120  retval = NC4_del_att(ncid, varid, _FillValue);
1121  if (retval && retval != NC_ENOTATT)
1122  return retval;
1123 
1124  /* Create a _FillValue attribute. */
1125  if ((retval = nc_put_att(ncid, varid, _FillValue, var->type_info->nc_typeid, 1, fill_value)))
1126  return retval;
1127  }
1128 
1129  /* Is the user setting the endianness? */
1130  if (endianness)
1131  var->type_info->endianness = *endianness;
1132 
1133  return NC_NOERR;
1134 }
1135 
1157 int
1158 NC4_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
1159  int deflate_level)
1160 {
1161  return nc_def_var_extra(ncid, varid, &shuffle, &deflate,
1162  &deflate_level, NULL, NULL, NULL, NULL, NULL, NULL);
1163 }
1164 
1183 int
1184 NC4_def_var_fletcher32(int ncid, int varid, int fletcher32)
1185 {
1186  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, &fletcher32,
1187  NULL, NULL, NULL, NULL, NULL);
1188 }
1189 
1212 int
1213 NC4_def_var_chunking(int ncid, int varid, int contiguous, const size_t *chunksizesp)
1214 {
1215  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL,
1216  &contiguous, chunksizesp, NULL, NULL, NULL);
1217 }
1218 
1235 int
1236 nc_inq_var_chunking_ints(int ncid, int varid, int *contiguousp, int *chunksizesp)
1237 {
1238  NC *nc;
1239  NC_GRP_INFO_T *grp;
1240  NC_VAR_INFO_T *var;
1241  NC_HDF5_FILE_INFO_T *h5;
1242 
1243  size_t *cs = NULL;
1244  int i, retval;
1245 
1246  /* Find this ncid's file info. */
1247  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1248  return retval;
1249  assert(nc);
1250 
1251  /* Find var cause I need the number of dims. */
1252  if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
1253  return retval;
1254 
1255  /* Allocate space for the size_t copy of the chunksizes array. */
1256  if (var->ndims)
1257  if (!(cs = malloc(var->ndims * sizeof(size_t))))
1258  return NC_ENOMEM;
1259 
1260  retval = NC4_inq_var_all(ncid, varid, NULL, NULL, NULL, NULL, NULL,
1261  NULL, NULL, NULL, NULL, contiguousp, cs, NULL,
1262  NULL, NULL, NULL, NULL, NULL);
1263 
1264  /* Copy from size_t array. */
1265  if (chunksizesp && var->contiguous == NC_CHUNKED)
1266  for (i = 0; i < var->ndims; i++)
1267  {
1268  chunksizesp[i] = (int)cs[i];
1269  if (cs[i] > NC_MAX_INT)
1270  retval = NC_ERANGE;
1271  }
1272 
1273  if (var->ndims)
1274  free(cs);
1275  return retval;
1276 }
1277 
1298 int
1299 nc_def_var_chunking_ints(int ncid, int varid, int contiguous, int *chunksizesp)
1300 {
1301  NC *nc;
1302  NC_GRP_INFO_T *grp;
1303  NC_VAR_INFO_T *var;
1304  NC_HDF5_FILE_INFO_T *h5;
1305  size_t *cs = NULL;
1306  int i, retval;
1307 
1308  /* Find this ncid's file info. */
1309  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1310  return retval;
1311  assert(nc);
1312 
1313  /* Find var cause I need the number of dims. */
1314  if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
1315  return retval;
1316 
1317  /* Allocate space for the size_t copy of the chunksizes array. */
1318  if (var->ndims)
1319  if (!(cs = malloc(var->ndims * sizeof(size_t))))
1320  return NC_ENOMEM;
1321 
1322  /* Copy to size_t array. */
1323  for (i = 0; i < var->ndims; i++)
1324  cs[i] = chunksizesp[i];
1325 
1326  retval = nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL,
1327  &contiguous, cs, NULL, NULL, NULL);
1328 
1329  if (var->ndims)
1330  free(cs);
1331  return retval;
1332 }
1333 
1357 int
1358 NC4_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
1359 {
1360  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
1361  NULL, &no_fill, fill_value, NULL);
1362 }
1363 
1386 int
1387 NC4_def_var_endian(int ncid, int varid, int endianness)
1388 {
1389  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
1390  NULL, NULL, NULL, &endianness);
1391 }
1392 
1412 int
1413 NC4_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams,
1414  const unsigned int* parms)
1415 {
1416  int retval = NC_NOERR;
1417  NC *nc;
1418  NC_GRP_INFO_T *grp;
1419  NC_HDF5_FILE_INFO_T *h5;
1420  NC_VAR_INFO_T *var;
1421 
1422  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
1423 
1424  /* Find info for this file and group, and set pointer to each. */
1425  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1426  return retval;
1427 
1428  assert(nc && grp && h5);
1429 
1430  /* Find the var. */
1431  if (varid < 0 || varid >= grp->vars.nelems)
1432  return NC_ENOTVAR;
1433  var = grp->vars.value[varid];
1434  if (!var) return NC_ENOTVAR;
1435  assert(var->varid == varid);
1436 
1437  /* Can't turn on parallel and filters */
1438  if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
1439  return NC_EINVAL;
1440  }
1441 
1442  /* If the HDF5 dataset has already been created, then it is too
1443  * late to set all the extra stuff. */
1444  if (var->created)
1445  return NC_ELATEDEF;
1446 
1447 #ifdef HAVE_H5Z_SZIP
1448  if(id == H5Z_FILTER_SZIP) {
1449  if(nparams != 2)
1450  return NC_EFILTER; /* incorrect no. of parameters */
1451  }
1452 #else
1453  if(id == H5Z_FILTER_SZIP)
1454  return NC_EFILTER; /* Not allowed */
1455 #endif
1456 
1457 #if 0
1458  {
1459  unsigned int fcfg = 0;
1460  herr_t herr = H5Zget_filter_info(id,&fcfg);
1461  if(herr < 0)
1462  return NC_EFILTER;
1463  if((H5Z_FILTER_CONFIG_ENCODE_ENABLED & fcfg) == 0
1464  || (H5Z_FILTER_CONFIG_DECODE_ENABLED & fcfg) == 0)
1465  return NC_EFILTER;
1466  }
1467 #endif /*0*/
1468 
1469  var->filterid = id;
1470  var->nparams = nparams;
1471  var->params = NULL;
1472  if(parms != NULL) {
1473  var->params = (unsigned int*)calloc(nparams,sizeof(unsigned int));
1474  if(var->params == NULL) return NC_ENOMEM;
1475  memcpy(var->params,parms,sizeof(unsigned int)*var->nparams);
1476  }
1477  return NC_NOERR;
1478 }
1479 
1492 int
1493 NC4_inq_varid(int ncid, const char *name, int *varidp)
1494 {
1495  NC *nc;
1496  NC_GRP_INFO_T *grp;
1497  NC_VAR_INFO_T *var;
1498  char norm_name[NC_MAX_NAME + 1];
1499  int retval;
1500  uint32_t nn_hash;
1501  int i;
1502 
1503  if (!name)
1504  return NC_EINVAL;
1505  if (!varidp)
1506  return NC_NOERR;
1507 
1508  LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
1509 
1510  /* Find info for this file and group, and set pointer to each. */
1511  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, NULL)))
1512  return retval;
1513 
1514  /* Normalize name. */
1515  if ((retval = nc4_normalize_name(name, norm_name)))
1516  return retval;
1517 
1518  nn_hash = hash_fast(norm_name, strlen(norm_name));
1519 
1520  /* Find var of this name. */
1521  for (i=0; i < grp->vars.nelems; i++)
1522  {
1523  var = grp->vars.value[i];
1524  if (!var) continue;
1525  if (nn_hash == var->hash && !(strcmp(var->name, norm_name)))
1526  {
1527  *varidp = var->varid;
1528  return NC_NOERR;
1529  }
1530  }
1531  return NC_ENOTVAR;
1532 }
1533 
1551 int
1552 NC4_rename_var(int ncid, int varid, const char *name)
1553 {
1554  NC *nc;
1555  NC_GRP_INFO_T *grp;
1556  NC_HDF5_FILE_INFO_T *h5;
1557  NC_VAR_INFO_T *var, *tmp_var;
1558  uint32_t nn_hash;
1559  int retval = NC_NOERR;
1560  int i;
1561 
1562  if (!name)
1563  return NC_EINVAL;
1564 
1565  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid,
1566  name));
1567 
1568  /* Find info for this file and group, and set pointer to each. */
1569  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1570  return retval;
1571  assert(h5 && grp && h5);
1572 
1573  /* Is the new name too long? */
1574  if (strlen(name) > NC_MAX_NAME)
1575  return NC_EMAXNAME;
1576 
1577  /* Trying to write to a read-only file? No way, Jose! */
1578  if (h5->no_write)
1579  return NC_EPERM;
1580 
1581  /* Check name validity, if strict nc3 rules are in effect for this
1582  * file. */
1583  if ((retval = NC_check_name(name)))
1584  return retval;
1585 
1586  /* Check if name is in use, and retain a pointer to the correct variable */
1587  nn_hash = hash_fast(name, strlen(name));
1588  tmp_var = NULL;
1589  for (i=0; i < grp->vars.nelems; i++)
1590  {
1591  var = grp->vars.value[i];
1592  if (!var) continue;
1593  if (nn_hash == var->hash && !strncmp(var->name, name, NC_MAX_NAME))
1594  return NC_ENAMEINUSE;
1595  if (var->varid == varid)
1596  tmp_var = var;
1597  }
1598  if (!tmp_var)
1599  return NC_ENOTVAR;
1600  var = tmp_var;
1601 
1602  /* If we're not in define mode, new name must be of equal or
1603  less size, if strict nc3 rules are in effect for this . */
1604  if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(var->name) &&
1605  (h5->cmode & NC_CLASSIC_MODEL))
1606  return NC_ENOTINDEFINE;
1607 
1608  /* Change the HDF5 file, if this var has already been created
1609  there. Should we check here to ensure there is not already a
1610  dimscale dataset of name name??? */
1611  if (var->created)
1612  {
1613  /* Is there an existing dimscale-only dataset of this name? If
1614  * so, it must be deleted. */
1615  if (var->ndims && var->dim[0]->hdf_dimscaleid)
1616  {
1617  if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->dimid, var->dim[0])))
1618  return retval;
1619  }
1620 
1621  LOG((3, "Moving dataset %s to %s", var->name, name));
1622  if (H5Gmove(grp->hdf_grpid, var->name, name) < 0)
1623  BAIL(NC_EHDFERR);
1624  }
1625 
1626  /* Now change the name in our metadata. */
1627  free(var->name);
1628  if (!(var->name = malloc((strlen(name) + 1) * sizeof(char))))
1629  return NC_ENOMEM;
1630  strcpy(var->name, name);
1631  var->hash = nn_hash;
1632  LOG((3, "var is now %s", var->name));
1633 
1634  /* Check if this was a coordinate variable previously, but names are different now */
1635  if (var->dimscale && strcmp(var->name, var->dim[0]->name))
1636  {
1637  /* Break up the coordinate variable */
1638  if ((retval = nc4_break_coord_var(grp, var, var->dim[0])))
1639  return retval;
1640  }
1641 
1642  /* Check if this should become a coordinate variable */
1643  if (!var->dimscale)
1644  {
1645  /* Only variables with >0 dimensions can become coordinate variables */
1646  if (var->ndims)
1647  {
1648  NC_GRP_INFO_T *dim_grp;
1649  NC_DIM_INFO_T *dim;
1650 
1651  /* Check to see if this is became a coordinate variable. If so, it
1652  * will have the same name as dimension index 0. If it is a
1653  * coordinate var, is it a coordinate var in the same group as the dim?
1654  */
1655  if ((retval = nc4_find_dim(grp, var->dimids[0], &dim, &dim_grp)))
1656  return retval;
1657  if (!strcmp(dim->name, name) && dim_grp == grp)
1658  {
1659  /* Reform the coordinate variable */
1660  if ((retval = nc4_reform_coord_var(grp, var, dim)))
1661  return retval;
1662  var->became_coord_var = NC_TRUE;
1663  }
1664  }
1665  }
1666 
1667 exit:
1668  return retval;
1669 }
1670 
1689 int
1690 NC4_var_par_access(int ncid, int varid, int par_access)
1691 {
1692 #ifndef USE_PARALLEL4
1693  return NC_ENOPAR;
1694 #else
1695  NC *nc;
1696  NC_GRP_INFO_T *grp;
1697  NC_HDF5_FILE_INFO_T *h5;
1698  NC_VAR_INFO_T *var;
1699  int retval;
1700 
1701  LOG((1, "%s: ncid 0x%x varid %d par_access %d", __func__, ncid,
1702  varid, par_access));
1703 
1704  if (par_access != NC_INDEPENDENT && par_access != NC_COLLECTIVE)
1705  return NC_EINVAL;
1706 
1707  /* Find info for this file and group, and set pointer to each. */
1708  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1709  return retval;
1710 
1711  /* This function only for files opened with nc_open_par or nc_create_par. */
1712  if (!h5->parallel)
1713  return NC_ENOPAR;
1714 
1715  /* Find the var, and set its preference. */
1716  if (varid < 0 || varid >= grp->vars.nelems)
1717  return NC_ENOTVAR;
1718  var = grp->vars.value[varid];
1719  if (!var) return NC_ENOTVAR;
1720  assert(var->varid == varid);
1721 
1722  if (par_access)
1723  var->parallel_access = NC_COLLECTIVE;
1724  else
1725  var->parallel_access = NC_INDEPENDENT;
1726  return NC_NOERR;
1727 #endif /* USE_PARALLEL4 */
1728 }
1729 
1745 int
1746 NC4_put_vara(int ncid, int varid, const size_t *startp,
1747  const size_t *countp, const void *op, int memtype)
1748 {
1749  NC *nc;
1750 
1751  if (!(nc = nc4_find_nc_file(ncid, NULL)))
1752  return NC_EBADID;
1753 
1754  return nc4_put_vara(nc, ncid, varid, startp, countp, memtype, 0, (void *)op);
1755 }
1756 
1772 int
1773 NC4_get_vara(int ncid, int varid, const size_t *startp,
1774  const size_t *countp, void *ip, int memtype)
1775 {
1776  NC *nc;
1777  NC_HDF5_FILE_INFO_T* h5;
1778 
1779  LOG((2, "%s: ncid 0x%x varid %d memtype %d", __func__, ncid, varid,
1780  memtype));
1781 
1782  if (!(nc = nc4_find_nc_file(ncid, &h5)))
1783  return NC_EBADID;
1784 
1785  /* Get the data. */
1786  return nc4_get_vara(nc, ncid, varid, startp, countp, memtype,
1787  0, (void *)ip);
1788 }
#define _FillValue
Name of fill value attribute.
Definition: netcdf.h:112
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:395
#define NC_CHUNKED
In HDF5 files you can set storage for each variable to be either contiguous or chunked, with nc_def_var_chunking().
Definition: netcdf.h:284
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:35
#define NC_MAX_INT
Max or min values for a type.
Definition: netcdf.h:93
#define NC_CONTIGUOUS
In HDF5 files you can set storage for each variable to be either contiguous or chunked, with nc_def_var_chunking().
Definition: netcdf.h:285
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:135
#define NC_ERANGE
Math result not representable.
Definition: netcdf.h:394
#define NC_MAX_VAR_DIMS
max per variable dimensions
Definition: netcdf.h:266
int NC4_get_vara(int ncid, int varid, const size_t *startp, const size_t *countp, void *ip, int memtype)
Read an array of values.
Definition: nc4var.c:1773
#define NC_EHDFERR
Error at HDF5 layer.
Definition: netcdf.h:427
#define NC_MPIIO
Turn on MPI I/O.
Definition: netcdf.h:152
#define NC_STRING
string
Definition: netcdf.h:46
#define NC_ENOTINDEFINE
Operation not allowed in data mode.
Definition: netcdf.h:331
#define NC_DOUBLE
double precision floating point number
Definition: netcdf.h:40
#define NC_INDEPENDENT
Use with nc_var_par_access() to set parallel access to independent.
Definition: netcdf_par.h:23
#define NC_EMAXDIMS
NC_MAX_DIMS exceeded.
Definition: netcdf.h:352
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:24
#define NC_COLLECTIVE
Use with nc_var_par_access() to set parallel access to collective.
Definition: netcdf_par.h:25
#define H5Z_FILTER_SZIP
ID of HDF SZIP filter.
Definition: dvarinq.c:15
#define NC_MIN_DEFLATE_LEVEL
Minimum deflate level.
Definition: netcdf.h:306
#define NC_ENAMEINUSE
String match to name in use.
Definition: netcdf.h:354
int NC4_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams, const unsigned int *parms)
Definition: nc4var.c:1413
#define NC_VLEN
vlen (variable-length) types
Definition: netcdf.h:52
#define NC_EFILTER
Filter operation failed.
Definition: netcdf.h:459
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:357
#define NC_EDIMMETA
Problem with dimension metadata.
Definition: netcdf.h:432
#define NC_MAX_DEFLATE_LEVEL
Maximum deflate level.
Definition: netcdf.h:307
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:325
#define NC_INT
signed 4 byte integer
Definition: netcdf.h:37
#define NC_ESTRICTNC3
Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
Definition: netcdf.h:438
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:265
#define NC_NAT
Not A Type.
Definition: netcdf.h:33
#define NC_EBADTYPID
Bad type ID.
Definition: netcdf.h:443
EXTERNL int nc_put_att(int ncid, int varid, const char *name, nc_type xtype, size_t len, const void *op)
Write an attribute.
Definition: dattput.c:229
#define NC_EBADID
Not a netcdf id.
Definition: netcdf.h:322
#define NC_ENOPAR
Parallel operation on file opened for non-parallel access.
Definition: netcdf.h:440
#define NC_MAX_UINT
Max or min values for a type.
Definition: netcdf.h:101
#define NC_ENDIAN_NATIVE
In HDF5 files you can set the endianness of variables with nc_def_var_endian().
Definition: netcdf.h:275
#define NC_ENOTVAR
Variable not found.
Definition: netcdf.h:369
#define NC_EMAXNAME
NC_MAX_NAME exceeded.
Definition: netcdf.h:373
#define NC_EPERM
Write to read only.
Definition: netcdf.h:326
#define NC_NOERR
No Error.
Definition: netcdf.h:315
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition: netcdf.h:238
#define NC_ELATEDEF
Attempt to define var properties, like deflate, after enddef.
Definition: netcdf.h:449
#define NC_FLOAT
single precision floating point number
Definition: netcdf.h:39
#define NC_ENOTATT
Attribute not found.
Definition: netcdf.h:355
#define NC_MPIPOSIX
Turn on MPI POSIX I/O.
Definition: netcdf.h:155
#define NC_EBADCHUNK
Bad chunksize.
Definition: netcdf.h:453

Return to the Main Unidata NetCDF page.
Generated on Fri May 11 2018 21:24:00 for NetCDF. NetCDF is a Unidata library.