15 #ifdef HAVE_SYS_RESOURCE_H 16 #include <sys/resource.h> 18 #ifdef HAVE_SYS_TYPES_H 19 #include <sys/types.h> 21 #ifdef HAVE_SYS_STAT_H 24 #include "ncdispatch.h" 26 #include "ncwinpath.h" 49 static int openmagic(
struct MagicFile* file);
50 static int readmagic(
struct MagicFile* file,
long pos,
char* magic);
53 static void printmagic(
const char* tag,
char* magic,
struct MagicFile*);
60 static char HDF5_SIGNATURE[MAGIC_NUMBER_LEN] =
"\211HDF\r\n\032\n";
121 if(memcmp(magic,HDF5_SIGNATURE,
sizeof(HDF5_SIGNATURE))==0) {
127 #if defined(USE_NETCDF4) && defined(USE_HDF4) 128 if(magic[0] ==
'\016' && magic[1] ==
'\003' 129 && magic[2] ==
'\023' && magic[3] ==
'\001') {
135 if(magic[0] ==
'C' && magic[1] ==
'D' && magic[2] ==
'F') {
136 if(magic[3] ==
'\001') {
141 if(magic[3] ==
'\002') {
147 if(magic[3] ==
'\005') {
178 NC_check_file_type(
const char *path,
int flags,
void *parameters,
179 int* model,
int* version)
181 char magic[MAGIC_NUMBER_LEN];
189 struct MagicFile file;
194 memset((
void*)&file,0,
sizeof(file));
196 file.parameters = parameters;
197 if(inmemory && parameters == NULL)
200 file.inmemory = inmemory;
207 file.use_parallel = use_parallel;
213 status = openmagic(&file);
216 if(file.filelen < MAGIC_NUMBER_LEN)
218 if((status = readmagic(&file,0L,magic)) !=
NC_NOERR) {
234 if((pos+MAGIC_NUMBER_LEN) > file.filelen)
236 if((status = readmagic(&file,pos,magic)) !=
NC_NOERR)
526 size_t *chunksizehintp,
int *ncidp)
528 return NC_create(path, cmode, initialsz, 0,
529 chunksizehintp, 0, NULL, ncidp);
552 nc__create_mp(
const char *path,
int cmode,
size_t initialsz,
553 int basepe,
size_t *chunksizehintp,
int *ncidp)
555 return NC_create(path, cmode, initialsz, basepe,
556 chunksizehintp, 0, NULL, ncidp);
671 nc_open(
const char *path,
int mode,
int *ncidp)
673 return NC_open(path, mode, 0, NULL, 0, NULL, ncidp);
729 size_t *chunksizehintp,
int *ncidp)
735 return NC_open(path, mode, 0, chunksizehintp, 0,
785 nc_open_mem(
const char* path,
int mode,
size_t size,
void* memory,
int* ncidp)
791 if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL)
797 meminfo.memory = memory;
798 return NC_open(path, mode, 0, NULL, 0, &meminfo, ncidp);
823 nc__open_mp(
const char *path,
int mode,
int basepe,
824 size_t *chunksizehintp,
int *ncidp)
826 return NC_open(path, mode, basepe, chunksizehintp,
852 if ((stat = NC_check_id(ncid, &ncp)))
854 if(ncp->path == NULL) {
855 if(pathlen) *pathlen = 0;
856 if(path) path[0] =
'\0';
858 if (pathlen) *pathlen = strlen(ncp->path);
859 if (path) strcpy(path, ncp->path);
916 int stat = NC_check_id(ncid, &ncp);
918 return ncp->dispatch->redef(ncid);
981 status = NC_check_id(ncid, &ncp);
982 if(status !=
NC_NOERR)
return status;
983 return ncp->dispatch->_enddef(ncid,0,1,0,1);
1068 nc__enddef(
int ncid,
size_t h_minfree,
size_t v_align,
size_t v_minfree,
1072 int stat = NC_check_id(ncid, &ncp);
1074 return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
1148 int stat = NC_check_id(ncid, &ncp);
1150 return ncp->dispatch->sync(ncid);
1200 int stat = NC_check_id(ncid, &ncp);
1209 stat = ncp->dispatch->abort(ncid);
1210 del_from_NCList(ncp);
1259 int stat = NC_check_id(ncid, &ncp);
1264 if(ncp->refcount <= 0)
1268 stat = ncp->dispatch->close(ncid);
1272 del_from_NCList(ncp);
1381 int stat = NC_check_id(ncid, &ncp);
1383 return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1401 nc_inq_base_pe(
int ncid,
int *pe)
1404 int stat = NC_check_id(ncid, &ncp);
1406 return ncp->dispatch->inq_base_pe(ncid,pe);
1424 nc_set_base_pe(
int ncid,
int pe)
1427 int stat = NC_check_id(ncid, &ncp);
1429 return ncp->dispatch->set_base_pe(ncid,pe);
1454 int stat = NC_check_id(ncid, &ncp);
1456 return ncp->dispatch->inq_format(ncid,formatp);
1489 int stat = NC_check_id(ncid, &ncp);
1491 return ncp->dispatch->inq_format_extended(ncid,formatp,modep);
1539 nc_inq(
int ncid,
int *ndimsp,
int *nvarsp,
int *nattsp,
int *unlimdimidp)
1542 int stat = NC_check_id(ncid, &ncp);
1544 return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1561 int stat = NC_check_id(ncid, &ncp);
1563 return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1641 if(xtype <= ATOMICTYPEMAX4) {
1642 if(name) strncpy(name,NC_atomictypename(xtype),
NC_MAX_NAME);
1643 if(size) *size = NC_atomictypelen(xtype);
1648 stat = NC_check_id(ncid, &ncp);
1652 return ncp->dispatch->inq_type(ncid,xtype,name,size);
1680 if (mode_format && (mode_format & (mode_format - 1)))
1693 #ifndef USE_DISKLESS 1695 if (mode & NC_DISKLESS)
1708 #ifndef USE_PARALLEL 1747 NC_create(
const char *path0,
int cmode,
size_t initialsz,
1748 int basepe,
size_t *chunksizehintp,
int useparallel,
1749 void* parameters,
int *ncidp)
1753 NC_Dispatch* dispatcher = NULL;
1773 if ((stat = nc_initialize()))
1777 #ifndef USE_DISKLESS 1783 path = NCpathcvt(path0);
1785 path = nulldup(path0);
1790 ncp = find_in_NCList_by_name(path);
1798 char* newpath = NULL;
1799 model = NC_urlmodel(path,cmode,&newpath);
1800 isurl = (model != 0);
1824 int format = nc_get_default_format();
1868 if (dispatcher == NULL)
1874 dispatcher = NC4_dispatch_table;
1879 dispatcher = NCP_dispatch_table;
1883 dispatcher = NC3_dispatch_table;
1892 stat = new_NC(dispatcher,path,cmode,model,&ncp);
1893 nullfree(path); path = NULL;
1895 if(stat)
return stat;
1906 if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp,
1907 useparallel, parameters, dispatcher, ncp))) {
1908 del_from_NCList(ncp);
1911 if(ncidp)*ncidp = ncp->ext_ncid;
1940 NC_open(
const char *path0,
int cmode,
int basepe,
size_t *chunksizehintp,
1941 int useparallel,
void* parameters,
int *ncidp)
1945 NC_Dispatch* dispatcher = NULL;
1957 stat = nc_initialize();
1958 if(stat)
return stat;
1966 #ifndef USE_DISKLESS 1976 path = NCpathcvt(path0);
1978 path = nulldup(path0);
1983 ncp = find_in_NCList_by_name(path);
1987 if(ncidp) *ncidp = ncp->ext_ncid;
1993 char* newpath = NULL;
1994 model = NC_urlmodel(path,cmode,&newpath);
1995 isurl = (model != 0);
2008 stat = NC_check_file_type(path,flags,parameters,&model,&version);
2022 fprintf(stderr,
"Model == 0\n");
2049 else if(version == 5) {
2066 if(dispatcher != NULL)
goto havetable;
2069 #if defined(ENABLE_DAP) 2071 dispatcher = NCD2_dispatch_table;
2074 #if defined(ENABLE_DAP4) 2076 dispatcher = NCD4_dispatch_table;
2079 #if defined(USE_PNETCDF) 2081 dispatcher = NCP_dispatch_table;
2084 #if defined(USE_NETCDF4) 2086 dispatcher = NC4_dispatch_table;
2090 dispatcher = NC3_dispatch_table;
2098 if(dispatcher == NULL) {
2104 stat = new_NC(dispatcher,path,cmode,model,&ncp);
2105 nullfree(path); path = NULL;
2106 if(stat)
return stat;
2117 stat = dispatcher->open(ncp->path, cmode, basepe, chunksizehintp,
2118 useparallel, parameters, dispatcher, ncp);
2120 if(ncidp) *ncidp = ncp->ext_ncid;
2122 del_from_NCList(ncp);
2133 static int pseudofd = 0;
2147 #ifdef HAVE_GETRLIMIT 2149 if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
2150 if(rl.rlim_max != RLIM_INFINITY)
2151 maxfd = (int)rl.rlim_max;
2152 if(rl.rlim_cur != RLIM_INFINITY)
2153 maxfd = (int)rl.rlim_cur;
2167 openmagic(
struct MagicFile* file)
2170 if(file->inmemory) {
2172 NC_MEM_INFO* meminfo = (NC_MEM_INFO*)file->parameters;
2173 file->filelen = (
long long)meminfo->size;
2177 if (file->use_parallel) {
2181 MPI_Comm comm = MPI_COMM_WORLD;
2182 MPI_Info info = MPI_INFO_NULL;
2183 if(file->parameters != NULL) {
2184 comm = ((NC_MPI_INFO*)file->parameters)->comm;
2185 info = ((NC_MPI_INFO*)file->parameters)->info;
2187 if((retval = MPI_File_open(comm,(
char*)file->path,MPI_MODE_RDONLY,info,
2188 &file->fh)) != MPI_SUCCESS)
2191 if((retval=MPI_File_get_size(file->fh, &size)) != MPI_SUCCESS)
2193 file->filelen = (
long long)size;
2198 if(file->path == NULL || strlen(file->path)==0)
2201 file->fp = fopen(file->path,
"rb");
2203 file->fp = fopen(file->path,
"r");
2205 if(file->fp == NULL)
2206 {status = errno;
goto done;}
2210 int fd = fileno(file->fp);
2211 __int64 len64 = _filelengthi64(fd);
2213 {status = errno;
goto done;}
2214 file->filelen = (
long long)len64;
2217 if((status = fseek(file->fp, 0L, SEEK_END)) < 0)
2218 {status = errno;
goto done;}
2219 size = ftell(file->fp);
2220 file->filelen = (
long long)size;
2232 readmagic(
struct MagicFile* file,
long pos,
char* magic)
2235 memset(magic,0,MAGIC_NUMBER_LEN);
2236 if(file->inmemory) {
2238 NC_MEM_INFO* meminfo = (NC_MEM_INFO*)file->parameters;
2239 if((pos + MAGIC_NUMBER_LEN) > meminfo->size)
2241 mempos = ((
char*)meminfo->memory) + pos;
2242 memcpy((
void*)magic,mempos,MAGIC_NUMBER_LEN);
2244 printmagic(
"XXX: readmagic",magic,file);
2249 if (file->use_parallel) {
2254 if((retval = MPI_File_seek(file->fh, offset, MPI_SEEK_SET)) != MPI_SUCCESS)
2256 if((retval = MPI_File_read(file->fh, magic, MAGIC_NUMBER_LEN, MPI_CHAR,
2257 &mstatus)) != MPI_SUCCESS)
2264 int i = fseek(file->fp,pos,SEEK_SET);
2266 {status = errno;
goto done;}
2267 for(i=0;i<MAGIC_NUMBER_LEN;) {
2268 count=fread(&magic[i],1,(MAGIC_NUMBER_LEN-i),file->fp);
2269 if(count == 0 || ferror(file->fp))
2270 {status = errno;
goto done;}
2276 if(file && file->fp) clearerr(file->fp);
2293 if(file->inmemory)
goto done;
2295 if (file->use_parallel) {
2298 if((retval = MPI_File_close(&file->fh)) != MPI_SUCCESS)
2304 if(file->fp) fclose(file->fp);
2313 printmagic(
const char* tag,
char* magic,
struct MagicFile* f)
2316 fprintf(stderr,
"%s: inmem=%d ispar=%d magic=",tag,f->inmemory,f->use_parallel);
2317 for(i=0;i<MAGIC_NUMBER_LEN;i++) {
2318 unsigned int c = (
unsigned int)magic[i];
2321 fprintf(stderr,
" 0x%0x/'\\n'",c);
2323 fprintf(stderr,
" 0x%0x/'\\r'",c);
2325 fprintf(stderr,
" 0x%0x/'?'",c);
2327 fprintf(stderr,
" 0x%0x/'%c'",c,c);
2329 fprintf(stderr,
"\n");
#define NC_PNETCDF
Use parallel-netcdf library; alias for NC_MPIIO.
int nc__open(const char *path, int mode, size_t *chunksizehintp, int *ncidp)
Open a netCDF file with extra performance parameters for the classic library.
#define NC_ENFILE
Too many netcdfs open.
int NC_initialized
True when dispatch table is initialized.
#define NC_FORMATX_NC4
alias
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Main header file for in-memory (diskless) functionality.
int nc_redef(int ncid)
Put open netcdf dataset into define mode.
int nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree, size_t r_align)
Leave define mode with performance tuning.
#define NC_INMEMORY
Read from memory.
#define NC_MPIIO
Turn on MPI I/O.
int nc_inq_format(int ncid, int *formatp)
Inquire about the binary format of a netCDF file as presented by the API.
int nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
Inquire about a file or group.
int nc_type
The nc_type type is just an int.
#define NC_64BIT_OFFSET
Use large (64-bit) file offsets.
int nc_inq_format_extended(int ncid, int *formatp, int *modep)
Obtain more detailed (vis-a-vis nc_inq_format) format information about an open dataset.
#define NC_ENOTNC
Not a netcdf file.
#define NC_FORMAT_CDF5
Format specifier for nc_set_default_format() and returned by nc_inq_format.
#define NC_64BIT_DATA
CDF-5 format: classic model but 64 bit dimensions and sizes.
#define NC_ENOTBUILT
Attempt to use feature that was not turned on when netCDF was built.
int nc_close(int ncid)
Close an open netCDF dataset.
#define NC_EDISKLESS
Error in using diskless access.
int nc_abort(int ncid)
No longer necessary for user to invoke manually.
#define NC_EBADTYPE
Not a netcdf data type.
#define NC_SIZEHINT_DEFAULT
Let nc__create() or nc__open() figure out a suitable buffer size.
#define NC_EINVAL
Invalid Argument.
int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
#define NC_MAX_NAME
Maximum for classic library.
#define NC_NAT
Not A Type.
int nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
Inquire about a type.
#define NC_FORMATX_DAP2
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
#define NC_FORMATX_NC3
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
#define NC_EPARINIT
Error initializing for parallel access.
#define NC_NETCDF4
Use netCDF-4/HDF5 format.
int nc__create(const char *path, int cmode, size_t initialsz, size_t *chunksizehintp, int *ncidp)
Create a netCDF file with some extra parameters controlling classic file cacheing.
#define NC_FORMAT_NETCDF4_CLASSIC
Format specifier for nc_set_default_format() and returned by nc_inq_format.
#define NC_FORMATX_NC_HDF4
netCDF-4 subset of HDF4
#define NC_FORMAT_NETCDF4
Format specifier for nc_set_default_format() and returned by nc_inq_format.
#define NC_CDF5
Alias NC_CDF5 to NC_64BIT_DATA.
#define NC_WRITE
Set read-write access for nc_open().
int nc_inq_path(int ncid, size_t *pathlen, char *path)
Get the file pathname (or the opendap URL) which was used to open/create the ncid's file...
#define NC_NOERR
No Error.
int nc_inq_nvars(int ncid, int *nvarsp)
Learn the number of variables in a file or group.
#define NC_DISKLESS
Use diskless file.
static int check_create_mode(int mode)
Check the create mode parameter for sanity.
int nc_open(const char *path, int mode, int *ncidp)
Open an existing netCDF file.
#define NC_FORMATX_DAP4
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
int nc_enddef(int ncid)
Leave define mode.
#define NC_FORMATX_PNETCDF
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
int nc_open_mem(const char *path, int mode, size_t size, void *memory, int *ncidp)
Open a netCDF file with the contents taken from a block of memory.
static int NC_interpret_magic_number(char *magic, int *model, int *version)
Interpret the magic number found in the header of a netCDF file.
#define NC_FORMAT_64BIT_OFFSET
Format specifier for nc_set_default_format() and returned by nc_inq_format.
#define NC_MMAP
Use diskless file with mmap.
static int closemagic(struct MagicFile *file)
Close the file opened to check for magic number.
#define NC_FORMATX_UNDEFINED
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
#define NC_FORMAT_CLASSIC
Format specifier for nc_set_default_format() and returned by nc_inq_format.
int nc_sync(int ncid)
Synchronize an open netcdf dataset to disk.
int nc_create(const char *path, int cmode, int *ncidp)
Create a new netCDF file.
#define NC_MPIPOSIX
Turn on MPI POSIX I/O.