18 #ifdef HAVE_SYS_RESOURCE_H
19 #include <sys/resource.h>
21 #ifdef HAVE_SYS_TYPES_H
22 #include <sys/types.h>
24 #ifdef HAVE_SYS_STAT_H
35 extern int fileno(FILE*);
37 #include "ncdispatch.h"
39 #include "ncwinpath.h"
64 static int openmagic(
struct MagicFile* file);
65 static int readmagic(
struct MagicFile* file,
long pos,
char* magic);
68 static void printmagic(
const char* tag,
char* magic,
struct MagicFile*);
75 static char HDF5_SIGNATURE[MAGIC_NUMBER_LEN] =
"\211HDF\r\n\032\n";
79 NC_Dispatch *UDF0_dispatch_table = NULL;
81 NC_Dispatch *UDF1_dispatch_table = NULL;
151 UDF0_dispatch_table = dispatch_table;
156 UDF1_dispatch_table = dispatch_table;
192 *dispatch_table = UDF0_dispatch_table;
198 *dispatch_table = UDF1_dispatch_table;
230 if (strlen(UDF0_magic_number) && !strncmp(UDF0_magic_number, magic,
231 strlen(UDF0_magic_number)))
237 if (strlen(UDF1_magic_number) && !strncmp(UDF1_magic_number, magic,
238 strlen(UDF1_magic_number)))
247 if(memcmp(magic,HDF5_SIGNATURE,
sizeof(HDF5_SIGNATURE))==0) {
252 if(magic[0] ==
'\016' && magic[1] ==
'\003'
253 && magic[2] ==
'\023' && magic[3] ==
'\001') {
258 if(magic[0] ==
'C' && magic[1] ==
'D' && magic[2] ==
'F') {
259 if(magic[3] ==
'\001') {
264 if(magic[3] ==
'\002') {
269 if(magic[3] ==
'\005') {
299 NC_check_file_type(
const char *path,
int flags,
int use_parallel,
300 void *parameters,
int* model,
int* version)
302 char magic[MAGIC_NUMBER_LEN];
308 struct MagicFile file;
314 if(diskless && inmemory) {status =
NC_EDISKLESS;
goto done;}
315 if(diskless && mmap) {status =
NC_EDISKLESS;
goto done;}
316 if(inmemory && mmap) {status =
NC_EINMEMORY;
goto done;}
321 memset((
void*)&file,0,
sizeof(file));
323 file.parameters = parameters;
324 file.inmemory = inmemory;
325 file.diskless = diskless;
326 file.use_parallel = use_parallel;
328 status = openmagic(&file);
331 if(file.filelen < MAGIC_NUMBER_LEN)
333 if((status = readmagic(&file,0L,magic)) !=
NC_NOERR) {
353 if((pos+MAGIC_NUMBER_LEN) > file.filelen)
355 if((status = readmagic(&file,pos,magic)) !=
NC_NOERR)
635 size_t *chunksizehintp,
int *ncidp)
637 return NC_create(path, cmode, initialsz, 0,
638 chunksizehintp, 0, NULL, ncidp);
684 return NC_create(path, mode, initialsize, 0, NULL, 0, NULL, ncidp);
707 nc__create_mp(
const char *path,
int cmode,
size_t initialsz,
708 int basepe,
size_t *chunksizehintp,
int *ncidp)
710 return NC_create(path, cmode, initialsz, basepe,
711 chunksizehintp, 0, NULL, ncidp);
828 nc_open(
const char *path,
int omode,
int *ncidp)
830 return NC_open(path, omode, 0, NULL, 0, NULL, ncidp);
886 size_t *chunksizehintp,
int *ncidp)
891 return NC_open(path, omode, 0, chunksizehintp, 0, NULL, ncidp);
940 nc_open_mem(
const char* path,
int omode,
size_t size,
void* memory,
int* ncidp)
945 if(memory == NULL || size < MAGIC_NUMBER_LEN || path == NULL)
951 meminfo.memory = memory;
952 meminfo.flags = NC_MEMIO_LOCKED;
953 return NC_open(path, omode, 0, NULL, 0, &meminfo, ncidp);
1008 if(path == NULL || params == NULL)
1010 if(params->memory == NULL || params->size < MAGIC_NUMBER_LEN)
1016 return NC_open(path, omode, 0, NULL, 0, params, ncidp);
1038 nc__open_mp(
const char *path,
int omode,
int basepe,
1039 size_t *chunksizehintp,
int *ncidp)
1041 return NC_open(path, omode, basepe, chunksizehintp, 0, NULL, ncidp);
1066 if ((stat = NC_check_id(ncid, &ncp)))
1068 if(ncp->path == NULL) {
1069 if(pathlen) *pathlen = 0;
1070 if(path) path[0] =
'\0';
1072 if (pathlen) *pathlen = strlen(ncp->path);
1073 if (path) strcpy(path, ncp->path);
1130 int stat = NC_check_id(ncid, &ncp);
1132 return ncp->dispatch->redef(ncid);
1195 status = NC_check_id(ncid, &ncp);
1196 if(status !=
NC_NOERR)
return status;
1197 return ncp->dispatch->_enddef(ncid,0,1,0,1);
1282 nc__enddef(
int ncid,
size_t h_minfree,
size_t v_align,
size_t v_minfree,
1286 int stat = NC_check_id(ncid, &ncp);
1288 return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
1362 int stat = NC_check_id(ncid, &ncp);
1364 return ncp->dispatch->sync(ncid);
1414 int stat = NC_check_id(ncid, &ncp);
1423 stat = ncp->dispatch->abort(ncid);
1424 del_from_NCList(ncp);
1473 int stat = NC_check_id(ncid, &ncp);
1478 if(ncp->refcount <= 0)
1481 stat = ncp->dispatch->close(ncid,NULL);
1485 del_from_NCList(ncp);
1538 int stat = NC_check_id(ncid, &ncp);
1543 if(ncp->refcount <= 0)
1546 stat = ncp->dispatch->close(ncid,memio);
1550 del_from_NCList(ncp);
1659 int stat = NC_check_id(ncid, &ncp);
1661 return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1679 nc_inq_base_pe(
int ncid,
int *pe)
1682 int stat = NC_check_id(ncid, &ncp);
1684 return ncp->dispatch->inq_base_pe(ncid,pe);
1702 nc_set_base_pe(
int ncid,
int pe)
1705 int stat = NC_check_id(ncid, &ncp);
1707 return ncp->dispatch->set_base_pe(ncid,pe);
1732 int stat = NC_check_id(ncid, &ncp);
1734 return ncp->dispatch->inq_format(ncid,formatp);
1767 int stat = NC_check_id(ncid, &ncp);
1769 return ncp->dispatch->inq_format_extended(ncid,formatp,modep);
1817 nc_inq(
int ncid,
int *ndimsp,
int *nvarsp,
int *nattsp,
int *unlimdimidp)
1820 int stat = NC_check_id(ncid, &ncp);
1822 return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1839 int stat = NC_check_id(ncid, &ncp);
1841 return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1919 if(xtype <= ATOMICTYPEMAX4) {
1920 if(name) strncpy(name,NC_atomictypename(xtype),
NC_MAX_NAME);
1921 if(size) *size = NC_atomictypelen(xtype);
1926 stat = NC_check_id(ncid, &ncp);
1930 return ncp->dispatch->inq_type(ncid,xtype,name,size);
1961 if (mode_format && (mode_format & (mode_format - 1)))
1974 if(mmap && (mode & NC_NETCDF4))
return NC_EINVAL;
1983 if (mode & NC_NETCDF4)
2019 NC_create(
const char *path0,
int cmode,
size_t initialsz,
2020 int basepe,
size_t *chunksizehintp,
int useparallel,
2021 void* parameters,
int *ncidp)
2025 NC_Dispatch* dispatcher = NULL;
2044 if ((stat = nc_initialize()))
2050 path = NCpathcvt(path0);
2052 path = nulldup(path0);
2057 ncp = find_in_NCList_by_name(path);
2065 char* newpath = NULL;
2066 model = NC_urlmodel(path,cmode,&newpath);
2067 isurl = (model != 0);
2095 int format = nc_get_default_format();
2134 dispatcher = HDF5_dispatch_table;
2140 dispatcher = NCP_dispatch_table;
2145 dispatcher = NC3_dispatch_table;
2152 stat = new_NC(dispatcher,path,cmode,model,&ncp);
2153 nullfree(path); path = NULL;
2155 if(stat)
return stat;
2166 if ((stat = dispatcher->create(ncp->path, cmode, initialsz, basepe, chunksizehintp,
2167 parameters, dispatcher, ncp))) {
2168 del_from_NCList(ncp);
2171 if(ncidp)*ncidp = ncp->ext_ncid;
2200 NC_open(
const char *path0,
int omode,
int basepe,
size_t *chunksizehintp,
2201 int useparallel,
void* parameters,
int *ncidp)
2205 NC_Dispatch* dispatcher = NULL;
2217 stat = nc_initialize();
2218 if(stat)
return stat;
2226 if(mmap && inmemory)
2228 if(mmap && diskless)
2237 path = NCpathcvt(path0);
2239 path = nulldup(path0);
2244 ncp = find_in_NCList_by_name(path);
2248 if(ncidp) *ncidp = ncp->ext_ncid;
2254 char* newpath = NULL;
2255 model = NC_urlmodel(path,omode,&newpath);
2256 isurl = (model != 0);
2268 if (!UDF0_dispatch_table)
2271 dispatcher = UDF0_dispatch_table;
2277 if (!UDF1_dispatch_table)
2280 dispatcher = UDF1_dispatch_table;
2288 stat = NC_check_file_type(path,flags,useparallel,parameters,&model,&version);
2302 fprintf(stderr,
"Model == 0\n");
2339 omode &= ~NC_NETCDF4;
2342 omode &= ~NC_NETCDF4;
2346 omode &= ~NC_NETCDF4;
2354 #if defined(ENABLE_DAP)
2356 dispatcher = NCD2_dispatch_table;
2359 #if defined(ENABLE_DAP4)
2361 dispatcher = NCD4_dispatch_table;
2364 #if defined(USE_PNETCDF)
2366 dispatcher = NCP_dispatch_table;
2369 #if defined(USE_HDF5)
2371 dispatcher = HDF5_dispatch_table;
2374 #if defined(USE_HDF4)
2376 dispatcher = HDF4_dispatch_table;
2381 dispatcher = UDF0_dispatch_table;
2384 dispatcher = UDF1_dispatch_table;
2388 dispatcher = NC3_dispatch_table;
2403 stat = new_NC(dispatcher,path,omode,model,&ncp);
2404 nullfree(path); path = NULL;
2405 if(stat)
return stat;
2416 stat = dispatcher->open(ncp->path, omode, basepe, chunksizehintp,
2417 parameters, dispatcher, ncp);
2419 if(ncidp) *ncidp = ncp->ext_ncid;
2421 del_from_NCList(ncp);
2432 static int pseudofd = 0;
2446 #ifdef HAVE_GETRLIMIT
2448 if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
2449 if(rl.rlim_max != RLIM_INFINITY)
2450 maxfd = (int)rl.rlim_max;
2451 if(rl.rlim_cur != RLIM_INFINITY)
2452 maxfd = (int)rl.rlim_cur;
2466 openmagic(
struct MagicFile* file)
2469 assert((file->inmemory) ? file->parameters != NULL : 1);
2470 if(file->inmemory) {
2473 file->filelen = (
long long)meminfo->size;
2477 if (file->use_parallel) {
2480 assert(file->parameters);
2481 if((retval = MPI_File_open(((NC_MPI_INFO*)file->parameters)->comm,
2482 (
char*)file->path,MPI_MODE_RDONLY,
2483 ((NC_MPI_INFO*)file->parameters)->info,
2484 &file->fh)) != MPI_SUCCESS) {
2485 #ifdef MPI_ERR_NO_SUCH_FILE
2487 MPI_Error_class(retval, &errorclass);
2488 if (errorclass == MPI_ERR_NO_SUCH_FILE)
2500 if((retval=MPI_File_get_size(file->fh, &size)) != MPI_SUCCESS)
2502 file->filelen = (
long long)size;
2507 if(file->path == NULL || strlen(file->path)==0)
2510 file->fp = fopen(file->path,
"rb");
2512 file->fp = fopen(file->path,
"r");
2514 if(file->fp == NULL)
2515 {status = errno;
goto done;}
2518 int fd = fileno(file->fp);
2520 __int64 len64 = _filelengthi64(fd);
2522 {status = errno;
goto done;}
2523 file->filelen = (
long long)len64;
2526 size = lseek(fd, 0, SEEK_END);
2528 {status = errno;
goto done;}
2529 file->filelen = (
long long)size;
2541 readmagic(
struct MagicFile* file,
long pos,
char* magic)
2544 memset(magic,0,MAGIC_NUMBER_LEN);
2545 if(file->inmemory) {
2548 if((pos + MAGIC_NUMBER_LEN) > meminfo->size)
2550 mempos = ((
char*)meminfo->memory) + pos;
2551 memcpy((
void*)magic,mempos,MAGIC_NUMBER_LEN);
2553 printmagic(
"XXX: readmagic",magic,file);
2558 if (file->use_parallel) {
2561 if((retval = MPI_File_read_at_all(file->fh, pos, magic,
2562 MAGIC_NUMBER_LEN, MPI_CHAR, &mstatus)) != MPI_SUCCESS)
2569 int i = fseek(file->fp,pos,SEEK_SET);
2571 {status = errno;
goto done;}
2572 for(i=0;i<MAGIC_NUMBER_LEN;) {
2573 count=fread(&magic[i],1,(
size_t)(MAGIC_NUMBER_LEN-i),file->fp);
2574 if(count == 0 || ferror(file->fp))
2575 {status = errno;
goto done;}
2581 if(file && file->fp) clearerr(file->fp);
2598 if(file->inmemory)
goto done;
2600 if (file->use_parallel) {
2602 if((retval = MPI_File_close(&file->fh)) != MPI_SUCCESS)
2608 if(file->fp) fclose(file->fp);
2617 printmagic(
const char* tag,
char* magic,
struct MagicFile* f)
2620 fprintf(stderr,
"%s: inmem=%d ispar=%d magic=",tag,f->inmemory,f->use_parallel);
2621 for(i=0;i<MAGIC_NUMBER_LEN;i++) {
2622 unsigned int c = (
unsigned int)magic[i];
2625 fprintf(stderr,
" 0x%0x/'\\n'",c);
2627 fprintf(stderr,
" 0x%0x/'\\r'",c);
2629 fprintf(stderr,
" 0x%0x/'?'",c);
2631 fprintf(stderr,
" 0x%0x/'%c'",c,c);
2633 fprintf(stderr,
"\n");
#define NC_MAX_MAGIC_NUMBER_LEN
Max len of user-defined format magic number.
#define NC_ENFILE
Too many netcdfs open.
int nc_def_user_format(int mode_flag, NC_Dispatch *dispatch_table, char *magic_number)
Add handling of user-defined format.
int NC_initialized
True when dispatch table is initialized.
int nc_close_memio(int ncid, NC_memio *memio)
Do a normal close (see nc_close()) on an in-memory dataset, then return a copy of the final memory co...
#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_UDF1
User-defined format 1.
#define NC_INMEMORY
Read from memory.
#define NC_MPIIO
Turn on MPI I/O.
int nc_open_memio(const char *path, int omode, NC_memio *params, int *ncidp)
Open a netCDF file with the contents taken from a block of memory.
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__open(const char *path, int omode, size_t *chunksizehintp, int *ncidp)
Open a netCDF file with extra performance parameters for the classic library.
#define NC_UDF0
User-defined format 0.
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.
int nc_open_mem(const char *path, int omode, size_t size, void *memory, int *ncidp)
Open a netCDF file with the contents taken from a block of memory.
#define NC_SIZEHINT_DEFAULT
Let nc__create() or nc__open() figure out a suitable buffer size.
#define NC_EINVAL
Invalid Argument.
#define NC_EINMEMORY
In-memory file error.
int nc_set_fill(int ncid, int fillmode, int *old_modep)
Change the fill-value mode to improve write performance.
#define NC_FORMATX_UDF0
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
#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 caching. ...
#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
int nc_open(const char *path, int omode, int *ncidp)
Open an existing netCDF file.
#define NC_FORMATX_UDF1
Extended format specifier returned by nc_inq_format_extended() Added in version 4.3.1.
#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_user_format(int mode_flag, NC_Dispatch **dispatch_table, char *magic_number)
Inquire about user-defined format.
int nc_create_mem(const char *path, int mode, size_t initialsize, int *ncidp)
Create a netCDF file with the contents stored in memory.
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.
#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.
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.
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.