NetCDF  4.6.0
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  {
269  if (chunksizes[d] < 1)
270  return NC_EINVAL;
271  dprod *= (double) chunksizes[d];
272  }
273 
274  if (dprod > (double) NC_MAX_UINT)
275  return NC_EBADCHUNK;
276 
277  return NC_NOERR;
278 }
279 
291 static int
292 nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
293 {
294  int d;
295  size_t type_size;
296  float num_values = 1, num_unlim = 0;
297  int retval;
298  size_t suggested_size;
299 #ifdef LOGGING
300  double total_chunk_size;
301 #endif
302 
303  if (var->type_info->nc_type_class == NC_STRING)
304  type_size = sizeof(char *);
305  else
306  type_size = var->type_info->size;
307 
308 #ifdef LOGGING
309  /* Later this will become the total number of bytes in the default
310  * chunk. */
311  total_chunk_size = (double) type_size;
312 #endif
313 
314  /* How many values in the variable (or one record, if there are
315  * unlimited dimensions). */
316  for (d = 0; d < var->ndims; d++)
317  {
318  assert(var->dim[d]);
319  if (! var->dim[d]->unlimited)
320  num_values *= (float)var->dim[d]->len;
321  else {
322  num_unlim++;
323  var->chunksizes[d] = 1; /* overwritten below, if all dims are unlimited */
324  }
325  }
326  /* Special case to avoid 1D vars with unlim dim taking huge amount
327  of space (DEFAULT_CHUNK_SIZE bytes). Instead we limit to about
328  4KB */
329  if (var->ndims == 1 && num_unlim == 1) {
330  if (DEFAULT_CHUNK_SIZE / type_size <= 0)
331  suggested_size = 1;
332  else if (DEFAULT_CHUNK_SIZE / type_size > DEFAULT_1D_UNLIM_SIZE)
333  suggested_size = DEFAULT_1D_UNLIM_SIZE;
334  else
335  suggested_size = DEFAULT_CHUNK_SIZE / type_size;
336  var->chunksizes[0] = suggested_size / type_size;
337  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
338  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[0]));
339  }
340  if (var->ndims > 1 && var->ndims == num_unlim) { /* all dims unlimited */
341  suggested_size = pow((double)DEFAULT_CHUNK_SIZE/type_size, 1.0/(double)(var->ndims));
342  for (d = 0; d < var->ndims; d++)
343  {
344  var->chunksizes[d] = suggested_size ? suggested_size : 1;
345  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
346  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
347  }
348  }
349 
350  /* Pick a chunk length for each dimension, if one has not already
351  * been picked above. */
352  for (d = 0; d < var->ndims; d++)
353  if (!var->chunksizes[d])
354  {
355  suggested_size = (pow((double)DEFAULT_CHUNK_SIZE/(num_values * type_size),
356  1.0/(double)(var->ndims - num_unlim)) * var->dim[d]->len - .5);
357  if (suggested_size > var->dim[d]->len)
358  suggested_size = var->dim[d]->len;
359  var->chunksizes[d] = suggested_size ? suggested_size : 1;
360  LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
361  "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
362  }
363 
364 #ifdef LOGGING
365  /* Find total chunk size. */
366  for (d = 0; d < var->ndims; d++)
367  total_chunk_size *= (double) var->chunksizes[d];
368  LOG((4, "total_chunk_size %f", total_chunk_size));
369 #endif
370 
371  /* But did this result in a chunk that is too big? */
372  retval = check_chunksizes(grp, var, var->chunksizes);
373  if (retval)
374  {
375  /* Other error? */
376  if (retval != NC_EBADCHUNK)
377  return retval;
378 
379  /* Chunk is too big! Reduce each dimension by half and try again. */
380  for ( ; retval == NC_EBADCHUNK; retval = check_chunksizes(grp, var, var->chunksizes))
381  for (d = 0; d < var->ndims; d++)
382  var->chunksizes[d] = var->chunksizes[d]/2 ? var->chunksizes[d]/2 : 1;
383  }
384 
385  /* Do we have any big data overhangs? They can be dangerous to
386  * babies, the elderly, or confused campers who have had too much
387  * beer. */
388  for (d = 0; d < var->ndims; d++)
389  {
390  size_t num_chunks;
391  size_t overhang;
392  assert(var->chunksizes[d] > 0);
393  num_chunks = (var->dim[d]->len + var->chunksizes[d] - 1) / var->chunksizes[d];
394  if(num_chunks > 0) {
395  overhang = (num_chunks * var->chunksizes[d]) - var->dim[d]->len;
396  var->chunksizes[d] -= overhang / num_chunks;
397  }
398  }
399 
400  return NC_NOERR;
401 }
402 
413 int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
414 {
415  NC_VAR_INFO_T **vp = NULL;
416 
417  if (grp->vars.nalloc == 0) {
418  assert(grp->vars.nelems == 0);
419  vp = (NC_VAR_INFO_T **) malloc(NC_ARRAY_GROWBY * sizeof(NC_VAR_INFO_T *));
420  if(vp == NULL)
421  return NC_ENOMEM;
422  grp->vars.value = vp;
423  grp->vars.nalloc = NC_ARRAY_GROWBY;
424  }
425  else if(grp->vars.nelems +1 > grp->vars.nalloc) {
426  vp = (NC_VAR_INFO_T **) realloc(grp->vars.value,
427  (grp->vars.nalloc + NC_ARRAY_GROWBY) * sizeof(NC_VAR_INFO_T *));
428  if(vp == NULL)
429  return NC_ENOMEM;
430  grp->vars.value = vp;
431  grp->vars.nalloc += NC_ARRAY_GROWBY;
432  }
433 
434  if(var != NULL) {
435  assert(var->varid == grp->vars.nelems);
436  grp->vars.value[grp->vars.nelems] = var;
437  grp->vars.nelems++;
438  }
439  return NC_NOERR;
440 }
441 
473 int
474 NC4_def_var(int ncid, const char *name, nc_type xtype,
475  int ndims, const int *dimidsp, int *varidp)
476 {
477  NC_GRP_INFO_T *grp;
478  NC_VAR_INFO_T *var;
479  NC_DIM_INFO_T *dim;
480  NC_HDF5_FILE_INFO_T *h5;
481  NC_TYPE_INFO_T *type_info = NULL;
482  char norm_name[NC_MAX_NAME + 1];
483  int d;
484  int retval;
485 
486  /* Find info for this file and group, and set pointer to each. */
487  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
488  BAIL(retval);
489  assert(grp && h5);
490 
491  /* If it's not in define mode, strict nc3 files error out,
492  * otherwise switch to define mode. This will also check that the
493  * file is writable. */
494  if (!(h5->flags & NC_INDEF))
495  {
496  if (h5->cmode & NC_CLASSIC_MODEL)
497  BAIL(NC_ENOTINDEFINE);
498  if ((retval = NC4_redef(ncid)))
499  BAIL(retval);
500  }
501  assert(!h5->no_write);
502 
503  /* Check and normalize the name. */
504  if ((retval = nc4_check_name(name, norm_name)))
505  BAIL(retval);
506 
507  /* Not a Type is, well, not a type.*/
508  if (xtype == NC_NAT)
509  BAIL(NC_EBADTYPE);
510 
511  /* For classic files, only classic types are allowed. */
512  if (h5->cmode & NC_CLASSIC_MODEL && xtype > NC_DOUBLE)
513  BAIL(NC_ESTRICTNC3);
514 
515  /* For classic files */
516  if (h5->cmode & NC_CLASSIC_MODEL && ndims > NC_MAX_VAR_DIMS)
517  BAIL(NC_EMAXDIMS);
518 
519  /* cast needed for braindead systems with signed size_t */
520  if((unsigned long) ndims > X_INT_MAX) /* Backward compat */
521  BAIL(NC_EINVAL);
522 
523  /* Check that this name is not in use as a var, grp, or type. */
524  if ((retval = nc4_check_dup_name(grp, norm_name)))
525  BAIL(retval);
526 
527  /* If there for non-scalar vars, dim IDs must be provided. */
528  if (ndims && !dimidsp)
529  BAIL(NC_EINVAL);
530 
531  /* Check all the dimids to make sure they exist. */
532  for (d = 0; d < ndims; d++)
533  if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, NULL)))
534  BAIL(retval);
535 
536  /* These degrubbing messages sure are handy! */
537  LOG((2, "%s: name %s type %d ndims %d", __func__, norm_name, xtype, ndims));
538 #ifdef LOGGING
539  {
540  int dd;
541  for (dd = 0; dd < ndims; dd++)
542  LOG((4, "dimid[%d] %d", dd, dimidsp[dd]));
543  }
544 #endif
545 
546  /* If this is a user-defined type, there is a type_info struct with
547  * all the type information. For atomic types, fake up a type_info
548  * struct. */
549  if (xtype <= NC_STRING)
550  {
551  if (!(type_info = calloc(1, sizeof(NC_TYPE_INFO_T))))
552  BAIL(NC_ENOMEM);
553  type_info->nc_typeid = xtype;
554  type_info->endianness = NC_ENDIAN_NATIVE;
555  if ((retval = nc4_get_hdf_typeid(h5, xtype, &type_info->hdf_typeid,
556  type_info->endianness)))
557  BAIL(retval);
558  if ((type_info->native_hdf_typeid = H5Tget_native_type(type_info->hdf_typeid,
559  H5T_DIR_DEFAULT)) < 0)
560  BAIL(NC_EHDFERR);
561  if ((retval = nc4_get_typelen_mem(h5, type_info->nc_typeid, 0,
562  &type_info->size)))
563  BAIL(retval);
564 
565  /* Set the "class" of the type */
566  if (xtype == NC_CHAR)
567  type_info->nc_type_class = NC_CHAR;
568  else
569  {
570  H5T_class_t class;
571 
572  if ((class = H5Tget_class(type_info->hdf_typeid)) < 0)
573  BAIL(NC_EHDFERR);
574  switch(class)
575  {
576  case H5T_STRING:
577  type_info->nc_type_class = NC_STRING;
578  break;
579 
580  case H5T_INTEGER:
581  type_info->nc_type_class = NC_INT;
582  break;
583 
584  case H5T_FLOAT:
585  type_info->nc_type_class = NC_FLOAT;
586  break;
587 
588  default:
589  BAIL(NC_EBADTYPID);
590  }
591  }
592  }
593  /* If this is a user defined type, find it. */
594  else
595  {
596  if (nc4_find_type(grp->nc4_info, xtype, &type_info))
597  BAIL(NC_EBADTYPE);
598  }
599 
600  /* Create a new var and fill in some HDF5 cache setting values. */
601  if ((retval = nc4_var_add(&var)))
602  BAIL(retval);
603 
604  /* Now fill in the values in the var info structure. */
605  if (!(var->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
606  BAIL(NC_ENOMEM);
607  strcpy(var->name, norm_name);
608  var->hash = hash_fast(norm_name, strlen(norm_name));
609  var->varid = grp->nvars++;
610  var->ndims = ndims;
611  var->is_new_var = NC_TRUE;
612 
613  /* Add a var to the variable array, growing it as needed. */
614  if ((retval = nc4_vararray_add(grp, var)))
615  BAIL(retval);
616 
617  /* Point to the type, and increment its ref. count */
618  var->type_info = type_info;
619  var->type_info->rc++;
620  type_info = NULL;
621 
622  /* Allocate space for dimension information. */
623  if (ndims)
624  {
625  if (!(var->dim = calloc(ndims, sizeof(NC_DIM_INFO_T *))))
626  BAIL(NC_ENOMEM);
627  if (!(var->dimids = calloc(ndims, sizeof(int))))
628  BAIL(NC_ENOMEM);
629  }
630 
631  /* Set variables no_fill to match the database default
632  * unless the variable type is variable length (NC_STRING or NC_VLEN)
633  * or is user-defined type.
634  */
635  if (var->type_info->nc_type_class < NC_STRING)
636  var->no_fill = h5->fill_mode;
637 
638  /* Assign dimensions to the variable */
639  /* At the same time, check to see if this is a coordinate
640  * variable. If so, it will have the same name as one of its
641  * dimensions. If it is a coordinate var, is it a coordinate var in
642  * the same group as the dim? */
643  /* Also, check whether we should use contiguous or chunked storage */
644  var->contiguous = NC_TRUE;
645  for (d = 0; d < ndims; d++)
646  {
647  NC_GRP_INFO_T *dim_grp;
648 
649  /* Look up each dimension */
650  if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, &dim_grp)))
651  BAIL(retval);
652 
653  /* Check for dim index 0 having the same name, in the same group */
654  if (d == 0 && dim_grp == grp && dim->hash == var->hash && strcmp(dim->name, norm_name) == 0)
655  {
656  var->dimscale = NC_TRUE;
657  dim->coord_var = var;
658 
659  /* Use variable's dataset ID for the dimscale ID. So delete
660  * the HDF5 DIM_WITHOUT_VARIABLE dataset that was created for
661  * this dim. */
662  if (dim->hdf_dimscaleid)
663  {
664  /* Detach dimscale from any variables using it */
665  if ((retval = rec_detach_scales(grp, dimidsp[d], dim->hdf_dimscaleid)) < 0)
666  BAIL(retval);
667 
668  /* Close the HDF5 DIM_WITHOUT_VARIABLE dataset. */
669  if (H5Dclose(dim->hdf_dimscaleid) < 0)
670  BAIL(NC_EHDFERR);
671  dim->hdf_dimscaleid = 0;
672 
673  /* Now delete the DIM_WITHOUT_VARIABLE dataset (it will be
674  * recreated later, if necessary). */
675  if (H5Gunlink(grp->hdf_grpid, dim->name) < 0)
676  BAIL(NC_EDIMMETA);
677  }
678  }
679 
680  /* Check for unlimited dimension and turn off contiguous storage. */
681  if (dim->unlimited)
682  var->contiguous = NC_FALSE;
683 
684  /* Track dimensions for variable */
685  var->dimids[d] = dimidsp[d];
686  var->dim[d] = dim;
687  }
688 
689  /* Determine default chunksizes for this variable. (Even for
690  * variables which may be contiguous.) */
691  LOG((4, "allocating array of %d size_t to hold chunksizes for var %s",
692  var->ndims, var->name));
693  if (var->ndims)
694  if (!(var->chunksizes = calloc(var->ndims, sizeof(size_t))))
695  BAIL(NC_ENOMEM);
696 
697  if ((retval = nc4_find_default_chunksizes2(grp, var)))
698  BAIL(retval);
699 
700  /* Is this a variable with a chunksize greater than the current
701  * cache size? */
702  if ((retval = nc4_adjust_var_cache(grp, var)))
703  BAIL(retval);
704 
705  /* If the user names this variable the same as a dimension, but
706  * doesn't use that dimension first in its list of dimension ids,
707  * is not a coordinate variable. I need to change its HDF5 name,
708  * because the dimension will cause a HDF5 dataset to be created,
709  * and this var has the same name. */
710  for (dim = grp->dim; dim; dim = dim->l.next)
711  if (dim->hash == var->hash && !strcmp(dim->name, norm_name) &&
712  (!var->ndims || dimidsp[0] != dim->dimid))
713  {
714  /* Set a different hdf5 name for this variable to avoid name
715  * clash. */
716  if (strlen(norm_name) + strlen(NON_COORD_PREPEND) > NC_MAX_NAME)
717  BAIL(NC_EMAXNAME);
718  if (!(var->hdf5_name = malloc((strlen(NON_COORD_PREPEND) +
719  strlen(norm_name) + 1) * sizeof(char))))
720  BAIL(NC_ENOMEM);
721 
722  sprintf(var->hdf5_name, "%s%s", NON_COORD_PREPEND, norm_name);
723  }
724 
725  /* If this is a coordinate var, it is marked as a HDF5 dimension
726  * scale. (We found dim above.) Otherwise, allocate space to
727  * remember whether dimension scales have been attached to each
728  * dimension. */
729  if (!var->dimscale && ndims)
730  if (ndims && !(var->dimscale_attached = calloc(ndims, sizeof(nc_bool_t))))
731  BAIL(NC_ENOMEM);
732 
733  /* Return the varid. */
734  if (varidp)
735  *varidp = var->varid;
736  LOG((4, "new varid %d", var->varid));
737 
738 exit:
739  if (type_info)
740  if ((retval = nc4_type_free(type_info)))
741  BAIL2(retval);
742 
743  return retval;
744 }
745 
783 int
784 NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
785  int *ndimsp, int *dimidsp, int *nattsp,
786  int *shufflep, int *deflatep, int *deflate_levelp,
787  int *fletcher32p, int *contiguousp, size_t *chunksizesp,
788  int *no_fill, void *fill_valuep, int *endiannessp,
789  unsigned int* idp, size_t* nparamsp, unsigned int* params
790  )
791 {
792  NC *nc;
793  NC_GRP_INFO_T *grp;
794  NC_HDF5_FILE_INFO_T *h5;
795  NC_VAR_INFO_T *var;
796  NC_ATT_INFO_T *att;
797  int natts=0;
798  int d;
799  int retval;
800 
801  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
802 
803  /* Find info for this file and group, and set pointer to each. */
804  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
805  return retval;
806 
807  assert(nc);
808  assert(grp && h5);
809 
810  /* Walk through the list of vars, and return the info about the one
811  with a matching varid. If the varid is -1, find the global
812  atts and call it a day. */
813  if (varid == NC_GLOBAL)
814  {
815  if (nattsp)
816  {
817  for (att = grp->att; att; att = att->l.next)
818  natts++;
819  *nattsp = natts;
820  }
821  return NC_NOERR;
822  }
823 
824  /* Find the var. */
825  if (varid < 0 || varid >= grp->vars.nelems)
826  return NC_ENOTVAR;
827  var = grp->vars.value[varid];
828  assert(var && var->varid == varid);
829 
830  /* Copy the data to the user's data buffers. */
831  if (name)
832  strcpy(name, var->name);
833  if (xtypep)
834  *xtypep = var->type_info->nc_typeid;
835  if (ndimsp)
836  *ndimsp = var->ndims;
837  if (dimidsp)
838  for (d = 0; d < var->ndims; d++)
839  dimidsp[d] = var->dimids[d];
840  if (nattsp)
841  {
842  for (att = var->att; att; att = att->l.next)
843  natts++;
844  *nattsp = natts;
845  }
846 
847  /* Chunking stuff. */
848  if (!var->contiguous && chunksizesp)
849  for (d = 0; d < var->ndims; d++)
850  {
851  chunksizesp[d] = var->chunksizes[d];
852  LOG((4, "chunksizesp[%d]=%d", d, chunksizesp[d]));
853  }
854 
855  if (contiguousp)
856  *contiguousp = var->contiguous ? NC_CONTIGUOUS : NC_CHUNKED;
857 
858  /* Filter stuff. */
859  if (deflatep)
860  *deflatep = (int)var->deflate;
861  if (deflate_levelp)
862  *deflate_levelp = var->deflate_level;
863  if (shufflep)
864  *shufflep = (int)var->shuffle;
865  if (fletcher32p)
866  *fletcher32p = (int)var->fletcher32;
867 
868  if (idp)
869  *idp = var->filterid;
870  if (nparamsp)
871  *nparamsp = (var->params == NULL ? 0 : var->nparams);
872  if (params && var->params != NULL)
873  memcpy(params,var->params,var->nparams*sizeof(unsigned int));
874 
875  /* Fill value stuff. */
876  if (no_fill)
877  *no_fill = (int)var->no_fill;
878 
879  /* Don't do a thing with fill_valuep if no_fill mode is set for
880  * this var, or if fill_valuep is NULL. */
881  if (!var->no_fill && fill_valuep)
882  {
883  /* Do we have a fill value for this var? */
884  if (var->fill_value)
885  {
886  if (var->type_info->nc_type_class == NC_STRING)
887  {
888  if (*(char **)var->fill_value) {
889 
890  if (!(fill_valuep = calloc(1, sizeof(char *))))
891  return NC_ENOMEM;
892 
893  if (!(*(char **)fill_valuep = strdup(*(char **)var->fill_value)))
894  {
895  free(fill_valuep);
896  return NC_ENOMEM;
897  }
898  }
899  }
900  else {
901  assert(var->type_info->size);
902  memcpy(fill_valuep, var->fill_value, var->type_info->size);
903  }
904  }
905  else
906  {
907  if (var->type_info->nc_type_class == NC_STRING)
908  {
909  if (!(fill_valuep = calloc(1, sizeof(char *))))
910  return NC_ENOMEM;
911 
912  if ((retval = nc4_get_default_fill_value(var->type_info, (char **)fill_valuep)))
913  {
914  free(fill_valuep);
915  return retval;
916  } else {
917  free(fill_valuep);
918  }
919  }
920  else
921  {
922  if ((retval = nc4_get_default_fill_value(var->type_info, fill_valuep)))
923  return retval;
924  }
925  }
926  }
927 
928  /* Does the user want the endianness of this variable? */
929  if (endiannessp)
930  *endiannessp = var->type_info->endianness;
931 
932  return NC_NOERR;
933 }
934 
966 static int
967 nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
968  int *deflate_level, int *fletcher32, int *contiguous,
969  const size_t *chunksizes, int *no_fill,
970  const void *fill_value, int *endianness)
971 {
972  NC *nc;
973  NC_GRP_INFO_T *grp;
974  NC_HDF5_FILE_INFO_T *h5;
975  NC_VAR_INFO_T *var;
976  int d;
977  int retval;
978 
979  /* All or none of these will be provided. */
980  assert((deflate && deflate_level && shuffle) ||
981  (!deflate && !deflate_level && !shuffle));
982 
983  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
984 
985  /* Find info for this file and group, and set pointer to each. */
986  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
987  return retval;
988  assert(nc && grp && h5);
989 
990  /* Trying to write to a read-only file? No way, Jose! */
991  if (h5->no_write)
992  return NC_EPERM;
993 
994  /* Find the var. */
995  if (varid < 0 || varid >= grp->vars.nelems)
996  return NC_ENOTVAR;
997  var = grp->vars.value[varid];
998  assert(var && var->varid == varid);
999 
1000  /* Can't turn on parallel and deflate/fletcher32/szip/shuffle. */
1001  if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
1002  if (deflate || fletcher32 || shuffle)
1003  return NC_EINVAL;
1004  }
1005 
1006  /* If the HDF5 dataset has already been created, then it is too
1007  * late to set all the extra stuff. */
1008  if (var->created)
1009  return NC_ELATEDEF;
1010 
1011  /* Check compression options. */
1012  if (deflate && !deflate_level)
1013  return NC_EINVAL;
1014 
1015  /* Valid deflate level? */
1016  if (deflate && deflate_level)
1017  {
1018  if (*deflate)
1019  if (*deflate_level < NC_MIN_DEFLATE_LEVEL ||
1020  *deflate_level > NC_MAX_DEFLATE_LEVEL)
1021  return NC_EINVAL;
1022 
1023  /* For scalars, just ignore attempt to deflate. */
1024  if (!var->ndims)
1025  return NC_NOERR;
1026 
1027  /* Well, if we couldn't find any errors, I guess we have to take
1028  * the users settings. Darn! */
1029  var->contiguous = NC_FALSE;
1030  var->deflate = *deflate;
1031  if (*deflate)
1032  var->deflate_level = *deflate_level;
1033  LOG((3, "%s: *deflate_level %d", __func__, *deflate_level));
1034  }
1035 
1036  /* Shuffle filter? */
1037  if (shuffle)
1038  {
1039  var->shuffle = *shuffle;
1040  var->contiguous = NC_FALSE;
1041  }
1042 
1043  /* Fletcher32 checksum error protection? */
1044  if (fletcher32)
1045  {
1046  var->fletcher32 = *fletcher32;
1047  var->contiguous = NC_FALSE;
1048  }
1049 
1050  /* Does the user want a contiguous dataset? Not so fast! Make sure
1051  * that there are no unlimited dimensions, and no filters in use
1052  * for this data. */
1053  if (contiguous && *contiguous)
1054  {
1055  if (var->deflate || var->fletcher32 || var->shuffle)
1056  return NC_EINVAL;
1057 
1058  for (d = 0; d < var->ndims; d++)
1059  if (var->dim[d]->unlimited)
1060  return NC_EINVAL;
1061  var->contiguous = NC_TRUE;
1062  }
1063 
1064  /* Chunksizes anyone? */
1065  if (contiguous && *contiguous == NC_CHUNKED)
1066  {
1067  var->contiguous = NC_FALSE;
1068 
1069  /* If the user provided chunksizes, check that they are not too
1070  * big, and that their total size of chunk is less than 4 GB. */
1071  if (chunksizes)
1072  {
1073 
1074  if ((retval = check_chunksizes(grp, var, chunksizes)))
1075  return retval;
1076 
1077  /* Ensure chunksize is smaller than dimension size */
1078  for (d = 0; d < var->ndims; d++)
1079  if(!var->dim[d]->unlimited && var->dim[d]->len > 0 && chunksizes[d] > var->dim[d]->len)
1080  return NC_EBADCHUNK;
1081 
1082  /* Set the chunksizes for this variable. */
1083  for (d = 0; d < var->ndims; d++)
1084  var->chunksizes[d] = chunksizes[d];
1085  }
1086  }
1087 
1088  /* Is this a variable with a chunksize greater than the current
1089  * cache size? */
1090  if (!var->contiguous && (deflate || contiguous))
1091  {
1092  /* Determine default chunksizes for this variable (do nothing
1093  * for scalar vars). */
1094  if (var->chunksizes && !var->chunksizes[0])
1095  if ((retval = nc4_find_default_chunksizes2(grp, var)))
1096  return retval;
1097 
1098  /* Adjust the cache. */
1099  if ((retval = nc4_adjust_var_cache(grp, var)))
1100  return retval;
1101  }
1102 
1103  /* Are we setting a fill modes? */
1104  if (no_fill)
1105  {
1106  if (*no_fill)
1107  var->no_fill = NC_TRUE;
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 #ifdef USE_HDF4
1314  if(h5->hdf4)
1315  return NC_NOERR;
1316 #endif
1317 
1318  /* Find var cause I need the number of dims. */
1319  if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
1320  return retval;
1321 
1322  /* Allocate space for the size_t copy of the chunksizes array. */
1323  if (var->ndims)
1324  if (!(cs = malloc(var->ndims * sizeof(size_t))))
1325  return NC_ENOMEM;
1326 
1327  /* Copy to size_t array. */
1328  for (i = 0; i < var->ndims; i++)
1329  cs[i] = chunksizesp[i];
1330 
1331  retval = nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL,
1332  &contiguous, cs, NULL, NULL, NULL);
1333 
1334  if (var->ndims)
1335  free(cs);
1336  return retval;
1337 }
1338 
1362 int
1363 NC4_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
1364 {
1365  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
1366  NULL, &no_fill, fill_value, NULL);
1367 }
1368 
1391 int
1392 NC4_def_var_endian(int ncid, int varid, int endianness)
1393 {
1394  return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
1395  NULL, NULL, NULL, &endianness);
1396 }
1397 
1417 int
1418 NC4_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams,
1419  const unsigned int* parms)
1420 {
1421  int retval = NC_NOERR;
1422  NC *nc;
1423  NC_GRP_INFO_T *grp;
1424  NC_HDF5_FILE_INFO_T *h5;
1425  NC_VAR_INFO_T *var;
1426 
1427  LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid));
1428 
1429  /* Find info for this file and group, and set pointer to each. */
1430  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1431  return retval;
1432 
1433  assert(nc && grp && h5);
1434 
1435  /* Find the var. */
1436  if (varid < 0 || varid >= grp->vars.nelems)
1437  return NC_ENOTVAR;
1438  var = grp->vars.value[varid];
1439  if (!var) return NC_ENOTVAR;
1440  assert(var->varid == varid);
1441 
1442  /* Can't turn on parallel and filters */
1443  if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
1444  return NC_EINVAL;
1445  }
1446 
1447  /* If the HDF5 dataset has already been created, then it is too
1448  * late to set all the extra stuff. */
1449  if (var->created)
1450  return NC_ELATEDEF;
1451 
1452 #ifdef HAVE_H5Z_SZIP
1453  if(id == H5Z_FILTER_SZIP) {
1454  if(nparams != 2)
1455  return NC_EFILTER; /* incorrect no. of parameters */
1456  }
1457 #else
1458  if(id == H5Z_FILTER_SZIP)
1459  return NC_EFILTER; /* Not allowed */
1460 #endif
1461 
1462 #if 0
1463  {
1464  unsigned int fcfg = 0;
1465  herr_t herr = H5Zget_filter_info(id,&fcfg);
1466  if(herr < 0)
1467  return NC_EFILTER;
1468  if((H5Z_FILTER_CONFIG_ENCODE_ENABLED & fcfg) == 0
1469  || (H5Z_FILTER_CONFIG_DECODE_ENABLED & fcfg) == 0)
1470  return NC_EFILTER;
1471  }
1472 #endif /*0*/
1473 
1474  var->filterid = id;
1475  var->nparams = nparams;
1476  var->params = NULL;
1477  if(parms != NULL) {
1478  var->params = (unsigned int*)calloc(nparams,sizeof(unsigned int));
1479  if(var->params == NULL) return NC_ENOMEM;
1480  memcpy(var->params,parms,sizeof(unsigned int)*var->nparams);
1481  }
1482  return NC_NOERR;
1483 }
1484 
1497 int
1498 NC4_inq_varid(int ncid, const char *name, int *varidp)
1499 {
1500  NC *nc;
1501  NC_GRP_INFO_T *grp;
1502  NC_VAR_INFO_T *var;
1503  char norm_name[NC_MAX_NAME + 1];
1504  int retval;
1505  uint32_t nn_hash;
1506  int i;
1507 
1508  if (!name)
1509  return NC_EINVAL;
1510  if (!varidp)
1511  return NC_NOERR;
1512 
1513  LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
1514 
1515  /* Find info for this file and group, and set pointer to each. */
1516  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, NULL)))
1517  return retval;
1518 
1519  /* Normalize name. */
1520  if ((retval = nc4_normalize_name(name, norm_name)))
1521  return retval;
1522 
1523  nn_hash = hash_fast(norm_name, strlen(norm_name));
1524 
1525  /* Find var of this name. */
1526  for (i=0; i < grp->vars.nelems; i++)
1527  {
1528  var = grp->vars.value[i];
1529  if (!var) continue;
1530  if (nn_hash == var->hash && !(strcmp(var->name, norm_name)))
1531  {
1532  *varidp = var->varid;
1533  return NC_NOERR;
1534  }
1535  }
1536  return NC_ENOTVAR;
1537 }
1538 
1556 int
1557 NC4_rename_var(int ncid, int varid, const char *name)
1558 {
1559  NC *nc;
1560  NC_GRP_INFO_T *grp;
1561  NC_HDF5_FILE_INFO_T *h5;
1562  NC_VAR_INFO_T *var, *tmp_var;
1563  uint32_t nn_hash;
1564  int retval = NC_NOERR;
1565  int i;
1566 
1567  if (!name)
1568  return NC_EINVAL;
1569 
1570  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid,
1571  name));
1572 
1573  /* Find info for this file and group, and set pointer to each. */
1574  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1575  return retval;
1576  assert(h5 && grp && h5);
1577 
1578  /* Is the new name too long? */
1579  if (strlen(name) > NC_MAX_NAME)
1580  return NC_EMAXNAME;
1581 
1582  /* Trying to write to a read-only file? No way, Jose! */
1583  if (h5->no_write)
1584  return NC_EPERM;
1585 
1586  /* Check name validity, if strict nc3 rules are in effect for this
1587  * file. */
1588  if ((retval = NC_check_name(name)))
1589  return retval;
1590 
1591  /* Check if name is in use, and retain a pointer to the correct variable */
1592  nn_hash = hash_fast(name, strlen(name));
1593  tmp_var = NULL;
1594  for (i=0; i < grp->vars.nelems; i++)
1595  {
1596  var = grp->vars.value[i];
1597  if (!var) continue;
1598  if (nn_hash == var->hash && !strncmp(var->name, name, NC_MAX_NAME))
1599  return NC_ENAMEINUSE;
1600  if (var->varid == varid)
1601  tmp_var = var;
1602  }
1603  if (!tmp_var)
1604  return NC_ENOTVAR;
1605  var = tmp_var;
1606 
1607  /* If we're not in define mode, new name must be of equal or
1608  less size, if strict nc3 rules are in effect for this . */
1609  if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(var->name) &&
1610  (h5->cmode & NC_CLASSIC_MODEL))
1611  return NC_ENOTINDEFINE;
1612 
1613  /* Change the HDF5 file, if this var has already been created
1614  there. Should we check here to ensure there is not already a
1615  dimscale dataset of name name??? */
1616  if (var->created)
1617  {
1618  /* Is there an existing dimscale-only dataset of this name? If
1619  * so, it must be deleted. */
1620  if (var->ndims && var->dim[0]->hdf_dimscaleid)
1621  {
1622  if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->dimid, var->dim[0])))
1623  return retval;
1624  }
1625 
1626  LOG((3, "Moving dataset %s to %s", var->name, name));
1627  if (H5Gmove(grp->hdf_grpid, var->name, name) < 0)
1628  BAIL(NC_EHDFERR);
1629  }
1630 
1631  /* Now change the name in our metadata. */
1632  free(var->name);
1633  if (!(var->name = malloc((strlen(name) + 1) * sizeof(char))))
1634  return NC_ENOMEM;
1635  strcpy(var->name, name);
1636  var->hash = nn_hash;
1637  LOG((3, "var is now %s", var->name));
1638 
1639  /* Check if this was a coordinate variable previously, but names are different now */
1640  if (var->dimscale && strcmp(var->name, var->dim[0]->name))
1641  {
1642  /* Break up the coordinate variable */
1643  if ((retval = nc4_break_coord_var(grp, var, var->dim[0])))
1644  return retval;
1645  }
1646 
1647  /* Check if this should become a coordinate variable */
1648  if (!var->dimscale)
1649  {
1650  /* Only variables with >0 dimensions can become coordinate variables */
1651  if (var->ndims)
1652  {
1653  NC_GRP_INFO_T *dim_grp;
1654  NC_DIM_INFO_T *dim;
1655 
1656  /* Check to see if this is became a coordinate variable. If so, it
1657  * will have the same name as dimension index 0. If it is a
1658  * coordinate var, is it a coordinate var in the same group as the dim?
1659  */
1660  if ((retval = nc4_find_dim(grp, var->dimids[0], &dim, &dim_grp)))
1661  return retval;
1662  if (strcmp(dim->name, name) == 0 && dim_grp == grp)
1663  {
1664  /* Reform the coordinate variable */
1665  if ((retval = nc4_reform_coord_var(grp, var, dim)))
1666  return retval;
1667  }
1668  }
1669  }
1670 
1671 exit:
1672  return retval;
1673 }
1674 
1693 int
1694 NC4_var_par_access(int ncid, int varid, int par_access)
1695 {
1696 #ifndef USE_PARALLEL4
1697  return NC_ENOPAR;
1698 #else
1699  NC *nc;
1700  NC_GRP_INFO_T *grp;
1701  NC_HDF5_FILE_INFO_T *h5;
1702  NC_VAR_INFO_T *var;
1703  int retval;
1704 
1705  LOG((1, "%s: ncid 0x%x varid %d par_access %d", __func__, ncid,
1706  varid, par_access));
1707 
1708  if (par_access != NC_INDEPENDENT && par_access != NC_COLLECTIVE)
1709  return NC_EINVAL;
1710 
1711  /* Find info for this file and group, and set pointer to each. */
1712  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
1713  return retval;
1714 
1715  /* This function only for files opened with nc_open_par or nc_create_par. */
1716  if (!h5->parallel)
1717  return NC_ENOPAR;
1718 
1719  /* Find the var, and set its preference. */
1720  if (varid < 0 || varid >= grp->vars.nelems)
1721  return NC_ENOTVAR;
1722  var = grp->vars.value[varid];
1723  if (!var) return NC_ENOTVAR;
1724  assert(var->varid == varid);
1725 
1726  if (par_access)
1727  var->parallel_access = NC_COLLECTIVE;
1728  else
1729  var->parallel_access = NC_INDEPENDENT;
1730  return NC_NOERR;
1731 #endif /* USE_PARALLEL4 */
1732 }
1733 
1734 #ifdef USE_HDF4
1735 
1748 static int
1749 nc4_get_hdf4_vara(NC *nc, int ncid, int varid, const size_t *startp,
1750  const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
1751 {
1752  NC_GRP_INFO_T *grp;
1753  NC_HDF5_FILE_INFO_T *h5;
1754  NC_VAR_INFO_T *var;
1755  int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS];
1756  int retval, d;
1757 
1758  /* Find our metadata for this file, group, and var. */
1759  assert(nc);
1760  if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
1761  return retval;
1762  h5 = NC4_DATA(nc);
1763  assert(grp && h5 && var && var->name);
1764 
1765  for (d = 0; d < var->ndims; d++)
1766  {
1767  start32[d] = startp[d];
1768  edge32[d] = countp[d];
1769  }
1770 
1771  if (SDreaddata(var->sdsid, start32, NULL, edge32, data))
1772  return NC_EHDFERR;
1773 
1774  return NC_NOERR;
1775 }
1776 #endif /* USE_HDF4 */
1777 
1793 int
1794 NC4_put_vara(int ncid, int varid, const size_t *startp,
1795  const size_t *countp, const void *op, int memtype)
1796 {
1797  NC *nc;
1798 
1799  if (!(nc = nc4_find_nc_file(ncid, NULL)))
1800  return NC_EBADID;
1801 
1802  return nc4_put_vara(nc, ncid, varid, startp, countp, memtype, 0, (void *)op);
1803 }
1804 
1820 int
1821 NC4_get_vara(int ncid, int varid, const size_t *startp,
1822  const size_t *countp, void *ip, int memtype)
1823 {
1824  NC *nc;
1825  NC_HDF5_FILE_INFO_T* h5;
1826 
1827  LOG((2, "%s: ncid 0x%x varid %d memtype %d", __func__, ncid, varid,
1828  memtype));
1829 
1830  if (!(nc = nc4_find_nc_file(ncid, &h5)))
1831  return NC_EBADID;
1832 
1833 #ifdef USE_HDF4
1834  /* Handle HDF4 cases. */
1835  if (h5->hdf4)
1836  return nc4_get_hdf4_vara(nc, ncid, varid, startp, countp, memtype,
1837  0, (void *)ip);
1838 #endif /* USE_HDF4 */
1839 
1840  /* Handle HDF5 cases. */
1841  return nc4_get_vara(nc, ncid, varid, startp, countp, memtype,
1842  0, (void *)ip);
1843 }
#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:1821
#define NC_EHDFERR
Error at HDF5 layer.
Definition: netcdf.h:426
#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:1418
#define NC_VLEN
vlen (variable-length) types
Definition: netcdf.h:52
#define NC_EFILTER
Filter operation failed.
Definition: netcdf.h:458
#define NC_EBADTYPE
Not a netcdf data type.
Definition: netcdf.h:357
#define NC_EDIMMETA
Problem with dimension metadata.
Definition: netcdf.h:431
#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:437
#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:442
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:439
#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:448
#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:452

Return to the Main Unidata NetCDF page.
Generated on Thu Jan 25 2018 21:06:33 for NetCDF. NetCDF is a Unidata library.