2010-06-22 21:25:14 +08:00
|
|
|
/*
|
2010-08-18 23:11:17 +08:00
|
|
|
Copyright 2010 University Corporation for Atmospheric
|
|
|
|
Research/Unidata. See COPYRIGHT file for more info.
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
This file defines the file create and open functions.
|
2010-06-22 21:25:14 +08:00
|
|
|
*/
|
|
|
|
|
2010-08-05 10:44:59 +08:00
|
|
|
#include "ncdispatch.h"
|
2010-06-22 21:25:14 +08:00
|
|
|
|
|
|
|
static int nc_initialized = 0;
|
|
|
|
|
|
|
|
static int
|
2010-11-30 06:23:16 +08:00
|
|
|
NC_check_file_type(const char *path, int use_parallel, void *mpi_info,
|
|
|
|
int *cdf, int *hdf)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
char magic[MAGIC_NUMBER_LEN];
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
*hdf = 0; *cdf = 0;
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
/* Get the 4-byte magic from the beginning of the file. Don't use posix
|
2010-06-22 21:25:14 +08:00
|
|
|
* for parallel, use the MPI functions instead. */
|
|
|
|
#ifdef USE_PARALLEL_MPIO
|
2010-11-30 06:23:16 +08:00
|
|
|
if (use_parallel)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
MPI_File fh;
|
|
|
|
MPI_Status status;
|
|
|
|
int retval;
|
|
|
|
MPI_Comm comm = 0;
|
|
|
|
MPI_Info info = 0;
|
2010-11-30 06:23:16 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
if(mpi_info != NULL) {
|
|
|
|
comm = ((NC_MPI_INFO*)mpi_info)->comm;
|
|
|
|
info = ((NC_MPI_INFO*)mpi_info)->info;
|
|
|
|
}
|
2010-11-30 06:23:16 +08:00
|
|
|
if((retval = MPI_File_open(comm, (char *)path, MPI_MODE_RDONLY,info,
|
|
|
|
&fh)) != MPI_SUCCESS)
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_EPARINIT;
|
2010-11-30 06:23:16 +08:00
|
|
|
if((retval = MPI_File_read(fh, magic, MAGIC_NUMBER_LEN, MPI_CHAR,
|
|
|
|
&status)) != MPI_SUCCESS)
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_EPARINIT;
|
|
|
|
if((retval = MPI_File_close(&fh)) != MPI_SUCCESS)
|
|
|
|
return NC_EPARINIT;
|
|
|
|
} else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif /* USE_PARALLEL */
|
2010-08-18 23:11:17 +08:00
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
int i;
|
2010-11-30 06:23:16 +08:00
|
|
|
|
|
|
|
if (!(fp = fopen(path, "r")))
|
2010-08-18 23:11:17 +08:00
|
|
|
return errno;
|
|
|
|
i = fread(magic, MAGIC_NUMBER_LEN, 1, fp);
|
2010-11-30 06:23:16 +08:00
|
|
|
fclose(fp);
|
2010-08-18 23:11:17 +08:00
|
|
|
if(i != 1)
|
|
|
|
return errno;
|
|
|
|
}
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
/* Ignore the first byte for HDF */
|
|
|
|
if(magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
|
|
|
|
*hdf = 5;
|
|
|
|
else if(magic[0] == '\016' && magic[1] == '\003'
|
|
|
|
&& magic[2] == '\023' && magic[3] == '\001')
|
|
|
|
*hdf = 4;
|
2010-11-30 06:23:16 +08:00
|
|
|
else if(magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F')
|
|
|
|
{
|
|
|
|
if(magic[3] == '\001')
|
|
|
|
*cdf = 1;
|
|
|
|
else if(magic[3] == '\002')
|
|
|
|
*cdf = 2;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_NOERR;
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
nc_create(const char *path, int cmode, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_create(path, cmode, 0, 0, NULL, 0, NULL, ncidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
nc__create(const char *path, int cmode, size_t initialsz,
|
|
|
|
size_t *chunksizehintp, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_create(path, cmode, initialsz, 0,
|
|
|
|
chunksizehintp, 0, NULL, ncidp);
|
|
|
|
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
nc__create_mp(const char *path, int cmode, size_t initialsz,
|
|
|
|
int basepe, size_t *chunksizehintp, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_create(path, cmode, initialsz, basepe,
|
|
|
|
chunksizehintp, 0, NULL, ncidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-08-18 23:11:17 +08:00
|
|
|
For create, we have the following pieces of information
|
|
|
|
to use to determine the dispatch table.
|
|
|
|
1. table specified by override
|
|
|
|
2. path
|
|
|
|
3. cmode
|
2010-06-22 21:25:14 +08:00
|
|
|
*/
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
NC_create(const char *path, int cmode, size_t initialsz,
|
|
|
|
int basepe, size_t *chunksizehintp, int useparallel,
|
|
|
|
void* mpi_info, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
int stat = NC_NOERR;
|
|
|
|
NC* ncp = NULL;
|
|
|
|
NC_Dispatch* dispatcher = NULL;
|
|
|
|
/* Need three pieces of information for now */
|
2010-12-16 05:45:05 +08:00
|
|
|
int model = 0; /* one of the NC_DISPATCH_XXX values */
|
|
|
|
int isurl = 0; /* dap or cdmremote or neither */
|
2010-08-18 23:11:17 +08:00
|
|
|
int xcmode = 0; /* for implied cmode flags */
|
|
|
|
extern int default_create_format;
|
|
|
|
|
|
|
|
/* Initialize the dispatch table. The function pointers in the
|
|
|
|
* dispatch table will depend on how netCDF was built
|
2010-12-16 05:45:05 +08:00
|
|
|
* (with/without netCDF-4, DAP, CDMREMOTE). */
|
2010-08-18 23:11:17 +08:00
|
|
|
if(!nc_initialized)
|
|
|
|
{
|
|
|
|
if ((stat = NC_initialize()))
|
|
|
|
return stat;
|
|
|
|
nc_initialized = 1;
|
|
|
|
}
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
if((isurl = NC_testurl(path)))
|
|
|
|
model = NC_urlmodel(path);
|
2010-08-18 23:11:17 +08:00
|
|
|
|
|
|
|
/* Look to the incoming cmode for hints */
|
|
|
|
if(model == 0) {
|
2011-02-24 07:39:25 +08:00
|
|
|
if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF)
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC4;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if(model == 0) {
|
|
|
|
/* Check default format */
|
|
|
|
int format = default_create_format;
|
|
|
|
switch (format) {
|
2010-07-23 05:50:51 +08:00
|
|
|
#ifdef USE_NETCDF4
|
2010-08-18 23:11:17 +08:00
|
|
|
case NC_FORMAT_NETCDF4:
|
2010-07-23 05:50:51 +08:00
|
|
|
xcmode |= NC_NETCDF4;
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC4;
|
2010-07-23 05:50:51 +08:00
|
|
|
break;
|
2010-08-18 23:11:17 +08:00
|
|
|
case NC_FORMAT_NETCDF4_CLASSIC:
|
2010-07-23 05:50:51 +08:00
|
|
|
xcmode |= NC_CLASSIC_MODEL;
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC4;
|
2010-07-23 05:50:51 +08:00
|
|
|
break;
|
|
|
|
#endif
|
2010-08-18 23:11:17 +08:00
|
|
|
case NC_FORMAT_64BIT:
|
2010-07-23 05:50:51 +08:00
|
|
|
xcmode |= NC_64BIT_OFFSET;
|
|
|
|
/* fall thru */
|
2010-08-18 23:11:17 +08:00
|
|
|
case NC_FORMAT_CLASSIC:
|
|
|
|
default:
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC3;
|
2010-07-23 05:50:51 +08:00
|
|
|
break;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
2010-12-16 05:45:05 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
/* Add inferred flags */
|
|
|
|
cmode |= xcmode;
|
2010-07-23 05:50:51 +08:00
|
|
|
|
2010-06-22 21:25:14 +08:00
|
|
|
#ifdef USE_NETCDF4
|
2010-08-18 23:11:17 +08:00
|
|
|
if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
|
|
|
|
return NC_EINVAL;
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
dispatcher = NC_get_dispatch_override();
|
|
|
|
if(dispatcher != NULL) goto havetable;
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
/* Figure out what dispatcher to use */
|
2010-06-22 21:25:14 +08:00
|
|
|
#ifdef USE_NETCDF4
|
2010-12-16 05:45:05 +08:00
|
|
|
#ifdef USE_CDMREMOTE
|
|
|
|
if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
|
|
|
|
dispatcher = NCCR_dispatch_table;
|
|
|
|
else
|
|
|
|
#endif
|
2010-06-22 21:25:14 +08:00
|
|
|
#ifdef USE_DAP
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCD))
|
|
|
|
dispatcher = NCD4_dispatch_table;
|
|
|
|
else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model == (NC_DISPATCH_NC4))
|
|
|
|
dispatcher = NC4_dispatch_table;
|
|
|
|
else
|
|
|
|
#endif /*USE_NETCDF4*/
|
|
|
|
#ifdef USE_DAP
|
|
|
|
if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
|
|
|
|
dispatcher = NCD3_dispatch_table;
|
|
|
|
else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model == (NC_DISPATCH_NC3))
|
|
|
|
dispatcher = NC3_dispatch_table;
|
|
|
|
else
|
|
|
|
return NC_ENOTNC;
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
havetable:
|
|
|
|
stat = dispatcher->create(path,cmode,initialsz,basepe,chunksizehintp,
|
|
|
|
useparallel,mpi_info,dispatcher,&ncp);
|
|
|
|
if(stat == NC_NOERR) {
|
|
|
|
ncp->dispatch = dispatcher;
|
|
|
|
if(ncidp) *ncidp = ncp->ext_ncid;
|
2010-11-10 06:53:03 +08:00
|
|
|
ncp->path = strdup(path);
|
|
|
|
if(path == NULL) stat = NC_ENOMEM;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
return stat;
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_open(const char *path, int mode, int *ncidp)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_open(path, mode, 0, NULL, 0, NULL, ncidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
nc__open(const char *path, int cmode,
|
|
|
|
size_t *chunksizehintp, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_open(path, cmode, 0, chunksizehintp, 0,
|
|
|
|
NULL, ncidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-08-18 23:11:17 +08:00
|
|
|
nc__open_mp(const char *path, int cmode, int basepe,
|
|
|
|
size_t *chunksizehintp, int *ncidp)
|
2010-06-22 21:25:14 +08:00
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
return NC_open(path, cmode, basepe, chunksizehintp,
|
|
|
|
0, NULL, ncidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-08-18 23:11:17 +08:00
|
|
|
For create, we have the following pieces of information
|
|
|
|
to use to determine the dispatch table.
|
|
|
|
1. table specified by override
|
|
|
|
2. path
|
|
|
|
3. cmode
|
|
|
|
4. the contents of the file (if it exists);
|
|
|
|
basically checking its magic number
|
2010-06-22 21:25:14 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
NC_open(const char *path, int cmode,
|
|
|
|
int basepe, size_t *chunksizehintp,
|
|
|
|
int useparallel, void* mpi_info,
|
|
|
|
int *ncidp)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
int stat = NC_NOERR;
|
|
|
|
NC* ncp = NULL;
|
|
|
|
NC_Dispatch* dispatcher = NULL;
|
|
|
|
/* Need two pieces of information for now */
|
2010-12-16 05:45:05 +08:00
|
|
|
int model = 0;
|
|
|
|
int isurl = 0;
|
2010-08-18 23:11:17 +08:00
|
|
|
int cdfversion = 0;
|
|
|
|
int hdfversion = 0;
|
|
|
|
extern int default_create_format;
|
|
|
|
|
|
|
|
if(!nc_initialized)
|
|
|
|
{stat = NC_initialize(); if(stat) return stat; nc_initialized = 1;}
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
if((isurl = NC_testurl(path)))
|
2010-08-18 23:11:17 +08:00
|
|
|
model = NC_urlmodel(path);
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
if(isurl == 0) {
|
2010-08-18 23:11:17 +08:00
|
|
|
/* Look at the file if it exists */
|
|
|
|
stat = NC_check_file_type(path,useparallel,mpi_info,&cdfversion,&hdfversion);
|
|
|
|
if(stat == NC_NOERR) {
|
|
|
|
if(hdfversion != 0) {
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC4;
|
2010-08-18 23:11:17 +08:00
|
|
|
} else if(cdfversion != 0) {
|
2010-12-16 05:45:05 +08:00
|
|
|
model = NC_DISPATCH_NC3;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* else ignore the file */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look to the incoming cmode for hints */
|
|
|
|
if(model == 0) {
|
2011-02-24 07:39:25 +08:00
|
|
|
if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF) model = NC_DISPATCH_NC4;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model == 0) model = NC_DISPATCH_NC3; /* final default */
|
2010-08-18 23:11:17 +08:00
|
|
|
|
|
|
|
/* Force flag consistentcy */
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model & NC_DISPATCH_NC4)
|
2010-08-18 23:11:17 +08:00
|
|
|
cmode |= NC_NETCDF4;
|
2010-12-16 05:45:05 +08:00
|
|
|
else if(model & NC_DISPATCH_NC3) {
|
2011-02-24 07:39:25 +08:00
|
|
|
cmode &= ~NC_NETCDF4; /* must be netcdf-3 */
|
2010-08-18 23:11:17 +08:00
|
|
|
if(cdfversion == 2) cmode |= NC_64BIT_OFFSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
|
|
|
|
return NC_EINVAL;
|
|
|
|
|
|
|
|
/* override overrides any other table choice */
|
|
|
|
dispatcher = NC_get_dispatch_override();
|
|
|
|
if(dispatcher != NULL) goto havetable;
|
|
|
|
|
|
|
|
/* Figure out what dispatcher to use */
|
2010-12-16 05:45:05 +08:00
|
|
|
#if defined(USE_CDMREMOTE)
|
|
|
|
if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
|
|
|
|
dispatcher = NCCR_dispatch_table;
|
|
|
|
else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
2010-12-16 05:45:05 +08:00
|
|
|
#if defined(USE_NETCDF4) && defined(USE_DAP)
|
|
|
|
if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCD))
|
|
|
|
dispatcher = NCD4_dispatch_table;
|
|
|
|
else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
2010-12-16 05:45:05 +08:00
|
|
|
#if defined(USE_DAP)
|
|
|
|
if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
|
|
|
|
dispatcher = NCD3_dispatch_table;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
#if defined(USE_NETCDF4)
|
|
|
|
if(model == (NC_DISPATCH_NC4))
|
|
|
|
dispatcher = NC4_dispatch_table;
|
|
|
|
else
|
2010-06-22 21:25:14 +08:00
|
|
|
#endif
|
2010-12-16 05:45:05 +08:00
|
|
|
if(model == (NC_DISPATCH_NC3))
|
|
|
|
dispatcher = NC3_dispatch_table;
|
|
|
|
else
|
|
|
|
return NC_ENOTNC;
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-08-18 23:11:17 +08:00
|
|
|
havetable:
|
2011-04-17 04:56:36 +08:00
|
|
|
stat = dispatcher->open(path, cmode, basepe, chunksizehintp,
|
2010-08-18 23:11:17 +08:00
|
|
|
useparallel, mpi_info, dispatcher, &ncp);
|
|
|
|
if(stat == NC_NOERR) {
|
|
|
|
ncp->dispatch = dispatcher;
|
|
|
|
if(ncidp) *ncidp = ncp->ext_ncid;
|
2010-11-10 06:53:03 +08:00
|
|
|
ncp->path = strdup(path);
|
|
|
|
if(path == NULL) stat = NC_ENOMEM;
|
2010-08-18 23:11:17 +08:00
|
|
|
}
|
|
|
|
return stat;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function returns the file pathname (or the opendap URL) which
|
|
|
|
* was used to open/create the ncid's file. */
|
|
|
|
int
|
|
|
|
nc_inq_path(int ncid, size_t *pathlen, char *path)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
2010-11-10 06:53:03 +08:00
|
|
|
int stat = NC_NOERR;
|
2010-08-18 23:11:17 +08:00
|
|
|
if ((stat = NC_check_id(ncid, &ncp)))
|
|
|
|
return stat;
|
2010-11-10 06:53:03 +08:00
|
|
|
if(ncp->path == NULL) {
|
|
|
|
if(pathlen) *pathlen = 0;
|
|
|
|
if(path) path[0] = '\0';
|
|
|
|
} else {
|
|
|
|
if (pathlen) *pathlen = strlen(ncp->path);
|
|
|
|
if (path) strcpy(path, ncp->path);
|
|
|
|
}
|
|
|
|
return stat;
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_redef(int ncid)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->redef(ncid);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, size_t r_align)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_enddef(int ncid)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
int status;
|
|
|
|
NC *ncp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
|
|
if(status != NC_NOERR) return status;
|
|
|
|
return ncp->dispatch->_enddef(ncid,0,1,0,1);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_sync(int ncid)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->sync(ncid);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
2010-11-10 06:53:03 +08:00
|
|
|
static void
|
|
|
|
NC_reclaim(NC* ncp)
|
|
|
|
{
|
|
|
|
/* reclaim the path */
|
|
|
|
if(ncp->path != NULL) free(ncp->path);
|
|
|
|
ncp->path = NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-22 21:25:14 +08:00
|
|
|
int
|
|
|
|
nc_abort(int ncid)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2010-11-10 06:53:03 +08:00
|
|
|
NC_reclaim(ncp);
|
2010-08-18 23:11:17 +08:00
|
|
|
return ncp->dispatch->abort(ncid);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_close(int ncid)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->close(ncid);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_set_fill(int ncid, int fillmode, int *old_modep)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_inq_base_pe(int ncid, int *pe)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->inq_base_pe(ncid,pe);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_set_base_pe(int ncid, int pe)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->set_base_pe(ncid,pe);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_inq_format(int ncid, int *formatp)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->inq_format(ncid,formatp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
|
|
|
|
{
|
2010-08-18 23:11:17 +08:00
|
|
|
NC* ncp;
|
|
|
|
/* For compatibility, we need to allow inq about
|
|
|
|
atomic types, even if ncid is ill-defined */
|
|
|
|
if(xtype <= ATOMICTYPEMAX) {
|
|
|
|
if(xtype <= NC_NAT) return NC_EBADTYPE;
|
|
|
|
if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
|
|
|
|
if(size) *size = NC_atomictypelen(xtype);
|
|
|
|
return NC_NOERR;
|
|
|
|
} else {
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return NC_EBADTYPE; /* compatibility */
|
|
|
|
return ncp->dispatch->inq_type(ncid,xtype,name,size);
|
|
|
|
}
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|