source: XIOS/dev/dev_cmip6_omp/extern/src_netcdf4/dfile.c @ 1606

Last change on this file since 1606 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 52.4 KB
Line 
1/** \file
2File create and open functions
3
4These functions end up calling functions in one of the dispatch layers
5(netCDF-4, dap server, etc).
6
7Copyright 2010 University Corporation for Atmospheric
8Research/Unidata. See COPYRIGHT file for more info. 
9*/
10
11#include "config.h"
12#include <stdlib.h>
13#ifdef HAVE_SYS_RESOURCE_H
14#include <sys/resource.h>
15#endif
16#ifdef HAVE_SYS_TYPES_H
17#include <sys/types.h>
18#endif
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif
22#ifdef HAVE_FCNTL_H
23#include <fcntl.h>
24#endif
25#include "ncdispatch.h"
26
27static int nc_initialized = 0;
28
29/** \defgroup datasets NetCDF Files
30
31NetCDF opens datasets as files or remote access URLs.
32
33A netCDF dataset that has not yet been opened can only be referred to
34by its dataset name. Once a netCDF dataset is opened, it is referred
35to by a netCDF ID, which is a small non-negative integer returned when
36you create or open the dataset. A netCDF ID is much like a file
37descriptor in C or a logical unit number in FORTRAN. In any single
38program, the netCDF IDs of distinct open netCDF datasets are
39distinct. A single netCDF dataset may be opened multiple times and
40will then have multiple distinct netCDF IDs; however at most one of
41the open instances of a single netCDF dataset should permit
42writing. When an open netCDF dataset is closed, the ID is no longer
43associated with a netCDF dataset.
44
45Functions that deal with the netCDF library include:
46- Get version of library.
47- Get error message corresponding to a returned error code.
48
49The operations supported on a netCDF dataset as a single object are:
50- Create, given dataset name and whether to overwrite or not.
51- Open for access, given dataset name and read or write intent.
52- Put into define mode, to add dimensions, variables, or attributes.
53- Take out of define mode, checking consistency of additions.
54- Close, writing to disk if required.
55- Inquire about the number of dimensions, number of variables,
56number of global attributes, and ID of the unlimited dimension, if
57any.
58- Synchronize to disk to make sure it is current.
59- Set and unset nofill mode for optimized sequential writes.
60- After a summary of conventions used in describing the netCDF
61interfaces, the rest of this chapter presents a detailed description
62of the interfaces for these operations.
63*/
64/**@{*/
65
66size_t* NC_coord_zero;
67size_t* NC_coord_one;
68
69static void
70nc_local_initialize(void)
71{
72    int i;
73    NC_coord_zero = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
74    if(NC_coord_zero == NULL) abort();
75    NC_coord_one = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
76    if(NC_coord_one == NULL) abort();
77    for(i=0;i<NC_MAX_VAR_DIMS;i++) {
78        NC_coord_one[i] = 1;
79        NC_coord_zero[i] = 0;
80    }
81}
82
83static int
84NC_check_file_type(const char *path, int use_parallel, void *mpi_info,
85                   int *cdf, int *hdf)
86{
87   char magic[MAGIC_NUMBER_LEN];
88   
89   *hdf = 0; *cdf = 0;
90
91   /* Get the 4-byte magic from the beginning of the file. Don't use posix
92    * for parallel, use the MPI functions instead. */
93#ifdef USE_PARALLEL_MPIO
94   if (use_parallel) 
95   {
96      MPI_File fh;
97      MPI_Status status;
98      int retval;
99      MPI_Comm comm = 0;
100      MPI_Info info = 0;
101
102      if(mpi_info != NULL) {
103         comm = ((NC_MPI_INFO*)mpi_info)->comm;
104         info = ((NC_MPI_INFO*)mpi_info)->info;
105      }
106      if((retval = MPI_File_open(comm, (char *)path, MPI_MODE_RDONLY,info, 
107                                 &fh)) != MPI_SUCCESS)
108         return NC_EPARINIT;
109      if((retval = MPI_File_read(fh, magic, MAGIC_NUMBER_LEN, MPI_CHAR,
110                                 &status)) != MPI_SUCCESS)
111         return NC_EPARINIT;
112      if((retval = MPI_File_close(&fh)) != MPI_SUCCESS)
113         return NC_EPARINIT;
114   } else
115#endif /* USE_PARALLEL */
116   {
117      FILE *fp;
118      int i;
119
120      if(path == NULL || strlen(path)==0)
121        return NC_EINVAL;
122       
123      if (!(fp = fopen(path, "r")))
124         return errno;
125      i = fread(magic, MAGIC_NUMBER_LEN, 1, fp);
126      fclose(fp);
127      if(i != 1)
128         return errno;
129   }
130   
131   /* Ignore the first byte for HDF */
132   if(magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
133      *hdf = 5;
134   else if(magic[0] == '\016' && magic[1] == '\003'
135           && magic[2] == '\023' && magic[3] == '\001')
136      *hdf = 4;
137   else if(magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F') 
138   {
139      if(magic[3] == '\001') 
140         *cdf = 1; /* netcdf classic version 1 */
141      else if(magic[3] == '\002') 
142         *cdf = 2; /* netcdf classic version 2 */
143   }
144   
145   return NC_NOERR;
146}
147
148/**  \ingroup datasets
149Create a new netCDF file.
150
151This function creates a new netCDF dataset, returning a netCDF ID that
152can subsequently be used to refer to the netCDF dataset in other
153netCDF function calls. The new netCDF dataset opened for write access
154and placed in define mode, ready for you to add dimensions, variables,
155and attributes.
156
157\param path The file name of the new netCDF dataset.
158
159\param cmode The creation mode flag. The following flags are
160available: NC_NOCLOBBER (do not overwrite existing file), NC_SHARE
161(limit write caching - netcdf classic files onlt), NC_64BIT_OFFSET
162(create 64-bit offset file), NC_NETCDF4 (create netCDF-4/HDF5 file),
163NC_CLASSIC_MODEL (enforce netCDF classic mode on netCDF-4/HDF5
164files), NC_DISKLESS (store data only in memory), NC_MMAP (use MMAP
165for NC_DISKLESS), and NC_WRITE.
166See discussion below.
167
168\param ncidp Pointer to location where returned netCDF ID is to be
169stored.
170
171<h2>The cmode Flag</h2>
172
173The cmode flag is used to control the type of file created, and some
174aspects of how it may be used.
175
176Setting NC_NOCLOBBER means you do not want to clobber (overwrite) an
177existing dataset; an error (NC_EEXIST) is returned if the specified
178dataset already exists.
179
180The NC_SHARE flag is appropriate when one process may be writing the
181dataset and one or more other processes reading the dataset
182concurrently; it means that dataset accesses are not buffered and
183caching is limited. Since the buffering scheme is optimized for
184sequential access, programs that do not access data sequentially may
185see some performance improvement by setting the NC_SHARE flag. This
186flag is ignored for netCDF-4 files.
187
188Setting NC_64BIT_OFFSET causes netCDF to create a 64-bit offset format
189file, instead of a netCDF classic format file. The 64-bit offset
190format imposes far fewer restrictions on very large (i.e. over 2 GB)
191data files. See Large File Support.
192
193A zero value (defined for convenience as NC_CLOBBER) specifies the
194default behavior: overwrite any existing dataset with the same file
195name and buffer and cache accesses for efficiency. The dataset will be
196in netCDF classic format. See NetCDF Classic Format Limitations.
197
198Setting NC_NETCDF4 causes netCDF to create a HDF5/NetCDF-4 file.
199
200Setting NC_CLASSIC_MODEL causes netCDF to enforce the classic data
201model in this file. (This only has effect for netCDF-4/HDF5 files, as
202classic and 64-bit offset files always use the classic model.) When
203used with NC_NETCDF4, this flag ensures that the resulting
204netCDF-4/HDF5 file may never contain any new constructs from the
205enhanced data model. That is, it cannot contain groups, user defined
206types, multiple unlimited dimensions, or new atomic types. The
207advantage of this restriction is that such files are guaranteed to
208work with existing netCDF software.
209
210Setting NC_DISKLESS causes netCDF to create the file only in memory.
211This allows for the use of files that have no long term purpose. Note that
212with one exception, the in-memory file is destroyed upon calling
213nc_close. If, however, the flag combination (NC_DISKLESS|NC_WRITE)
214is used, then at close, the contents of the memory file will be
215made persistent in the file path that was specified in the nc_create
216call. If NC_DISKLESS is going to be used for creating a large classic file,
217it behooves one to use either nc__create or nc_create_mp and specify
218an appropriately large value of the initialsz parameter to avoid
219to many extensions to the in-memory space for the file.
220This flag applies to files in classic format and to file in extended
221format (netcdf-4).
222
223Normally, NC_DISKLESS allocates space in the heap for
224storing the in-memory file. If, however, the ./configure
225flags --enable-mmap is used, and the additional mode flag
226NC_MMAP is specified, then the file will be created using
227the operating system MMAP facility.
228This flag only applies to files in classic format. Extended
229format (netcdf-4) files will ignore the NC_MMAP flag.
230
231Using NC_MMAP for nc_create is
232only included for completeness vis-a-vis nc_open. The
233ability to use MMAP is of limited use for nc_create because
234nc_create is going to create the file in memory anyway.
235Closing a MMAP'd file will be slightly faster, but not significantly.
236
237Note that nc_create(path,cmode,ncidp) is equivalent to the invocation of
238nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp).
239
240\returns ::NC_NOERR No error.
241
242\returns ::NC_ENOMEM System out of memory.
243
244\returns ::NC_EHDFERR HDF5 error (netCDF-4 files only).
245
246\returns ::NC_EFILEMETA Error writing netCDF-4 file-level metadata in
247HDF5 file. (netCDF-4 files only).
248
249\returns ::NC_EDISKLESS if there was an error in creating the
250in-memory file.
251
252\note When creating a netCDF-4 file HDF5 error reporting is turned
253off, if it is on. This doesn't stop the HDF5 error stack from
254recording the errors, it simply stops their display to the user
255through stderr.
256
257<h1>Examples</h1>
258
259In this example we create a netCDF dataset named foo.nc; we want the
260dataset to be created in the current directory only if a dataset with
261that name does not already exist:
262
263@code
264     #include <netcdf.h>
265        ...
266     int status = NC_NOERR;
267     int ncid;
268        ...
269     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
270     if (status != NC_NOERR) handle_error(status);
271@endcode
272
273In this example we create a netCDF dataset named foo_large.nc. It will
274be in the 64-bit offset format.
275
276@code
277     #include <netcdf.h>
278        ...
279     int status = NC_NOERR;
280     int ncid;
281        ...
282     status = nc_create("foo_large.nc", NC_NOCLOBBER|NC_64BIT_OFFSET, &ncid);
283     if (status != NC_NOERR) handle_error(status);
284@endcode
285
286In this example we create a netCDF dataset named foo_HDF5.nc. It will
287be in the HDF5 format.
288
289@code
290     #include <netcdf.h>
291        ...
292     int status = NC_NOERR;
293     int ncid;
294        ...
295     status = nc_create("foo_HDF5.nc", NC_NOCLOBBER|NC_NETCDF4, &ncid);
296     if (status != NC_NOERR) handle_error(status);
297@endcode
298
299In this example we create a netCDF dataset named
300foo_HDF5_classic.nc. It will be in the HDF5 format, but will not allow
301the use of any netCDF-4 advanced features. That is, it will conform to
302the classic netCDF-3 data model.
303
304@code
305     #include <netcdf.h>
306        ...
307     int status = NC_NOERR;
308     int ncid;
309        ...
310     status = nc_create("foo_HDF5_classic.nc", NC_NOCLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid);
311     if (status != NC_NOERR) handle_error(status);
312@endcode
313
314In this example we create a in-memory netCDF classic dataset named
315diskless.nc whose content will be lost when nc_close() is called.
316
317@code
318     #include <netcdf.h>
319        ...
320     int status = NC_NOERR;
321     int ncid;
322        ...
323     status = nc_create("diskless.nc", NC_DISKLESS, &ncid);
324     if (status != NC_NOERR) handle_error(status);
325@endcode
326
327In this example we create a in-memory netCDF classic dataset named
328diskless.nc and specify that it should be made persistent
329in a file named diskless.nc when nc_close() is called.
330
331@code
332     #include <netcdf.h>
333        ...
334     int status = NC_NOERR;
335     int ncid;
336        ...
337     status = nc_create("diskless.nc", NC_DISKLESS|NC_WRITE, &ncid);
338     if (status != NC_NOERR) handle_error(status);
339@endcode
340
341A variant of nc_create(), nc__create() (note the double underscore) allows
342users to specify two tuning parameters for the file that it is
343creating.  */
344int
345nc_create(const char *path, int cmode, int *ncidp)
346{
347   return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
348}
349
350/*!
351Create a netCDF file with some extra parameters controlling classic
352file cacheing.
353
354Like nc_create(), this function creates a netCDF file.
355
356\param path The file name of the new netCDF dataset.
357
358\param cmode The creation mode flag, the same as in nc_create().
359
360\param initialsz On some systems, and with custom I/O layers, it may
361be advantageous to set the size of the output file at creation
362time. This parameter sets the initial size of the file at creation
363time. This only applies to classic and 64-bit offset files.
364The special value NC_SIZEHINT_DEFAULT (which is the value 0),
365lets the netcdf library choose a suitable initial size.
366
367\param chunksizehintp A pointer to the chunk size hint,
368which controls a space versus time tradeoff, memory
369allocated in the netcdf library versus number of system
370calls. Because of internal requirements, the value may not
371be set to exactly the value requested. The actual value
372chosen is returned by reference. Using a NULL pointer or
373having the pointer point to the value NC_SIZEHINT_DEFAULT
374causes the library to choose a default. How the system
375chooses the default depends on the system. On many systems,
376the "preferred I/O block size" is available from the stat()
377system call, struct stat member st_blksize. If this is
378available it is used. Lacking that, twice the system
379pagesize is used. Lacking a call to discover the system
380pagesize, we just set default bufrsize to 8192. The bufrsize
381is a property of a given open netcdf descriptor ncid, it is
382not a persistent property of the netcdf dataset. This only
383applies to classic and 64-bit offset files.
384
385\param ncidp Pointer to location where returned netCDF ID is to be
386stored.
387
388\note This function uses the same return codes as the nc_create()
389function.
390
391<h1>Examples</h1>
392
393In this example we create a netCDF dataset named foo_large.nc; we want
394the dataset to be created in the current directory only if a dataset
395with that name does not already exist. We also specify that bufrsize
396and initial size for the file.
397
398\code
399#include <netcdf.h>
400        ...
401     int status = NC_NOERR;
402     int ncid;
403     int intialsz = 2048;
404     int *bufrsize;
405        ...
406     *bufrsize = 1024;
407     status = nc__create("foo.nc", NC_NOCLOBBER, initialsz, bufrsize, &ncid);
408     if (status != NC_NOERR) handle_error(status);
409\endcode
410*/
411int
412nc__create(const char *path, int cmode, size_t initialsz,
413           size_t *chunksizehintp, int *ncidp)
414{
415   return NC_create(path, cmode, initialsz, 0, 
416                    chunksizehintp, 0, NULL, ncidp);
417
418}
419/**
420\internal
421
422\deprecated This function was used in the old days with the Cray at
423NCAR. The Cray is long gone, and this call is supported only for
424backward compatibility.
425
426 */
427int
428nc__create_mp(const char *path, int cmode, size_t initialsz, 
429              int basepe, size_t *chunksizehintp, int *ncidp)
430{
431   return NC_create(path, cmode, initialsz, basepe, 
432                    chunksizehintp, 0, NULL, ncidp);
433}
434
435/**
436Open an existing netCDF file.
437 
438This function opens an existing netCDF dataset for access. It
439determines the underlying file format automatically. Use the same call
440to open a netCDF classic, 64-bit offset, or netCDF-4 file.
441
442\param path File name for netCDF dataset to be opened. When DAP
443support is enabled, then the path may be an OPeNDAP URL rather than a
444file path.
445 
446\param mode The mode flag may include NC_WRITE (for read/write
447access) and NC_SHARE (see below) and NC_DISKLESS (see below).
448
449\param ncidp Pointer to location where returned netCDF ID is to be
450stored.
451
452<h2>Open Mode</h2>
453
454A zero value (or NC_NOWRITE) specifies the default behavior: open the
455dataset with read-only access, buffering and caching accesses for
456efficiency.
457
458Otherwise, the open mode is NC_WRITE, NC_SHARE, or
459NC_WRITE|NC_SHARE. Setting the NC_WRITE flag opens the dataset with
460read-write access. ("Writing" means any kind of change to the dataset,
461including appending or changing data, adding or renaming dimensions,
462variables, and attributes, or deleting attributes.)
463
464The NC_SHARE flag is only used for netCDF classic and 64-bit offset
465files. It is appropriate when one process may be writing the dataset
466and one or more other processes reading the dataset concurrently; it
467means that dataset accesses are not buffered and caching is
468limited. Since the buffering scheme is optimized for sequential
469access, programs that do not access data sequentially may see some
470performance improvement by setting the NC_SHARE flag.
471
472This procedure may also be invoked with the NC_DISKLESS flag
473set in the mode argument if the file to be opened is a
474classic format file.  For nc_open(), this flag applies only
475to files in classic format.  If the file is of type
476NC_NETCDF4, then the NC_DISKLESS flag will be ignored.
477
478If NC_DISKLESS is specified, then the whole file is read completely into
479memory. In effect this creates an in-memory cache of the file.
480If the mode flag also specifies NC_WRITE, then the in-memory cache
481will be re-written to the disk file when nc_close() is called.
482For some kinds of manipulations, having the in-memory cache can
483speed up file processing. But in simple cases, non-cached
484processing may actually be faster than using cached processing.
485You will need to experiment to determine if the in-memory caching
486is worthwhile for your application.
487
488Normally, NC_DISKLESS allocates space in the heap for
489storing the in-memory file. If, however, the ./configure
490flags --enable-mmap is used, and the additional mode flag
491NC_MMAP is specified, then the file will be opened using
492the operating system MMAP facility.
493This flag only applies to files in classic format. Extended
494format (netcdf-4) files will ignore the NC_MMAP flag.
495
496In most cases, using MMAP provides no advantage
497for just NC_DISKLESS. The one case where using MMAP is an
498advantage is when a file is to be opened and only a small portion
499of its data is to be read and/or written.
500In this scenario, MMAP will cause only the accessed data to be
501retrieved from disk. Without MMAP, NC_DISKLESS will read the whole
502file into memory on nc_open. Thus, MMAP will provide some performance
503improvement in this case.
504
505It is not necessary to pass any information about the format of the
506file being opened. The file type will be detected automatically by the
507netCDF library.
508 
509If a the path is a DAP URL, then the open mode is read-only.
510Setting NC_WRITE will be ignored.
511
512\note When opening a netCDF-4 file HDF5 error reporting is turned off,
513if it is on. This doesn't stop the HDF5 error stack from recording the
514errors, it simply stops their display to the user through stderr.
515
516nc_open()returns the value NC_NOERR if no errors occurred. Otherwise,
517the returned status indicates an error. Possible causes of errors
518include:
519
520Note that nc_open(path,cmode,ncidp) is equivalent to the invocation of
521nc__open(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp).
522
523\returns ::NC_NOERR No error.
524
525\returns ::NC_ENOMEM Out of memory.
526
527\returns ::NC_EHDFERR HDF5 error. (NetCDF-4 files only.)
528
529\returns ::NC_EDIMMETA Error in netCDF-4 dimension metadata. (NetCDF-4 files only.)
530
531<h1>Examples</h1>
532
533Here is an example using nc_open()to open an existing netCDF dataset
534named foo.nc for read-only, non-shared access:
535
536@code
537#include <netcdf.h>
538   ...
539int status = NC_NOERR;
540int ncid;
541   ...
542status = nc_open("foo.nc", 0, &ncid);
543if (status != NC_NOERR) handle_error(status);
544@endcode
545*/
546int
547nc_open(const char *path, int mode, int *ncidp)
548{
549   return NC_open(path, mode, 0, NULL, 0, NULL, ncidp);
550}
551
552/**
553Open a netCDF file with extra performance parameters for the classic
554library.
555
556\param path File name for netCDF dataset to be opened. When DAP
557support is enabled, then the path may be an OPeNDAP URL rather than a
558file path.
559 
560\param mode The mode flag may include NC_WRITE (for read/write
561access) and NC_SHARE as in nc_open().
562
563\param chunksizehintp A size hint for the classic library. Only
564applies to classic and 64-bit offset files. See below for more
565information.
566
567\param ncidp Pointer to location where returned netCDF ID is to be
568stored.
569
570<h1>The chunksizehintp Parameter</h1>
571
572The argument referenced by bufrsizehintp controls a space versus time
573tradeoff, memory allocated in the netcdf library versus number of
574system calls.
575
576Because of internal requirements, the value may not be set to exactly
577the value requested. The actual value chosen is returned by reference.
578
579Using a NULL pointer or having the pointer point to the value
580NC_SIZEHINT_DEFAULT causes the library to choose a default.
581How the system chooses the default depends on the system. On
582many systems, the "preferred I/O block size" is available from the
583stat() system call, struct stat member st_blksize. If this is
584available it is used. Lacking that, twice the system pagesize is used.
585
586Lacking a call to discover the system pagesize, we just set default
587bufrsize to 8192.
588
589The bufrsize is a property of a given open netcdf descriptor ncid, it
590is not a persistent property of the netcdf dataset.
591
592
593\returns ::NC_NOERR No error.
594
595\returns ::NC_ENOMEM Out of memory.
596
597\returns ::NC_EHDFERR HDF5 error. (NetCDF-4 files only.)
598
599\returns ::NC_EDIMMETA Error in netCDF-4 dimension metadata. (NetCDF-4
600files only.)
601
602*/
603int
604nc__open(const char *path, int mode,
605         size_t *chunksizehintp, int *ncidp)
606{
607   return NC_open(path, mode, 0, chunksizehintp, 0, 
608                  NULL, ncidp);
609}
610
611/**
612\internal
613
614\deprecated This function was used in the old days with the Cray at
615NCAR. The Cray is long gone, and this call is supported only for
616backward compatibility.
617
618 */
619int
620nc__open_mp(const char *path, int mode, int basepe, 
621            size_t *chunksizehintp, int *ncidp)
622{
623   return NC_open(path, mode, basepe, chunksizehintp,
624                  0, NULL, ncidp);
625}
626
627/**
628Get the file pathname (or the opendap URL) which was used to
629open/create the ncid's file.
630
631\param ncid NetCDF ID, from a previous call to nc_open() or
632nc_create().
633
634\param pathlen Pointer where length of path will be returned. Ignored
635if NULL.
636
637\param path Pointer where path name will be copied. Space must already
638be allocated. Ignored if NULL. 
639
640\returns ::NC_NOERR No error.
641
642\returns ::NC_EBADID Invalid ncid passed.
643*/
644int 
645nc_inq_path(int ncid, size_t *pathlen, char *path)
646{
647   NC* ncp;
648   int stat = NC_NOERR;
649   if ((stat = NC_check_id(ncid, &ncp)))
650      return stat;
651   if(ncp->path == NULL) {
652        if(pathlen) *pathlen = 0;
653        if(path) path[0] = '\0';
654   } else {
655       if (pathlen) *pathlen = strlen(ncp->path);
656       if (path) strcpy(path, ncp->path);
657   }
658   return stat;
659}
660
661/**
662Put open netcdf dataset into define mode
663
664The function nc_redef puts an open netCDF dataset into define mode, so
665dimensions, variables, and attributes can be added or renamed and
666attributes can be deleted.
667
668For netCDF-4 files (i.e. files created with NC_NETCDF4 in the cmode in
669their call to nc_create()), it is not necessary to call nc_redef()
670unless the file was also created with NC_STRICT_NC3. For straight-up
671netCDF-4 files, nc_redef() is called automatically, as needed.
672
673For all netCDF-4 files, the root ncid must be used. This is the ncid
674returned by nc_open() and nc_create(), and points to the root of the
675hierarchy tree for netCDF-4 files.
676
677\param ncid NetCDF ID, from a previous call to nc_open() or
678nc_create().
679
680\returns ::NC_NOERR No error.
681
682\returns ::NC_EBADID Bad ncid.
683
684\returns ::NC_EBADGRPID The ncid must refer to the root group of the
685file, that is, the group returned by nc_open() or nc_create().
686
687\returns ::NC_EINDEFINE Already in define mode.
688
689\returns ::NC_EPERM File is read-only.
690
691<h1>Example</h1>
692
693Here is an example using nc_redef to open an existing netCDF dataset
694named foo.nc and put it into define mode:
695
696\code
697#include <netcdf.h>
698   ...
699int status = NC_NOERR;
700int ncid;
701   ...
702status = nc_open("foo.nc", NC_WRITE, &ncid); 
703if (status != NC_NOERR) handle_error(status);
704   ...
705status = nc_redef(ncid);                     
706if (status != NC_NOERR) handle_error(status);
707\endcode
708 */
709int
710nc_redef(int ncid)
711{
712   NC* ncp;
713   int stat = NC_check_id(ncid, &ncp);
714   if(stat != NC_NOERR) return stat;
715   return ncp->dispatch->redef(ncid);
716}
717
718/**
719Leave define mode
720
721The function nc_enddef() takes an open netCDF dataset out of define
722mode. The changes made to the netCDF dataset while it was in define
723mode are checked and committed to disk if no problems
724occurred. Non-record variables may be initialized to a "fill value" as
725well with nc_set_fill(). The netCDF dataset is then placed in data
726mode, so variable data can be read or written.
727
728It's not necessary to call nc_enddef() for netCDF-4 files. With netCDF-4
729files, nc_enddef() is called when needed by the netcdf-4 library. User
730calls to nc_enddef() for netCDF-4 files still flush the metadata to
731disk.
732
733This call may involve copying data under some circumstances. For a
734more extensive discussion see File Structure and Performance.
735
736For netCDF-4/HDF5 format files there are some variable settings (the
737compression, endianness, fletcher32 error correction, and fill value)
738which must be set (if they are going to be set at all) between the
739nc_def_var() and the next nc_enddef(). Once the nc_enddef() is called,
740these settings can no longer be changed for a variable. 
741
742\param ncid NetCDF ID, from a previous call to nc_open() or
743nc_create().
744
745If you use a group id (in a netCDF-4/HDF5 file), the enddef
746will apply to the entire file. That means the enddef will not just end
747define mode in one group, but in the entire file.
748
749\returns ::NC_NOERR no error
750
751\returns ::NC_EBADID Invalid ncid passed.
752
753<h1>Example</h1>
754
755Here is an example using nc_enddef() to finish the definitions of a new
756netCDF dataset named foo.nc and put it into data mode:
757
758\code
759     #include <netcdf.h>
760        ...
761     int status = NC_NOERR;
762     int ncid;
763        ...
764     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
765     if (status != NC_NOERR) handle_error(status);
766     
767        ...  create dimensions, variables, attributes
768     
769     status = nc_enddef(ncid);
770     if (status != NC_NOERR) handle_error(status);
771\endcode
772 */
773int
774nc_enddef(int ncid)
775{
776   int status = NC_NOERR;
777   NC *ncp;
778   status = NC_check_id(ncid, &ncp); 
779   if(status != NC_NOERR) return status;
780   return ncp->dispatch->_enddef(ncid,0,1,0,1);
781}
782
783/**
784Leave define mode with performance tuning
785
786The function nc__enddef takes an open netCDF dataset out of define
787mode. The changes made to the netCDF dataset while it was in define
788mode are checked and committed to disk if no problems
789occurred. Non-record variables may be initialized to a "fill value" as
790well with nc_set_fill(). The netCDF dataset is then placed in data mode,
791so variable data can be read or written.
792
793This call may involve copying data under some circumstances. For a
794more extensive discussion see File Structure and Performance.
795
796\warning This function exposes internals of the netcdf version 1 file
797format. Users should use nc_enddef() in most circumstances. This
798function may not be available on future netcdf implementations.
799
800The classic netcdf file format has three sections, the "header"
801section, the data section for fixed size variables, and the data
802section for variables which have an unlimited dimension (record
803variables).
804
805The header begins at the beginning of the file. The index (offset) of
806the beginning of the other two sections is contained in the
807header. Typically, there is no space between the sections. This causes
808copying overhead to accrue if one wishes to change the size of the
809sections, as may happen when changing names of things, text attribute
810values, adding attributes or adding variables. Also, for buffered i/o,
811there may be advantages to aligning sections in certain ways.
812
813The minfree parameters allow one to control costs of future calls to
814nc_redef, nc_enddef() by requesting that minfree bytes be available at
815the end of the section.
816
817The align parameters allow one to set the alignment of the beginning
818of the corresponding sections. The beginning of the section is rounded
819up to an index which is a multiple of the align parameter. The flag
820value ALIGN_CHUNK tells the library to use the bufrsize (see above) as
821the align parameter. It has nothing to do with the chunking
822(multidimensional tiling) features of netCDF-4.
823
824The file format requires mod 4 alignment, so the align parameters are
825silently rounded up to multiples of 4. The usual call,
826
827\code
828     nc_enddef(ncid);
829\endcode
830
831is equivalent to
832
833\code
834     nc__enddef(ncid, 0, 4, 0, 4);
835\endcode
836
837The file format does not contain a "record size" value, this is
838calculated from the sizes of the record variables. This unfortunate
839fact prevents us from providing minfree and alignment control of the
840"records" in a netcdf file. If you add a variable which has an
841unlimited dimension, the third section will always be copied with the
842new variable added. 
843
844\param ncid NetCDF ID, from a previous call to nc_open() or
845nc_create().
846
847\param h_minfree Sets the pad at the end of the "header" section.
848
849\param v_align Controls the alignment of the beginning of the data
850section for fixed size variables.
851
852\param v_minfree Sets the pad at the end of the data section for fixed
853size variables.
854
855\param r_align Controls the alignment of the beginning of the data
856section for variables which have an unlimited dimension (record
857variables).
858
859\returns ::NC_NOERR No error.
860
861\returns ::NC_EBADID Invalid ncid passed.
862
863 */
864int
865nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, 
866           size_t r_align)
867{
868   NC* ncp;
869   int stat = NC_check_id(ncid, &ncp);
870   if(stat != NC_NOERR) return stat;
871   return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
872}
873
874/**
875Synchronize an open netcdf dataset to disk
876
877The function nc_sync() offers a way to synchronize the disk copy of a
878netCDF dataset with in-memory buffers. There are two reasons you might
879want to synchronize after writes:
880- To minimize data loss in case of abnormal termination, or
881- To make data available to other processes for reading immediately
882  after it is written. But note that a process that already had the
883  dataset open for reading would not see the number of records
884  increase when the writing process calls nc_sync(); to accomplish this,
885  the reading process must call nc_sync.
886
887This function is backward-compatible with previous versions of the
888netCDF library. The intent was to allow sharing of a netCDF dataset
889among multiple readers and one writer, by having the writer call
890nc_sync() after writing and the readers call nc_sync() before each
891read. For a writer, this flushes buffers to disk. For a reader, it
892makes sure that the next read will be from disk rather than from
893previously cached buffers, so that the reader will see changes made by
894the writing process (e.g., the number of records written) without
895having to close and reopen the dataset. If you are only accessing a
896small amount of data, it can be expensive in computer resources to
897always synchronize to disk after every write, since you are giving up
898the benefits of buffering.
899
900An easier way to accomplish sharing (and what is now recommended) is
901to have the writer and readers open the dataset with the NC_SHARE
902flag, and then it will not be necessary to call nc_sync() at
903all. However, the nc_sync() function still provides finer granularity
904than the NC_SHARE flag, if only a few netCDF accesses need to be
905synchronized among processes.
906
907It is important to note that changes to the ancillary data, such as
908attribute values, are not propagated automatically by use of the
909NC_SHARE flag. Use of the nc_sync() function is still required for this
910purpose.
911
912Sharing datasets when the writer enters define mode to change the data
913schema requires extra care. In previous releases, after the writer
914left define mode, the readers were left looking at an old copy of the
915dataset, since the changes were made to a new copy. The only way
916readers could see the changes was by closing and reopening the
917dataset. Now the changes are made in place, but readers have no
918knowledge that their internal tables are now inconsistent with the new
919dataset schema. If netCDF datasets are shared across redefinition,
920some mechanism external to the netCDF library must be provided that
921prevents access by readers during redefinition and causes the readers
922to call nc_sync before any subsequent access.
923
924When calling nc_sync(), the netCDF dataset must be in data mode. A
925netCDF dataset in define mode is synchronized to disk only when
926nc_enddef() is called. A process that is reading a netCDF dataset that
927another process is writing may call nc_sync to get updated with the
928changes made to the data by the writing process (e.g., the number of
929records written), without having to close and reopen the dataset.
930
931Data is automatically synchronized to disk when a netCDF dataset is
932closed, or whenever you leave define mode.
933
934\param ncid NetCDF ID, from a previous call to nc_open() or
935nc_create().
936
937\returns ::NC_NOERR No error.
938
939\returns ::NC_EBADID Invalid ncid passed.
940 */
941int
942nc_sync(int ncid)
943{
944   NC* ncp;
945   int stat = NC_check_id(ncid, &ncp);
946   if(stat != NC_NOERR) return stat;
947   return ncp->dispatch->sync(ncid);
948}
949
950/**
951\internal
952
953Users no longer need to call this function, since it is called
954automatically by nc_close() in case the dataset is in define mode and
955something goes wrong with committing the changes. The function
956nc_abort() just closes the netCDF dataset, if not in define mode. If
957the dataset is being created and is still in define mode, the dataset
958is deleted. If define mode was entered by a call to nc_redef(), the
959netCDF dataset is restored to its state before definition mode was
960entered and the dataset is closed.
961
962\param ncid NetCDF ID, from a previous call to nc_open() or
963nc_create().
964
965\returns ::NC_NOERR No error.
966
967<h1>Example</h1>
968
969Here is an example using nc_abort to back out of redefinitions of a
970dataset named foo.nc:
971
972\code
973     #include <netcdf.h>
974        ...
975     int ncid, status, latid;
976        ...
977     status = nc_open("foo.nc", NC_WRITE, &ncid);
978     if (status != NC_NOERR) handle_error(status);
979        ...
980     status = nc_redef(ncid);                 
981     if (status != NC_NOERR) handle_error(status);
982        ...
983     status = nc_def_dim(ncid, "lat", 18L, &latid);
984     if (status != NC_NOERR) {
985        handle_error(status);
986        status = nc_abort(ncid);               
987        if (status != NC_NOERR) handle_error(status);
988     }
989\endcode
990
991 */
992int
993nc_abort(int ncid)
994{
995   NC* ncp;
996   int stat = NC_check_id(ncid, &ncp);
997   if(stat != NC_NOERR) return stat;
998   if(ncp->path != NULL) free(ncp->path);
999   ncp->path = NULL;   
1000   return ncp->dispatch->abort(ncid);
1001}
1002
1003/**
1004Close an open netCDF dataset
1005
1006If the dataset in define mode, nc_enddef() will be called before
1007closing. (In this case, if nc_enddef() returns an error, nc_abort() will
1008automatically be called to restore the dataset to the consistent state
1009before define mode was last entered.) After an open netCDF dataset is
1010closed, its netCDF ID may be reassigned to the next netCDF dataset
1011that is opened or created.
1012
1013\param ncid NetCDF ID, from a previous call to nc_open() or nc_create().
1014
1015\returns ::NC_NOERR No error.
1016
1017\returns ::NC_EBADID Invalid id passed.
1018
1019\returns ::NC_EBADGRPID ncid did not contain the root group id of this
1020file. (NetCDF-4 only).
1021
1022<h1>Example</h1>
1023
1024Here is an example using nc_close to finish the definitions of a new
1025netCDF dataset named foo.nc and release its netCDF ID:
1026
1027\code
1028     #include <netcdf.h>
1029        ...
1030     int status = NC_NOERR;
1031     int ncid;
1032        ...
1033     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
1034     if (status != NC_NOERR) handle_error(status);
1035     
1036        ...   create dimensions, variables, attributes
1037     
1038     status = nc_close(ncid);       
1039     if (status != NC_NOERR) handle_error(status);
1040\endcode
1041
1042 */
1043int
1044nc_close(int ncid)
1045{
1046   NC* ncp;
1047   int stat = NC_check_id(ncid, &ncp);
1048   if(stat != NC_NOERR) return stat;
1049   return ncp->dispatch->close(ncid);
1050}
1051
1052/**
1053Change the fill-value mode to improve write performance.
1054
1055This function is intended for advanced usage, to optimize writes under
1056some circumstances described below. The function nc_set_fill() sets the
1057fill mode for a netCDF dataset open for writing and returns the
1058current fill mode in a return parameter. The fill mode can be
1059specified as either ::NC_FILL or ::NC_NOFILL. The default behavior
1060corresponding to ::NC_FILL is that data is pre-filled with fill values,
1061that is fill values are written when you create non-record variables
1062or when you write a value beyond data that has not yet been
1063written. This makes it possible to detect attempts to read data before
1064it was written. For more information on the use of fill values see
1065Fill Values. For information about how to define your own fill values
1066see Attribute Conventions.
1067
1068The behavior corresponding to ::NC_NOFILL overrides the default behavior
1069of prefilling data with fill values. This can be used to enhance
1070performance, because it avoids the duplicate writes that occur when
1071the netCDF library writes fill values that are later overwritten with
1072data.
1073
1074A value indicating which mode the netCDF dataset was already in is
1075returned. You can use this value to temporarily change the fill mode
1076of an open netCDF dataset and then restore it to the previous mode.
1077
1078After you turn on ::NC_NOFILL mode for an open netCDF dataset, you must
1079be certain to write valid data in all the positions that will later be
1080read. Note that nofill mode is only a transient property of a netCDF
1081dataset open for writing: if you close and reopen the dataset, it will
1082revert to the default behavior. You can also revert to the default
1083behavior by calling nc_set_fill() again to explicitly set the fill mode
1084to ::NC_FILL.
1085
1086There are three situations where it is advantageous to set nofill
1087mode:
1088- Creating and initializing a netCDF dataset. In this case, you should
1089  set nofill mode before calling nc_enddef() and then write completely
1090  all non-record variables and the initial records of all the record
1091  variables you want to initialize.
1092- Extending an existing record-oriented netCDF dataset. Set nofill
1093  mode after opening the dataset for writing, then append the
1094  additional records to the dataset completely, leaving no intervening
1095  unwritten records.
1096- Adding new variables that you are going to initialize to an existing
1097  netCDF dataset. Set nofill mode before calling nc_enddef() then write
1098  all the new variables completely.
1099
1100If the netCDF dataset has an unlimited dimension and the last record
1101was written while in nofill mode, then the dataset may be shorter than
1102if nofill mode was not set, but this will be completely transparent if
1103you access the data only through the netCDF interfaces.
1104
1105The use of this feature may not be available (or even needed) in
1106future releases. Programmers are cautioned against heavy reliance upon
1107this feature.
1108
1109\param ncid NetCDF ID, from a previous call to nc_open() or
1110nc_create().
1111
1112\param fillmode Desired fill mode for the dataset, either ::NC_NOFILL or
1113::NC_FILL.
1114
1115\param old_modep Pointer to location for returned current fill mode of
1116the dataset before this call, either ::NC_NOFILL or ::NC_FILL.
1117
1118\returns ::NC_NOERR No error.
1119
1120\returns ::NC_EBADID The specified netCDF ID does not refer to an open
1121netCDF dataset.
1122
1123\returns ::NC_EPERM The specified netCDF ID refers to a dataset open for
1124read-only access.
1125
1126\returns ::NC_EINVAL The fill mode argument is neither ::NC_NOFILL nor
1127::NC_FILL.
1128
1129<h1>Example</h1>
1130
1131Here is an example using nc_set_fill() to set nofill mode for subsequent
1132writes of a netCDF dataset named foo.nc:
1133
1134\code
1135     #include <netcdf.h>
1136        ...
1137     int ncid, status, old_fill_mode;
1138        ...
1139     status = nc_open("foo.nc", NC_WRITE, &ncid); 
1140     if (status != NC_NOERR) handle_error(status);
1141     
1142        ...     write data with default prefilling behavior
1143     
1144     status = nc_set_fill(ncid, ::NC_NOFILL, &old_fill_mode);
1145     if (status != NC_NOERR) handle_error(status);
1146     
1147        ...    write data with no prefilling
1148\endcode
1149 */
1150int
1151nc_set_fill(int ncid, int fillmode, int *old_modep)
1152{
1153   NC* ncp;
1154   int stat = NC_check_id(ncid, &ncp);
1155   if(stat != NC_NOERR) return stat;
1156   return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1157}
1158
1159/**
1160\internal
1161
1162\deprecated This function was used in the old days with the Cray at
1163NCAR. The Cray is long gone, and this call is supported only for
1164backward compatibility.
1165
1166\returns ::NC_NOERR No error.
1167
1168\returns ::NC_EBADID Invalid ncid passed.
1169 */
1170int
1171nc_inq_base_pe(int ncid, int *pe)
1172{
1173   NC* ncp;
1174   int stat = NC_check_id(ncid, &ncp);
1175   if(stat != NC_NOERR) return stat;
1176   return ncp->dispatch->inq_base_pe(ncid,pe);
1177}
1178
1179/**
1180\internal
1181
1182\deprecated This function was used in the old days with the Cray at
1183NCAR. The Cray is long gone, and this call is supported only for
1184backward compatibility.
1185
1186\returns ::NC_NOERR No error.
1187
1188\returns ::NC_EBADID Invalid ncid passed.
1189 */
1190int
1191nc_set_base_pe(int ncid, int pe)
1192{
1193   NC* ncp;
1194   int stat = NC_check_id(ncid, &ncp);
1195   if(stat != NC_NOERR) return stat;
1196   return ncp->dispatch->set_base_pe(ncid,pe);
1197}
1198
1199/**
1200Inquire about the binary format of a netCDF file.
1201
1202This function returns the (rarely needed) format version.
1203
1204\param ncid NetCDF ID, from a previous call to nc_open() or
1205nc_create().
1206
1207\param formatp Pointer to location for returned format version, one of
1208NC_FORMAT_CLASSIC, NC_FORMAT_64BIT, NC_FORMAT_NETCDF4,
1209NC_FORMAT_NETCDF4_CLASSIC.
1210
1211\returns ::NC_NOERR No error.
1212
1213\returns ::NC_EBADID Invalid ncid passed.
1214
1215 */
1216int
1217nc_inq_format(int ncid, int *formatp)
1218{
1219   NC* ncp;
1220   int stat = NC_check_id(ncid, &ncp);
1221   if(stat != NC_NOERR) return stat;
1222   return ncp->dispatch->inq_format(ncid,formatp);
1223}
1224
1225/**
1226Inquire about a file or group.
1227
1228\param ncid NetCDF or group ID, from a previous call to nc_open(),
1229nc_create(), nc_def_grp(), or associated inquiry functions such as
1230nc_inq_ncid().
1231
1232\param ndimsp Pointer to location for returned number of dimensions
1233defined for this netCDF dataset. Ignored if NULL.
1234
1235\param nvarsp Pointer to location for returned number of variables
1236defined for this netCDF dataset. Ignored if NULL.
1237
1238\param nattsp Pointer to location for returned number of global
1239attributes defined for this netCDF dataset. Ignored if NULL.
1240
1241\param unlimdimidp Pointer to location for returned ID of the
1242unlimited dimension, if there is one for this netCDF dataset. If no
1243unlimited length dimension has been defined, -1 is returned. Ignored
1244if NULL.  If there are multiple unlimited dimensions (possible only
1245for netCDF-4 files), only a pointer to the first is returned, for
1246backward compatibility.  If you want them all, use nc_inq_unlimids().
1247
1248\returns ::NC_NOERR No error.
1249
1250\returns ::NC_EBADID Invalid ncid passed.
1251
1252<h1>Example</h1>
1253
1254Here is an example using nc_inq to find out about a netCDF dataset
1255named foo.nc:
1256
1257\code
1258     #include <netcdf.h>
1259        ...
1260     int status, ncid, ndims, nvars, ngatts, unlimdimid;
1261        ...
1262     status = nc_open("foo.nc", NC_NOWRITE, &ncid);
1263     if (status != NC_NOERR) handle_error(status);
1264        ...
1265     status = nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid);
1266     if (status != NC_NOERR) handle_error(status);
1267\endcode
1268 */
1269int
1270nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1271{
1272   NC* ncp;
1273   int stat = NC_check_id(ncid, &ncp);
1274   if(stat != NC_NOERR) return stat;
1275   return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1276}
1277
1278int
1279nc_inq_nvars(int ncid, int *nvarsp)
1280{
1281   NC* ncp;
1282   int stat = NC_check_id(ncid, &ncp);
1283   if(stat != NC_NOERR) return stat;
1284   return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1285}
1286
1287/**
1288Inquire about a type.
1289
1290Given an ncid and a typeid, get the information about a type. This
1291function will work on any type, including atomic and any user defined
1292type, whether compound, opaque, enumeration, or variable length array.
1293
1294For even more information about a user defined type nc_inq_user_type().
1295
1296\param ncid The ncid for the group containing the type (ignored for
1297atomic types). 
1298
1299\param xtype The typeid for this type, as returned by nc_def_compound,
1300nc_def_opaque, nc_def_enum, nc_def_vlen, or nc_inq_var, or as found in
1301netcdf.h in the list of atomic types (NC_CHAR, NC_INT, etc.).
1302
1303\param name If non-NULL, the name of the user defined type will be
1304copied here. It will be NC_MAX_NAME bytes or less. For atomic types,
1305the type name from CDL will be given.
1306
1307\param size If non-NULL, the (in-memory) size of the type in bytes
1308will be copied here. VLEN type size is the size of nc_vlen_t. String
1309size is returned as the size of a character pointer. The size may be
1310used to malloc space for the data, no matter what the type.
1311
1312\returns ::NC_NOERR No error.
1313
1314\returns ::NC_EBADTYPE Bad typeid.
1315
1316\returns ::NC_ENOTNC4 Seeking a user-defined type in a netCDF-3 file.
1317
1318\returns ::NC_ESTRICTNC3 Seeking a user-defined type in a netCDF-4 file
1319for which classic model has been turned on.
1320
1321\returns ::NC_EBADGRPID Bad group ID in ncid.
1322
1323\returns ::NC_EBADID Type ID not found.
1324
1325\returns ::NC_EHDFERR An error was reported by the HDF5 layer.
1326
1327<h1>Example</h1>
1328
1329This example is from the test program tst_enums.c, and it uses all the
1330possible inquiry functions on an enum type.
1331
1332\code       
1333           if (nc_inq_user_type(ncid, typeids[0], name_in, &base_size_in, &base_nc_type_in,
1334                                &nfields_in, &class_in)) ERR;
1335           if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int) ||
1336               base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR;
1337           if (nc_inq_type(ncid, typeids[0], name_in, &base_size_in)) ERR;
1338           if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int)) ERR;
1339           if (nc_inq_enum(ncid, typeids[0], name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
1340           if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT || num_members != NUM_MEMBERS) ERR;
1341           for (i = 0; i < NUM_MEMBERS; i++)
1342           {
1343              if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
1344              if (strcmp(name_in, member_name[i]) || value_in != member_value[i]) ERR;
1345              if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR;
1346              if (strcmp(name_in, member_name[i])) ERR;
1347           }
1348     
1349           if (nc_close(ncid)) ERR;
1350\endcode
1351 */
1352int
1353nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1354{
1355   NC* ncp;
1356   /* For compatibility, we need to allow inq about
1357      atomic types, even if ncid is ill-defined */
1358   if(xtype <= ATOMICTYPEMAX) {
1359      if(xtype <= NC_NAT) return NC_EBADTYPE;
1360      if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1361      if(size) *size = NC_atomictypelen(xtype);
1362      return NC_NOERR;
1363   } else {
1364      int stat = NC_check_id(ncid, &ncp);
1365      if(stat != NC_NOERR) return NC_EBADTYPE; /* compatibility */
1366      return ncp->dispatch->inq_type(ncid,xtype,name,size);
1367   }
1368}
1369/**@}*/
1370
1371/**
1372\internal
1373\ingroup dispatch
1374
1375Create a file, calling the appropriate dispatch create call.
1376
1377For create, we have the following pieces of information to use to
1378determine the dispatch table:
1379- table specified by override
1380- path
1381- cmode
1382
1383\param path The file name of the new netCDF dataset.
1384
1385\param cmode The creation mode flag, the same as in nc_create().
1386
1387\param initialsz This parameter sets the initial size of the file at creation
1388time. This only applies to classic and 64-bit offset files.
1389
1390\param basepe Deprecated parameter from the Cray days.
1391
1392\param chunksizehintp A pointer to the chunk size hint. This only
1393applies to classic and 64-bit offset files.
1394
1395\param useparallel Non-zero if parallel I/O is to be used on this
1396file.
1397
1398\param mpi_info Pointer to MPI comm and info.
1399
1400\param ncidp Pointer to location where returned netCDF ID is to be
1401stored.
1402
1403\returns ::NC_NOERR No error.
1404*/
1405int
1406NC_create(const char *path, int cmode, size_t initialsz, 
1407          int basepe, size_t *chunksizehintp, int useparallel, 
1408          void* mpi_info, int *ncidp)
1409{
1410   int stat = NC_NOERR;
1411   NC* ncp = NULL;
1412   NC_Dispatch* dispatcher = NULL;
1413   /* Need three pieces of information for now */
1414   int model = 0; /* one of the NC_DISPATCH_XXX values */
1415   int isurl = 0;   /* dap or cdmremote or neither */
1416   int xcmode = 0; /* for implied cmode flags */
1417   extern int default_create_format;
1418
1419   /* Initialize the dispatch table. The function pointers in the
1420    * dispatch table will depend on how netCDF was built
1421    * (with/without netCDF-4, DAP, CDMREMOTE). */
1422   if(!nc_initialized)
1423   {
1424      if ((stat = NC_initialize()))
1425         return stat; 
1426      /* Do local initialization */
1427      nc_local_initialize();
1428      nc_initialized = 1;
1429   }
1430
1431   if((isurl = NC_testurl(path)))
1432        model = NC_urlmodel(path);
1433
1434   /* Look to the incoming cmode for hints */
1435   if(model == 0) {
1436      if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF)
1437        model = NC_DISPATCH_NC4;
1438   }
1439
1440   if(model == 0) {
1441      /* Check default format */
1442      int format = default_create_format;
1443      switch (format) {
1444#ifdef USE_NETCDF4
1445         case NC_FORMAT_NETCDF4:
1446            xcmode |= NC_NETCDF4;
1447            model = NC_DISPATCH_NC4;
1448            break;
1449         case NC_FORMAT_NETCDF4_CLASSIC:
1450            xcmode |= NC_CLASSIC_MODEL;
1451            model = NC_DISPATCH_NC4;
1452            break;
1453#endif
1454         case NC_FORMAT_64BIT:
1455            xcmode |= NC_64BIT_OFFSET;
1456            /* fall thru */
1457         case NC_FORMAT_CLASSIC:
1458         default:
1459            model = NC_DISPATCH_NC3;
1460            break;
1461      }
1462   }
1463   
1464   /* Add inferred flags */
1465   cmode |= xcmode;
1466
1467#ifdef USE_NETCDF4
1468   if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1469      return  NC_EINVAL;
1470#endif
1471
1472   if (!(dispatcher = NC_get_dispatch_override()))
1473   {
1474
1475      /* Figure out what dispatcher to use */
1476#ifdef USE_NETCDF4
1477#ifdef USE_CDMREMOTE
1478      if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1479         dispatcher = NCCR_dispatch_table;
1480      else
1481#endif
1482      if(model == (NC_DISPATCH_NC4))
1483        dispatcher = NC4_dispatch_table;
1484      else
1485#endif /*USE_NETCDF4*/
1486#ifdef USE_DAP
1487      if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1488        dispatcher = NCD3_dispatch_table;
1489      else
1490#endif
1491      if(model == (NC_DISPATCH_NC3))
1492        dispatcher = NC3_dispatch_table;
1493      else
1494         return NC_ENOTNC;
1495   }
1496
1497   if ((stat = dispatcher->create(path, cmode, initialsz, basepe, chunksizehintp,
1498                                   useparallel, mpi_info, dispatcher, &ncp)))
1499      return stat;
1500
1501   ncp->dispatch = dispatcher;
1502   if(ncidp) 
1503      *ncidp = ncp->ext_ncid;
1504   if (!(ncp->path = nulldup(path)))
1505      return NC_ENOMEM;
1506   return NC_NOERR;
1507}
1508
1509/**
1510\internal
1511\ingroup dispatch
1512
1513Open a netCDF file (or remote dataset) calling the appropriate
1514dispatch function.
1515
1516For open, we have the following pieces of information to use to determine the dispatch table.
1517- table specified by override
1518- path
1519- cmode
1520- the contents of the file (if it exists), basically checking its magic number.
1521
1522\returns ::NC_NOERR No error.
1523*/
1524int
1525NC_open(const char *path, int cmode,
1526        int basepe, size_t *chunksizehintp,
1527        int useparallel, void* mpi_info,
1528        int *ncidp)
1529{
1530   int stat = NC_NOERR;
1531   NC* ncp = NULL;
1532   NC_Dispatch* dispatcher = NULL;
1533   /* Need two pieces of information for now */
1534   int model = 0;
1535   int isurl = 0; 
1536   int cdfversion = 0;
1537   int hdfversion = 0;
1538   extern int default_create_format;
1539
1540   if(!nc_initialized) {
1541      stat = NC_initialize();
1542      if(stat) return stat;
1543      /* Do local initialization */
1544      nc_local_initialize();
1545      nc_initialized = 1;
1546   }
1547
1548   isurl = NC_testurl(path);
1549   if(isurl)
1550      model = NC_urlmodel(path);
1551
1552   if(!isurl) {
1553      /* Look at the file if it exists */
1554      stat = NC_check_file_type(path,useparallel,mpi_info,&cdfversion,&hdfversion);
1555      if(stat == NC_NOERR) {
1556         if(hdfversion != 0) {
1557            model = NC_DISPATCH_NC4;
1558         } else if(cdfversion != 0) {
1559            model = NC_DISPATCH_NC3;
1560         }
1561      } 
1562      /* else ignore the file */
1563   }
1564
1565   /* Look to the incoming cmode for hints */
1566   if(model == 0) {
1567      if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF) model |= NC_DISPATCH_NC4;
1568   }
1569
1570   if(model == 0) model = NC_DISPATCH_NC3; /* final default */
1571
1572   /* Force flag consistentcy */
1573   if(model & NC_DISPATCH_NC4)
1574      cmode |= NC_NETCDF4;
1575   else if(model & NC_DISPATCH_NC3) {
1576      cmode &= ~NC_NETCDF4; /* must be netcdf-3 */
1577      if(cdfversion == 2) cmode |= NC_64BIT_OFFSET;
1578   }
1579
1580   if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1581      return  NC_EINVAL;
1582
1583   /* override overrides any other table choice */
1584   dispatcher = NC_get_dispatch_override();
1585   if(dispatcher != NULL) goto havetable;
1586
1587   /* Figure out what dispatcher to use */
1588#if  defined(USE_CDMREMOTE)
1589   if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1590        dispatcher = NCCR_dispatch_table;
1591   else
1592#endif
1593#if defined(USE_DAP)
1594   if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1595        dispatcher = NCD3_dispatch_table;
1596   else
1597#endif
1598#if defined(USE_NETCDF4)
1599   if(model == (NC_DISPATCH_NC4))
1600        dispatcher = NC4_dispatch_table;
1601   else
1602#endif
1603   if(model == (NC_DISPATCH_NC3))
1604        dispatcher = NC3_dispatch_table;
1605   else
1606      return  NC_ENOTNC;
1607
1608  havetable:
1609  stat = dispatcher->open(path, cmode, basepe, chunksizehintp,
1610                           useparallel, mpi_info, dispatcher, &ncp);
1611   if(stat == NC_NOERR) {
1612      ncp->dispatch = dispatcher;
1613      if(ncidp) *ncidp = ncp->ext_ncid;
1614      ncp->path = nulldup(path);
1615      if(path == NULL) stat = NC_ENOMEM;       
1616   }
1617   return stat;
1618}
1619
1620/*Provide an internal function for generating pseudo file descriptors
1621  for systems that are not file based (e.g. dap, memio).
1622*/
1623
1624/* Static counter for pseudo file descriptors (incremented) */
1625static int pseudofd = 0;
1626
1627/* Create a pseudo file descriptor that does not
1628   overlap real file descriptors
1629*/
1630int
1631nc__pseudofd(void)
1632{
1633    if(pseudofd == 0)  {
1634        int maxfd = 32767; /* default */
1635#ifdef HAVE_GETRLIMIT
1636        struct rlimit rl;
1637        if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
1638            if(rl.rlim_max != RLIM_INFINITY)
1639                maxfd = rl.rlim_max;
1640            if(rl.rlim_cur != RLIM_INFINITY)
1641                maxfd = rl.rlim_cur;
1642        }
1643        pseudofd = maxfd+1;
1644#endif
1645    }
1646
1647    return pseudofd++;
1648}
1649
1650
Note: See TracBrowser for help on using the repository browser.