Change (again), and hopefully simplify, the file model inference algorithm.

* For URL paths, the new approach essentially centralizes all information
  in the URL into the "#mode=" fragment key and uses that value
  to determine the dispatcher for (most) URLs.

* The new approach has the following steps:

  1. canonicalize the path if it is a URL.
  2. use the mode= fragment key to determine the dispatcher
  3. if dispatcher still not determined, then use the mode flags
     argument to nc_open/nc_create to determine the dispatcher.
  4. if the path points to something readable, attempt to read the
     magic number at the front, and use that to determine the dispatcher.
     this case may override all previous cases.

* Misc changes.

  1. Update documentation
  2. Moved some unit tests from libdispatch to unit_test directory.
  3. Fixed use of wrong #ifdef macro in test_filter_reg.c
     [I think this may fix an previously reported esupport query].
This commit is contained in:
Dennis Heimbigner 2019-09-29 12:59:28 -06:00
parent 40cf6fb958
commit f1506d552e
30 changed files with 585 additions and 577 deletions

View File

@ -1,42 +1,34 @@
# Test c output
T=tst_diskless5
T=tst_vars3
#H58=8
H510=10
#SRC=hdf5plugins/H5Zmisc.c
#ARGS=diskless persist
#CMD=valgrind --leak-check=full
CMD=gdb --args
#SRC=
#CMD=env HDF5_DEBUG=trace
#CMD=export NETCDF_LOG_LEVEL=5 ;gdb --args
CMD=valgrind --leak-check=full
#CMD=gdb --args
#FILTER=H5Zmisc
#FILTEROBJ=hdf5plugins/${FILTER}.o
#PAR=1
#SZIP=1
ifdef H58
H5L=/usr/local
endif
ifdef H510
H5L=/opt
endif
#CFLAGS = -Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
CFLAGS = -Wall -g -O0 -I.. -I../include
CFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
LDFLAGS = ../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lm -lmfhdf -ldf
ifdef PAR
CC=mpicc
#CC=/usr/local/bin/mpicc
LDFLAGS=../liblib/.libs/libnetcdf.a -L${H5L}/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lpnetcdf -lmpich -lm
LDFLAGS += -lmpich
else
CC=gcc
#LDFLAGS=../liblib/.libs/libnetcdf.a -L${H5L}/lib -lhdf5_hl -lhdf5 -lz -lm -lcurl
LDFLAGS=../liblib/.libs/libnetcdf.a -L${H5L}/lib -lhdf5_hl -lhdf5 -lz -ldl -lm -lcurl
endif
# cd .. ; ${MAKE} all
ifdef SZIP
LDFLAGS += -lsz -laec
endif
LLP=${H5L}/lib:${LD_LIBRARY_PATH}
LLP=/usr/local/lib:${LD_LIBRARY_PATH}
all:: cmp
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
@ -44,14 +36,17 @@ all:: cmp
cmp::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${LDFLAGS}; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${FILTEROBJ} ${LDFLAGS}
filter::
${CC} ${CFLAGS} -c hdf5plugins/${FILTER}.c ${LDFLAGS}
cpp::
${CC} -E ${CFLAGS} ${T}.c > ${T}.txt
#TS = tst_diskless tst_diskless2 tst_diskless3 tst_diskless4 tst_diskless5 tst_diskless6
TS = tst_diskless5
several::
H5=h5testszip
EXT=testszip.nc
h5::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
for f in ${TS} ; do ${CC} -o ${TS} ${CFLAGS} ${TS}.c ${SRC} ${LDFLAGS}; done
${CC} -o h5 ${CFLAGS} ${H5}.c ${SRC} ${LDFLAGS}; \
${CMD} ./h5 ${EXT}

View File

@ -20,15 +20,15 @@ the remote server supports byte-range access.
Two examples:
1. An Amazon S3 object containing a netcdf classic file.
- location: "http://149.165.169.123:8080/thredds/fileServer/testdata/2004050300_eta_211.nc#bytes"
- location: "http://149.165.169.123:8080/thredds/fileServer/testdata/2004050300_eta_211.nc#mode=bytes"
2. A Thredds Server dataset supporting the Thredds HTTPServer protocol.
and containing a netcdf enhanced file.
- location: "http://noaa-goes16.s3.amazonaws.com/ABI-L1b-RadC/2017/059/03/OR_ABI-L1b-RadC-M3C13_G16_s20170590337505_e20170590340289_c20170590340316.nc#bytes"
- location: "http://noaa-goes16.s3.amazonaws.com/ABI-L1b-RadC/2017/059/03/OR_ABI-L1b-RadC-M3C13_G16_s20170590337505_e20170590340289_c20170590340316.nc#mode=bytes"
Other remote servers may also provide byte-range access in a similar form.
It is important to note that this is not intended as a true
production capability because, as is known, this kind of access
production capability because it is believed that this kind of access
can be quite slow. In addition, the byte-range IO drivers do not
currently do any sort of optimization or caching.
@ -42,7 +42,7 @@ This capability requires access to *libcurl*, and an error will occur
if byterange is enabled, but no *libcurl* could not be located.
In this, it is similar to the DAP2 and DAP4 capabilities.
Note also that the term "http" is often used as a synonym for *byterange*.
Note also that here, the term "http" is often used as a synonym for *byterange*.
# Run-time Usage {#byterange_url}
@ -50,7 +50,7 @@ In order to use this capability at run-time, with *ncdump* for
example, it is necessary to provide a URL pointing to the basic
dataset to be accessed. The URL must be annotated to tell the
netcdf-c library that byte-range access should be used. This is
indicated by appending the phrase ````#bytes````
indicated by appending the phrase ````#mode=bytes````
to the end of the URL.
The two examples above show how this will look.

View File

@ -494,39 +494,45 @@ _libdispatch/dinfermodel.c_ via the API in _include/ncmodel.h_.
The term _model_ is used here to include (at least) the following
information (see the structure type _NCmodel_ in _include/ncmodel.h_).
1. format -- this is an NC_FORMAT_XXX value defining the file format
as seen by the user program.
2. version -- the specific version of the format.
3. iosp -- this is and NC_IOSP_XXX value describing internal protocols to use.
4. impl -- this is an NC_FORMATX_XXX value defining, in effect, the
1. impl -- this is an NC_FORMATX_XXX value defining, in effect, the
dispatch table to use.
For example, if the format was NC_FORMAT_CLASSIC, then the client
will see the netcdf-3 data model, as modified by the version. If the
version was 5, for example, then that indicates the file format
is actually NC_FORMAT_64BIT_DATA, which is a variant of the netcdf-3
format.
The _iosp_ provides information about how the protocol the
dispatch table will use to access the actual dataset. If the iosp
is NC_IOSP_S3RAW, then it indicates that the dispatcher, NC_FORMATX_NC3,
for example, will access the dataset using the Amazon S3 REST API.
The construction of the model is primarily carried out by the function
_NC_infermodel()_. It is given the following parameters:
_NC_infermodel()_ (in _libdispatch/dinfermodel.c_).
It is given the following parameters:
1. path -- (IN) absolute file path or URL
2. omodep -- (IN/OUT) the set of mode flags given to _NC_open_ or _NC_create_.
2. modep -- (IN/OUT) the set of mode flags given to _NC_open_ or _NC_create_.
3. iscreate -- (IN) distinguish open from create.
4. useparallel -- (IN) indicate if parallel IO can be used.
5. params -- (IN/OUT) arbitrary data dependent on the mode and path.
6. model -- (IN/OUT) place to store inferred model information (e.g. format
or version).
7. newpathp -- (OUT) sometimes, it is necessary to rewrite the path.
6. model -- (IN/OUT) place to store inferred model.
7. newpathp -- (OUT) the canonical rewrite of the path argument.
As a rule, these values are used in the this order to infer the model.
1. file contents -- highest precedence
2. url (if it is one) -- using the protocol and fragment arguments
2. url (if it is one) -- using the "mode=" key in the fragment (see below).
3. mode flags
4. default format -- lowest precedence
If the path appears to be a URL, then it is parsed.
Information is extracted from the URL, and specifically,
the fragment key "mode=" is the critical element.
The URL will be rewritten to a canonical form with the following
changes.
1. The fragment part ("#..." at the end) is parsed and the "mode=" key
is extracted and its value is converted to a list of tags.
2. If the leading protocol is not http/https, then the protocol is added
to the mode list. That protocol is then replaced with either http or https.
3. Certain singleton values inb the fragment are extracted and removed
and added to the mode list. Consider, for example, "http://....#dap4".
The "dap4" singleton is removed and added to the mode list.
4. For backward compatibility, the values of "proto=" and "protocol="
are removed from the fragment and their value is added to the mode list.
5. The final mode list is converted to a comma separated string
and re-inserted into the fragment.
6. The final mode list is modified to remove duplicates.
The final result is the canonical form of the URL and is returned in the
newpathp argument described above.
*/

View File

@ -8,9 +8,6 @@
#include "config.h"
#include "netcdf.h"
/* Forward */
struct NCmodel;
/* There's an external ncid (ext_ncid) and an internal ncid
* (int_ncid). The ext_ncid is the ncid returned to the user. If
* the user has opened or created a netcdf-4 file, then the
@ -30,7 +27,6 @@ typedef struct NC {
void* dispatchdata; /*per-'file' data; points to e.g. NC3_INFO data*/
char* path;
int mode; /* as provided to nc_open/nc_create */
struct NCmodel* model; /* as determined by libdispatch/dfile.c */
} NC;
/*
@ -79,6 +75,6 @@ extern int iterate_NCList(int i,NC**); /* Walk from 0 ...; ERANGE return => stop
/* Defined in nc.c */
extern void free_NC(NC*);
extern int new_NC(const struct NC_Dispatch*, const char*, int, struct NCmodel*, NC**);
extern int new_NC(const struct NC_Dispatch*, const char*, int, NC**);
#endif /* _NC_H_ */

View File

@ -9,39 +9,20 @@
#ifndef NCINFERMODEL_H
#define NCINFERMODEL_H
/* Define the io handler to be used to do lowest level
access. This is above the libcurl level and below the
dispatcher level. This is only used for remote
datasets or for implementations where the implementation
multiplexes more than one IOSP in a single dispatcher.
*/
#define NC_IOSP_FILE (1)
#define NC_IOSP_MEMORY (2)
#define NC_IOSP_DAP2 (3)
#define NC_IOSP_DAP4 (4)
#define NC_IOSP_UDF (5) /*Placeholder since we do not know IOSP for UDF*/
#define NC_IOSP_HTTP (6)
/* Track the information hat will help us
infer how to access the data defined by
path + omode.
path + omode + (sometimes) file content.
*/
typedef struct NCmodel {
int format; /* NC_FORMAT_XXX value */
int impl; /* NC_FORMATX_XXX value */
int iosp; /* NC_IOSP_XXX value (above) */
int format; /* NC_FORMAT_XXX value; Used to remember extra info; */
} NCmodel;
/* Keep compiler quiet */
struct NCURI;
struct NC_dispatch;
#if 0
/* return first IOSP or NULL if none */
EXTERNL int NC_urliosp(struct NCURI* u);
#endif
/* Infer model format and implementation */
/* Infer model implementation */
EXTERNL int NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void* params, NCmodel* model, char** newpathp);
/**
@ -53,15 +34,4 @@ EXTERNL int NC_infermodel(const char* path, int* omodep, int iscreate, int usepa
*/
EXTERNL int nc__testurl(const char* path, char** basenamep);
#if 0
/* allow access url parse and params without exposing nc_url.h */
EXTERNL int NCDAP_urlparse(const char* s, void** dapurl);
EXTERNL void NCDAP_urlfree(void* dapurl);
EXTERNL const char* NCDAP_urllookup(void* dapurl, const char* param);
/* Ping a specific server */
EXTERNL int NCDAP2_ping(const char*);
EXTERNL int NCDAP4_ping(const char*);
#endif
#endif /*NCINFERMODEL_H*/

View File

@ -61,5 +61,6 @@ extern char* NC_entityescape(const char* s);
extern int NC_readfile(const char* filename, NCbytes* content);
extern int NC_writefile(const char* filename, size_t size, void* content);
extern char* NC_mktmp(const char* base);
extern int NC_getmodelist(const char* url, NClist** modelistp);
extern int NC_testmode(const char* path, const char* tag);
#endif /*NCRC_H*/

View File

@ -6,19 +6,6 @@
#ifndef NCURI_H
#define NCURI_H
/* Define error codes */
#define NCU_OK (0)
#define NCU_EINVAL (1) /* Generic, mostly means bad argument */
#define NCU_EBADURL (2)
#define NCU_ENOMEM (3)
#define NCU_EPROTO (4)
#define NCU_EPATH (5)
#define NCU_EUSRPWD (6)
#define NCU_EHOST (7)
#define NCU_EPORT (8)
#define NCU_EPARAMS (9)
#define NCU_ENOPARAM (10)
#define NCU_ECONSTRAINTS (11)
/* Define flags to control what is included by ncuribuild*/
#define NCURIPATH 1
@ -79,6 +66,9 @@ extern int ncurisetprotocol(NCURI*,const char* newprotocol);
/* Replace the constraints */
EXTERNL int ncurisetquery(NCURI*,const char* query);
/* Replace the fragment list */
extern int ncurisetfragments(NCURI*, const char* fragments);
/* Construct a complete NC URI; caller frees returned string */
EXTERNL char* ncuribuild(NCURI*,const char* prefix, const char* suffix, int flags);

View File

@ -322,7 +322,7 @@ NCD2_open(const char* path, int mode, int basepe, size_t *chunksizehintp,
dapcomm->oc.rawurltext = strdup(path);
#endif
if(ncuriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url) != NCU_OK)
if(ncuriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url))
{ncstat = NC_EURL; goto done;}
if(!constrainable(dapcomm->oc.url))

View File

@ -65,7 +65,7 @@ NCD4_open(const char * path, int mode,
d4info->controller = (NC*)nc;
/* Parse url and params */
if(ncuriparse(nc->path,&d4info->uri) != NCU_OK)
if(ncuriparse(nc->path,&d4info->uri))
{ret = NC_EDAPURL; goto done;}
/* Load auth info from rc file */

View File

@ -37,7 +37,7 @@ ncd4__testurl(const char* path, char** basenamep)
{
NCURI* uri;
int ok = NC_NOERR;
if(ncuriparse(path,&uri) != NCU_OK)
if(ncuriparse(path,&uri))
ok = NC_EURL;
else {
char* slash = (uri->path == NULL ? NULL : strrchr(uri->path, '/'));

View File

@ -67,9 +67,3 @@ ncsettings.c: $(top_srcdir)/libnetcdf.settings ncsettings.hdr
sed -e 's/\(.*\)/\"\1\\n\"/' | \
cat >> ncsettings.c
echo ';' >> ncsettings.c
# Unit tests
test_ncuri_SOURCES = test_ncuri.c ncuri.c ncbytes.c nclist.c
test_pathcvt_SOURCES = test_pathcvt.c dwinpath.c
check_PROGRAMS = test_ncuri test_pathcvt
TESTS = test_ncuri test_pathcvt

View File

@ -48,7 +48,7 @@ NC_parseproxy(NCauth* auth, const char* surl)
NCURI* uri = NULL;
if(surl == NULL || strlen(surl) == 0)
return (NC_NOERR); /* nothing there*/
if(ncuriparse(surl,&uri) != NCU_OK)
if(ncuriparse(surl,&uri))
return (NC_EURL);
auth->proxy.user = uri->user;
auth->proxy.pwd = uri->password;

View File

@ -1894,7 +1894,7 @@ NC_create(const char *path0, int cmode, size_t initialsz,
}
/* Create the NC* instance and insert its dispatcher and model */
if((stat = new_NC(dispatcher,path,cmode,&model,&ncp))) goto done;
if((stat = new_NC(dispatcher,path,cmode,&ncp))) goto done;
/* Add to list of known open files and define ext_ncid */
add_to_NCList(ncp);
@ -2088,7 +2088,7 @@ NC_open(const char *path0, int omode, int basepe, size_t *chunksizehintp,
if (!dispatcher) {stat = NC_ENOTNC; goto done;}
/* Create the NC* instance and insert its dispatcher */
if((stat = new_NC(dispatcher,path,omode,&model,&ncp))) goto done;
if((stat = new_NC(dispatcher,path,omode,&ncp))) goto done;
/* Add to list of known open files. This assigns an ext_ncid. */
add_to_NCList(ncp);

View File

@ -2,7 +2,7 @@
* @file
*
* Infer as much as possible from the omode + path.
* Possibly rewrite the path.
* Rewrite the path to a canonical form.
*
* Copyright 2018 University Corporation for Atmospheric
* Research/Unidata. See COPYRIGHT file for more info.
@ -42,6 +42,7 @@ file when searching for magic numbers
struct MagicFile {
const char* path;
struct NCURI* uri;
int omode;
NCmodel* model;
fileoffset_t filelen;
int use_parallel;
@ -60,8 +61,9 @@ struct MagicFile {
* H5Fis_hdf5, use the complete HDF5 magic number */
static char HDF5_SIGNATURE[MAGIC_NUMBER_LEN] = "\211HDF\r\n\032\n";
#ifdef DEBUG
#define modelcomplete(model) ((model)->impl != 0)
#ifdef DEBUG
static void dbgflush(void)
{
fflush(stdout);
@ -85,70 +87,48 @@ check(int err)
#define check(err) (err)
#endif
#define modelcomplete(model) ((model)->format != 0 && (model)->iosp != 0 && (model)->impl != 0)
enum mfield {MF, MI, MIO, MV};
/* Wrap model field assignment to fail if the
existing value is not zero and not same as src value
*/
#define conflictset(f,dst,src) do {if((dst) != 0 && (src) != (dst)) {stat=conflictfail(f,(dst),(src)); goto done;} else {(dst) = (src);} } while(0)
/*
Define a table of iosp string values for "mode=".
Includes cases where the impl or format implies the
iosp. Does not includes cases where NC_IOSP_FILE is
the inferred iosp.
*/
static struct IOSPS {
const char* tag;
const int iosp; /* NC_IOSP_XXX value */
} iosps[] = {
{"dap2",NC_IOSP_DAP2},
{"dap4",NC_IOSP_DAP4},
{"bytes",NC_IOSP_HTTP},
{NULL,0}
};
/*
Define a table of "mode=" string values.
Define a table of "mode=" string values
from which the implementation can be inferred.
Note that only cases that can currently
take URLs are included.
*/
static struct FORMATMODES {
const char* tag;
const int format; /* NC_FORMAT_XXX value */
const int impl; /* NC_FORMATX_XXX value */
} formatmodes[] = {
{"dap2",NC_FORMAT_CLASSIC,NC_FORMATX_DAP2},
{"dap4",NC_FORMAT_NETCDF4,NC_FORMATX_DAP4},
{"netcdf-3",NC_FORMAT_CLASSIC,NC_FORMATX_NC3},
{"classic",NC_FORMAT_CLASSIC,NC_FORMATX_NC3},
{"netcdf-4",NC_FORMAT_NETCDF4,NC_FORMATX_NC4},
{"enhanced",NC_FORMAT_NETCDF4,NC_FORMATX_NC4},
{"64bitoffset",NC_FORMAT_64BIT_OFFSET,0},
{"64bitdata",NC_FORMAT_64BIT_DATA,0},
{"cdf5",NC_FORMAT_64BIT_DATA,0}, /*alias*/
#if 0
{"hdf4",NC_FORMAT_HDF4,NC_FORMATX_NC4},
#endif
{NULL,0,0},
{"dap2",NC_FORMATX_DAP2},
{"dap4",NC_FORMATX_DAP4},
{"netcdf-3",NC_FORMATX_NC3},
{"classic",NC_FORMATX_NC3},
{"netcdf-4",NC_FORMATX_NC4},
{"enhanced",NC_FORMATX_NC4},
{"udf0",NC_FORMATX_UDF0},
{"udf1",NC_FORMATX_UDF1},
{"zarr",NC_FORMATX_ZARR},
{NULL,0},
};
/* Define the legal singleton mode tags */
/* Define the legal singleton mode tags;
thse should also appear in the above mode table. */
static const char* modesingles[] = {
"dap2", "dap4", "bytes", "zarr", NULL,
"dap2", "dap4", "bytes", "zarr", NULL
};
/* Map IOSP to readability to get magic number */
static struct IospRead {
int iosp;
/* Map FORMATX to readability to get magic number */
static struct Readable {
int impl;
int readable;
} readable[] = {
{NC_IOSP_FILE,1},
{NC_IOSP_MEMORY,1},
{NC_IOSP_UDF,0},
{NC_IOSP_HTTP,1},
{NC_FORMATX_NC3,1},
{NC_FORMATX_NC_HDF5,1},
{NC_FORMATX_NC_HDF4,1},
{NC_FORMATX_PNETCDF,1},
{NC_FORMATX_DAP2,0},
{NC_FORMATX_DAP4,0},
{NC_FORMATX_UDF0,0},
{NC_FORMATX_UDF1,0},
{NC_FORMATX_ZARR,0},
{0,0},
};
@ -167,12 +147,14 @@ static struct NCPROTOCOLLIST {
};
/* Forward */
static int NC_omodeinfer(int omode, NCmodel*);
static int NC_implinfer(int useparallel, NCmodel* model);
static int NC_dapinfer(NClist*, NCmodel* model);
static int check_file_type(const char *path, int flags, int use_parallel, void *parameters, NCmodel* model, NCURI* uri);
static int NC_omodeinfer(int useparallel, int omode, NCmodel*);
static int check_file_type(const char *path, int omode, int use_parallel, void *parameters, NCmodel* model, NCURI* uri);
static int parseurlmode(const char* modestr, NClist* list);
static int processuri(const char* path, NCURI** urip, char** newpathp, NClist* modeargs);
static int extractiosp(NClist* modeargs, int mode, NCmodel* model);
static char* list2string(NClist* modelist);
static char* envv2string(NClist* envv);
static int issingleton(const char* tag);;
static void set_default_mode(int* cmodep);
static int openmagic(struct MagicFile* file);
static int readmagic(struct MagicFile* file, long pos, char* magic);
@ -181,26 +163,122 @@ static int NC_interpret_magic_number(char* magic, NCmodel* model);
#ifdef DEBUG
static void printmagic(const char* tag, char* magic,struct MagicFile*);
#endif
static int isreadable(int iosp);
static int isreadable(NCmodel*);
/* Report a conflicting model field assignment;
see the conflictset macro above */
/*
If the path looks like a URL, then parse it, reformat it,
and compute the mode= flags. Then return it and the the reformatted path.
*/
static int
conflictfail(enum mfield f, int dst, int src)
processuri(const char* path, NCURI** urip, char** newpathp, NClist* modeargs)
{
const char* sf = NULL;
switch (f) {
case MF: sf = "format"; break;
case MI: sf = "impl"; break;
case MIO: sf = "iosp"; break;
case MV: sf = "version"; break;
default: sf = "?"; break;
int i,j,stat = NC_NOERR;
int found = 0;
const char** fragp = NULL;
NClist* fraglist = NULL;
struct NCPROTOCOLLIST* protolist;
NCURI* uri = NULL;
size_t pathlen = strlen(path);
char* str = NULL;
if(path == NULL || pathlen == 0) {stat = NC_EURL; goto done;}
/* Defaults */
if(newpathp) *newpathp = NULL;
if(urip) *urip = NULL;
if(ncuriparse(path,&uri)) goto done; /* not url */
/* Look up the protocol */
for(found=0,protolist=ncprotolist;protolist->protocol;protolist++) {
if(strcmp(uri->protocol,protolist->protocol) == 0) {
found = 1;
break;
}
}
nclog(NCLOGERR,"Model inference conflict: field=%s dst=%d src=%d", sf,dst,src);
return NC_EINVAL;
if(!found)
{stat = NC_EINVAL; goto done;} /* unrecognized URL form */
/* process the corresponding mode arg */
if(protolist->mode != NULL)
nclistpush(modeargs,strdup(protolist->mode));
/* Substitute the protocol in any case */
if(protolist->substitute) ncurisetprotocol(uri,protolist->substitute);
/* Iterate over the url fragment parameters and collect,
but remove mode= proto= and protocol= */
fraglist = nclistnew();
for(fragp=ncurifragmentparams(uri);fragp && *fragp;fragp+=2) {
int elide = 0;
const char* name = fragp[0];
const char* value = fragp[1];
if(strcmp(name,"protocol")==0
|| strcmp(name,"proto")==0) { /* for back compatibility */
nclistpush(modeargs,strdup(value));
elide = 1;
} else if(strcmp(name,"mode")==0) {
/* Capture the list of mode arguments */
if((stat = parseurlmode(value,modeargs))) goto done;
elide = 1;
} else if(issingleton(name) && (value == NULL || strlen(value)==0)) {
nclistpush(modeargs,strdup(name));
elide = 1;
} /*else ignore*/
if(!elide) {
/* Copy over */
nclistpush(fraglist,strdup(name));
if(value == NULL) value = "";
nclistpush(fraglist,strdup(value));
}
}
/* At this point modeargs should contain all mode-like args from the URL */
/* Remove duplicates */
for(i=nclistlength(modeargs)-1;i>=0;i--) {
const char* mode = nclistget(modeargs,i);
for(j=0;j<i;j++) {
const char* other = nclistget(modeargs,i);
if(strcasecmp(mode,other)==0) {
nclistremove(modeargs,i); /* duplicate */
break;
}
}
}
/* Convert the modelist to a new mode= fragment */
if(nclistlength(modeargs) > 0) {
str = list2string(modeargs);
/* Re-insert mode into fraglist */
nclistinsert(fraglist,0,str);
nclistinsert(fraglist,0,strdup("mode"));
}
/* Convert frag list to a string */
str = envv2string(fraglist);
ncurisetfragments(uri,str);
/* Rebuild the path (including fragment)*/
if(newpathp)
*newpathp = ncuribuild(uri,NULL,NULL,NCURIALL);
if(urip) {
*urip = uri;
uri = NULL;
}
#ifdef DEBUG
fprintf(stderr,"newpath=|%s|\n",*newpathp); fflush(stderr);
#endif
done:
nclistfreeall(fraglist);
nullfree(str);
if(uri != NULL) ncurifree(uri);
return check(stat);
}
/* Parse a mode string at the commas and convert to envv form */
/* Parse a mode string at the commas */
static int
parseurlmode(const char* modestr, NClist* list)
{
@ -230,32 +308,53 @@ done:
return check(stat);
}
/* Given a mode= argument, and the mode flags,
infer the iosp part of the model */
static int
extractiosp(NClist* modeargs, int cmode, NCmodel* model)
/* Convert an envv into a comma'd string*/
static char*
envv2string(NClist* envv)
{
int stat = NC_NOERR;
struct IOSPS* io = iosps;
int i;
NCbytes* buf = NULL;
char* result = NULL;
assert(model->iosp == 0);
for(;io->tag;io++) {
int i;
for(i=0;i<nclistlength(modeargs);i++) {
const char* p = nclistget(modeargs,i);
if(strcmp(p,io->tag)==0) {
conflictset(MIO,model->iosp,io->iosp);
goto done;
}
}
if(envv == NULL || nclistlength(envv) == 0) return NULL;
buf = ncbytesnew();
for(i=0;i<nclistlength(envv);i+=2) {
const char* key = nclistget(envv,i);
const char* val = nclistget(envv,i+1);
if(key == NULL || strlen(key) == 0) continue;
if(val == NULL) val = "";
if(i > 0) ncbytescat(buf,"&");
ncbytescat(buf,key);
ncbytescat(buf,"=");
ncbytescat(buf,val);
}
done:
if(model->iosp == 0)
model->iosp = (fIsSet(cmode,NC_INMEMORY) ? NC_IOSP_MEMORY:NC_IOSP_FILE);
return stat;
result = ncbytesextract(buf);
ncbytesfree(buf);
return result;
}
/* Given a mode= argument, fill in the matching part of the model; except IOSP */
/* Convert a list into a comma'd string */
static char*
list2string(NClist* modelist)
{
int i;
NCbytes* buf = NULL;
char* result = NULL;
if(modelist == NULL || nclistlength(modelist)==0) return NULL;
buf = ncbytesnew();
for(i=0;i<nclistlength(modelist);i++) {
const char* m = nclistget(modelist,i);
if(m == NULL || strlen(m) == 0) continue;
if(i > 0) ncbytescat(buf,",");
ncbytescat(buf,m);
}
result = ncbytesextract(buf);
ncbytesfree(buf);
return result;
}
/* Given a mode= argument, fill in the impl and possibly mode flags */
static int
processmodearg(const char* arg, NCmodel* model)
{
@ -263,11 +362,10 @@ processmodearg(const char* arg, NCmodel* model)
struct FORMATMODES* format = formatmodes;
for(;format->tag;format++) {
if(strcmp(format->tag,arg)==0) {
conflictset(MF,model->format,format->format);
conflictset(MI,model->impl,format->impl);
model->impl = format->impl;
}
}
done:
return check(stat);
}
@ -282,203 +380,93 @@ issingleton(const char* tag)
return 0;
}
/* If we have a url, see if we can determine DAP */
static int
NC_dapinfer(NClist* modeargs, NCmodel* model)
{
int stat = NC_NOERR;
int i;
/* 1. search modeargs for indicators */
for(i=0;i<nclistlength(modeargs);i++) {
const char* arg = nclistget(modeargs,i);
if(strcasecmp(arg,"bytes")==0
|| strcasecmp(arg,"zarr")==0) {
/* Ok, we know this is not DAP, so give up */
return stat;
}
if(strcasecmp(arg,"dap2")==0) {
model->format = NC_FORMAT_NC3;
model->iosp = NC_IOSP_DAP2;
model->impl = NC_FORMATX_DAP2;
} else if(strcasecmp(arg,"dap4")==0) {
model->format = NC_FORMAT_NETCDF4;
model->iosp = NC_IOSP_DAP4;
model->impl = NC_FORMATX_DAP4;
}
}
/* Ok, we have a URL, but no tags to tell us what it is, so assume DAP2 */
if(model->impl == 0) {
model->format = NC_FORMAT_NC3;
model->iosp = NC_IOSP_DAP2;
model->impl = NC_FORMATX_DAP2;
}
return stat;
}
/*
Infer from the mode
Infer from the mode + useparallel
only call if iscreate or file is not easily readable.
*/
static int
NC_omodeinfer(int cmode, NCmodel* model)
NC_omodeinfer(int useparallel, int cmode, NCmodel* model)
{
int stat = NC_NOERR;
/* If no format flags are set, then use default */
if(!fIsSet(cmode,NC_FORMAT_ALL))
conflictset(MF,model->format,nc_get_default_format());
set_default_mode(&cmode);
/* Process the cmode; may override some already set flags */
if(fIsSet(cmode,NC_64BIT_OFFSET)) {
conflictset(MF,model->format,NC_FORMAT_64BIT_OFFSET);
model->impl = NC_FORMATX_NC3;
model->format = NC_FORMAT_64BIT_OFFSET;
goto done;
}
if(fIsSet(cmode,NC_64BIT_DATA)) {
conflictset(MF,model->format,NC_FORMAT_64BIT_DATA);
model->impl = NC_FORMATX_NC3;
model->format = NC_FORMAT_64BIT_DATA;
goto done;
}
if(fIsSet(cmode,NC_NETCDF4)) {
conflictset(MF,model->format,NC_FORMAT_NETCDF4);
model->impl = NC_FORMATX_NC4;
if(fIsSet(cmode,NC_CLASSIC_MODEL))
model->format = NC_FORMAT_NETCDF4_CLASSIC;
else
model->format = NC_FORMAT_NETCDF4;
goto done;
}
if(fIsSet(cmode,(NC_UDF0|NC_UDF1))) {
conflictset(MF,model->format,NC_FORMAT_NETCDF4);
/* For user formats, we must back out some previous decisions */
model->iosp = NC_IOSP_UDF; /* Do not know anything about this */
model->format = NC_FORMAT_NETCDF4;
if(fIsSet(cmode,NC_UDF0)) {
conflictset(MI,model->impl,NC_FORMATX_UDF0);
model->impl = NC_FORMATX_UDF0;
} else {
conflictset(MI,model->impl,NC_FORMATX_UDF1);
model->impl = NC_FORMATX_UDF1;
}
goto done;
}
/* Ignore following flags for now */
#if 0 /* keep lgtm happy */
if(fIsSet(cmode,NC_CLASSIC_MODEL)) {}
if(fIsSet(cmode,NC_DISKLESS)) {}
#endif
/* Default to classic model */
model->format = NC_FORMAT_CLASSIC;
model->impl = NC_FORMATX_NC3;
done:
/* Apply parallel flag */
if(useparallel) {
if(model->impl == NC_FORMATX_NC3)
model->impl = NC_FORMATX_PNETCDF;
}
return check(stat);
}
/* Infer the implementation/dispatcher from format*/
static int
NC_implinfer(int useparallel, NCmodel* model)
/*
If the mode flags do not necessarily specify the
format, then default it by adding in appropriate flags.
*/
static void
set_default_mode(int* modep)
{
int stat = NC_NOERR;
int mode = *modep;
int dfaltformat;
/* If we do not have a format, then use default format */
if(model->format == 0)
conflictset(MF,model->format,nc_get_default_format());
/* Try to infer impl based on format; may modify mode flags */
if(model->impl == 0) {
switch (model->format) {
case NC_FORMAT_NETCDF4:
conflictset(MI,model->impl,NC_FORMATX_NC4);
break;
case NC_FORMAT_NETCDF4_CLASSIC:
conflictset(MI,model->impl,NC_FORMATX_NC4);
break;
case NC_FORMAT_CDF5:
conflictset(MI,model->impl,NC_FORMATX_NC3);
break;
case NC_FORMAT_64BIT_OFFSET:
conflictset(MI,model->impl,NC_FORMATX_NC3);
break;
case NC_FORMAT_CLASSIC:
conflictset(MI,model->impl,NC_FORMATX_NC3);
break;
default: break;
}
/* default dispatcher if above did not infer an implementation */
if (model->impl == 0)
conflictset(MI,model->impl,NC_FORMATX_NC3); /* Final choice */
/* Check for using PNETCDF */
if (model->impl== NC_FORMATX_NC3
&& useparallel
&& model->iosp == NC_IOSP_FILE)
model->impl = NC_FORMATX_PNETCDF; /* Use this instead */
}
assert(model->impl != 0);
done:
return check(stat);
}
static int
processuri(const char* path, NCURI** urip, char** newpathp, NClist* modeargs)
{
int stat = NC_NOERR;
int found = 0;
const char** fragp = NULL;
struct NCPROTOCOLLIST* protolist;
NCURI* uri = NULL;
size_t pathlen = strlen(path);
if(path == NULL || pathlen == 0) {stat = NC_EURL; goto done;}
/* Defaults */
if(newpathp) *newpathp = NULL;
if(urip) *urip = NULL;
if(ncuriparse(path,&uri) != NCU_OK) goto done; /* not url */
/* Look up the protocol */
for(found=0,protolist=ncprotolist;protolist->protocol;protolist++) {
if(strcmp(uri->protocol,protolist->protocol) == 0) {
found = 1;
break;
}
}
if(!found)
{stat = NC_EINVAL; goto done;} /* unrecognized URL form */
/* process the corresponding mode arg */
if(protolist->mode != NULL)
nclistpush(modeargs,strdup(protolist->mode));
/* Substitute the protocol in any case */
if(protolist->substitute) ncurisetprotocol(uri,protolist->substitute);
/* Iterate over the url fragment parameters */
for(fragp=ncurifragmentparams(uri);fragp && *fragp;fragp+=2) {
const char* name = fragp[0];
const char* value = fragp[1];
if(strcmp(name,"protocol")==0) {
nclistpush(modeargs,strdup(value));
} else
if(strcmp(name,"mode")==0) {
if((stat = parseurlmode(value,modeargs))) goto done;
} else
if(issingleton(name) && (value == NULL || strlen(value)==0)) {
nclistpush(modeargs,strdup(name));
} /*else ignore*/
}
/* At this point modeargs should contain all mode args from the URL */
/* Rebuild the path (including fragment)*/
if(newpathp)
*newpathp = ncuribuild(uri,NULL,NULL,NCURIALL);
if(urip) {
*urip = uri;
uri = NULL;
}
done:
if(uri != NULL) ncurifree(uri);
return check(stat);
dfaltformat = nc_get_default_format();
switch (dfaltformat) {
case NC_FORMAT_64BIT_OFFSET: mode |= NC_64BIT_OFFSET; break;
case NC_FORMAT_64BIT_DATA: mode |= NC_64BIT_DATA; break;
case NC_FORMAT_NETCDF4: mode |= NC_NETCDF4; break;
case NC_FORMAT_NETCDF4_CLASSIC: mode |= (NC_NETCDF4|NC_CLASSIC_MODEL); break;
case NC_FORMAT_CLASSIC: /* fall thru */
default: break; /* default to classic */
}
*modep = mode; /* final result */
}
/**************************************************/
/*
Infer model for this dataset using some
combination of cmode, path, and reading the dataset.
The precedence order is:
1. file contents -- highest precedence
2. path
2. isurl -- check for DAP
3. mode
4. default format -- lowest precedence
See the documentation in docs/internal.dox.
@param path
@param omode
@ -493,56 +481,54 @@ done:
int
NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void* params, NCmodel* model, char** newpathp)
{
int stat = NC_NOERR;
int i,stat = NC_NOERR;
char* newpath = NULL;
NCURI* uri = NULL;
int omode = *omodep;
int isuri = 0;
NClist* modeargs = nclistnew();
/* Phase 1: Reformat the uri to canonical form; store canonical form
into newpath. Return the "mode=" list in modeargs */
if((stat = processuri(path, &uri, &newpath, modeargs))) goto done;
isuri = (uri != NULL);
if(newpath == NULL) newpath = strdup(path); /* No change */
/* Phase 1: compute the IOSP */
if((stat = extractiosp(modeargs,omode,model))) goto done;
assert(model->iosp != 0);
/* Phase 2: Process the non-iosp mode arguments */
if(!modelcomplete(model) && isuri) {
int i;
for(i=0;i<nclistlength(modeargs);i++) {
const char* arg = nclistget(modeargs,i);
if((stat=processmodearg(arg,model))) goto done;
}
/* Phase 2: Process the modeargs list to see if we can tell the formatx */
/* Note that if the path was not a URL, then modeargs will be empty list*/
for(i=0;i<nclistlength(modeargs);i++) {
const char* arg = nclistget(modeargs,i);
if((stat=processmodearg(arg,model))) goto done;
}
/* Phase 3: See if we can infer DAP */
if(!modelcomplete(model) && isuri) {
if((stat = NC_dapinfer(modeargs,model))) goto done;
/* Phase 2.5: Special case: if this is a URL, and there are no mode args
and model.impl is still not defined, default to DAP2 */
if(uri != NULL && nclistlength(modeargs) == 0 && !modelcomplete(model)) {
model->impl = NC_FORMATX_DAP2;
model->format = NC_FORMAT_NC3;
}
/* Phase 4: mode inference */
/* Phase 3: mode inference from mode flags */
/* The modeargs did not give us a model (probably not a URL).
So look at the combination of mode flags and the useparallel flag */
if(!modelcomplete(model)) {
if((stat = NC_omodeinfer(omode,model))) goto done;
if((stat = NC_omodeinfer(useparallel,omode,model))) goto done;
}
/* Phase 5: Infer from file content, if possible;
/* Phase 4: Infer from file content, if possible;
this has highest precedence, so it may override
previous decisions.
previous decisions. Note that we do this last
because we need previously determined model info
to guess if this file is readable.
*/
if(!iscreate && isreadable(model->iosp)) {
if(!iscreate && isreadable(model)) {
/* Ok, we need to try to read the file */
if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done;
}
/* Phase 6: Infer impl from format */
if(!modelcomplete(model)) {
if((stat = NC_implinfer(useparallel, model))) goto done;
}
/* Need a decision */
if(!modelcomplete(model))
{stat = NC_ENOTNC; goto done;}
assert(modelcomplete(model));
/* Force flag consistency */
/* Force flag consistency */
switch (model->impl) {
case NC_FORMATX_NC4:
case NC_FORMATX_NC_HDF4:
@ -553,9 +539,6 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void
if(model->format == NC_FORMAT_NETCDF4_CLASSIC)
omode |= NC_CLASSIC_MODEL;
break;
case NC_FORMATX_DAP2:
omode &= ~(NC_NETCDF4|NC_64BIT_OFFSET|NC_64BIT_DATA);
break;
case NC_FORMATX_NC3:
omode &= ~NC_NETCDF4; /* must be netcdf-3 (CDF-1, CDF-2, CDF-5) */
if(model->format == NC_FORMAT_64BIT_OFFSET) omode |= NC_64BIT_OFFSET;
@ -566,6 +549,9 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void
if(model->format == NC_FORMAT_64BIT_OFFSET) omode |= NC_64BIT_OFFSET;
else if(model->format == NC_FORMAT_64BIT_DATA) omode |= NC_64BIT_DATA;
break;
case NC_FORMATX_DAP2:
omode &= ~(NC_NETCDF4|NC_64BIT_OFFSET|NC_64BIT_DATA|NC_CLASSIC_MODEL);
break;
default:
{stat = NC_ENOTNC; goto done;}
}
@ -580,12 +566,12 @@ done:
}
static int
isreadable(int iosp)
isreadable(NCmodel* model)
{
struct IospRead* r;
struct Readable* r;
/* Look up the protocol */
for(r=readable;r->iosp;r++) {
if(iosp == r->iosp) return r->readable;
for(r=readable;r->impl;r++) {
if(model->impl == r->impl) return r->readable;
}
return 0;
}
@ -633,7 +619,7 @@ nc__testurl(const char* path, char** basenamep)
{
NCURI* uri;
int ok = 0;
if(ncuriparse(path,&uri) == NCU_OK) {
if(!ncuriparse(path,&uri)) {
char* slash = (uri->path == NULL ? NULL : strrchr(uri->path, '/'));
char* dot;
if(slash == NULL) slash = (char*)path; else slash++;
@ -653,6 +639,8 @@ nc__testurl(const char* path, char** basenamep)
return ok;
}
/**************************************************/
/**
* @internal Given an existing file, figure out its format and return
@ -670,7 +658,7 @@ nc__testurl(const char* path, char** basenamep)
* @author Dennis Heimbigner
*/
static int
check_file_type(const char *path, int flags, int use_parallel,
check_file_type(const char *path, int omode, int use_parallel,
void *parameters, NCmodel* model, NCURI* uri)
{
char magic[NC_MAX_MAGIC_NUMBER_LEN];
@ -680,6 +668,7 @@ check_file_type(const char *path, int flags, int use_parallel,
memset((void*)&magicinfo,0,sizeof(magicinfo));
magicinfo.path = path; /* do not free */
magicinfo.uri = uri; /* do not free */
magicinfo.omode = omode;
magicinfo.model = model; /* do not free */
magicinfo.parameters = parameters; /* do not free */
#ifdef USE_STDIO
@ -738,14 +727,19 @@ openmagic(struct MagicFile* file)
{
int status = NC_NOERR;
switch (file->model->iosp) {
case NC_IOSP_MEMORY: {
if(fIsSet(file->omode,NC_INMEMORY)) {
/* Get its length */
NC_memio* meminfo = (NC_memio*)file->parameters;
assert(meminfo != NULL);
file->filelen = (long long)meminfo->size;
} break;
case NC_IOSP_FILE: {
#ifdef ENABLE_BYTERANGE
} else if(file->uri != NULL) {
/* Construct a URL minus any fragment */
file->curlurl = ncuribuild(file->uri,NULL,NULL,NCURISVC);
/* Open the curl handle */
if((status=nc_http_open(file->curlurl,&file->curl,&file->filelen))) goto done;
#endif
} else {
#ifdef USE_PARALLEL
if (file->use_parallel) {
int retval;
@ -804,20 +798,7 @@ openmagic(struct MagicFile* file)
}
rewind(file->fp);
}
} break;
#ifdef ENABLE_BYTERANGE
case NC_IOSP_HTTP: {
/* Construct a URL minus any fragment */
file->curlurl = ncuribuild(file->uri,NULL,NULL,NCURISVC);
/* Open the curl handle */
if((status=nc_http_open(file->curlurl,&file->curl,&file->filelen))) goto done;
} break;
#endif
default: assert(0);
}
done:
return check(status);
}
@ -827,8 +808,7 @@ readmagic(struct MagicFile* file, long pos, char* magic)
{
int status = NC_NOERR;
memset(magic,0,MAGIC_NUMBER_LEN);
switch (file->model->iosp) {
case NC_IOSP_MEMORY: {
if(fIsSet(file->omode,NC_INMEMORY)) {
char* mempos;
NC_memio* meminfo = (NC_memio*)file->parameters;
if((pos + MAGIC_NUMBER_LEN) > meminfo->size)
@ -838,9 +818,21 @@ readmagic(struct MagicFile* file, long pos, char* magic)
#ifdef DEBUG
printmagic("XXX: readmagic",magic,file);
#endif
} break;
case NC_IOSP_FILE:
#ifdef ENABLE_BYTERANGE
} else if(file->uri != NULL) {
NCbytes* buf = ncbytesnew();
fileoffset_t start = (size_t)pos;
fileoffset_t count = MAGIC_NUMBER_LEN;
status = nc_http_read(file->curl,file->curlurl,start,count,buf);
if(status == NC_NOERR) {
if(ncbyteslength(buf) != count)
status = NC_EINVAL;
else
memcpy(magic,ncbytescontents(buf),count);
}
ncbytesfree(buf);
#endif
} else {
#ifdef USE_PARALLEL
if (file->use_parallel) {
MPI_Status mstatus;
@ -862,25 +854,6 @@ readmagic(struct MagicFile* file, long pos, char* magic)
i += count;
}
}
break;
#ifdef ENABLE_BYTERANGE
case NC_IOSP_HTTP: {
NCbytes* buf = ncbytesnew();
fileoffset_t start = (size_t)pos;
fileoffset_t count = MAGIC_NUMBER_LEN;
status = nc_http_read(file->curl,file->curlurl,start,count,buf);
if(status == NC_NOERR) {
if(ncbyteslength(buf) != count)
status = NC_EINVAL;
else
memcpy(magic,ncbytescontents(buf),count);
}
ncbytesfree(buf);
} break;
#endif
default: assert(0);
}
done:
@ -901,11 +874,14 @@ static int
closemagic(struct MagicFile* file)
{
int status = NC_NOERR;
switch (file->model->iosp) {
case NC_IOSP_MEMORY:
break; /* noop */
case NC_IOSP_FILE:
if(fIsSet(file->omode,NC_INMEMORY)) {
/* noop */
#ifdef ENABLE_BYTERANGE
} else if(file->uri != NULL) {
status = nc_http_close(file->curl);
nullfree(file->curlurl);
#endif
} else {
#ifdef USE_PARALLEL
if (file->use_parallel) {
int retval;
@ -916,18 +892,7 @@ closemagic(struct MagicFile* file)
{
if(file->fp) fclose(file->fp);
}
break;
#ifdef ENABLE_BYTERANGE
case NC_IOSP_HTTP:
status = nc_http_close(file->curl);
nullfree(file->curlurl);
break;
#endif
default: assert(0);
}
return status;
}

View File

@ -329,7 +329,7 @@ rccompile(const char* path)
*rtag = '\0';
/* compile the url and pull out the host */
if(uri) ncurifree(uri);
if(ncuriparse(url,&uri) != NCU_OK) {
if(ncuriparse(url,&uri)) {
nclog(NCLOGERR, "Malformed [url] in %s entry: %s",path,line);
free(triple);
continue;

View File

@ -22,6 +22,7 @@
#include "netcdf.h"
#include "ncuri.h"
#include "ncbytes.h"
#include "nclist.h"
#include "nclog.h"
#include "ncwinpath.h"
@ -45,7 +46,7 @@ NC__testurl(const char* path, char** basenamep)
{
NCURI* uri;
int ok = NC_NOERR;
if(ncuriparse(path,&uri) != NCU_OK)
if(ncuriparse(path,&uri))
ok = NC_EURL;
else {
char* slash = (uri->path == NULL ? NULL : strrchr(uri->path, '/'));
@ -281,3 +282,72 @@ done:
return ret;
}
/*
Parse a path as a url and extract the modelist.
If the path is not a URL, then return a NULL list.
If a URL, but modelist is empty or does not exist,
then return empty list.
*/
int
NC_getmodelist(const char* path, NClist** modelistp)
{
int stat=NC_NOERR;
NClist* modelist = NULL;
NCURI* uri = NULL;
const char* modestr = NULL;
const char* p = NULL;
const char* endp = NULL;
ncuriparse(path,&uri);
if(uri == NULL) goto done; /* not a uri */
/* Get the mode= arg from the fragment */
modelist = nclistnew();
modestr = ncurilookup(uri,"mode");
if(modestr == NULL || strlen(modestr) == 0) goto done;
/* Parse the mode string at the commas or EOL */
p = modestr;
for(;;) {
char* s;
ptrdiff_t slen;
endp = strchr(p,',');
if(endp == NULL) endp = p + strlen(p);
slen = (endp - p);
if((s = malloc(slen+1)) == NULL) {stat = NC_ENOMEM; goto done;}
memcpy(s,p,slen);
s[slen] = '\0';
nclistpush(modelist,s);
if(*endp == '\0') break;
p = endp+1;
}
done:
if(stat == NC_NOERR) {
if(modelistp) {*modelistp = modelist; modelist = NULL;}
}
ncurifree(uri);
nclistfree(modelist);
return stat;
}
/*
Check "mode=" list for a path and return 1 if present, 0 otherwise.
*/
int
NC_testmode(const char* path, const char* tag)
{
int stat = NC_NOERR;
int found = 0;
int i;
NClist* modelist = NULL;
if((stat = NC_getmodelist(path, &modelist))) goto done;
for(i=0;i<nclistlength(modelist);i++) {
const char* value = nclistget(modelist,i);
if(strcasecmp(tag,value)==0) {found = 1; break;}
}
done:
nclistfree(modelist);
return found;
}

View File

@ -59,8 +59,6 @@ free_NC(NC *ncp)
return;
if(ncp->path)
free(ncp->path);
if(ncp->model)
free(ncp->model);
/* We assume caller has already cleaned up ncp->dispatchdata */
free(ncp);
}
@ -81,17 +79,13 @@ free_NC(NC *ncp)
* @author Glenn Davis, Dennis Heimbigner
*/
int
new_NC(const NC_Dispatch* dispatcher, const char* path, int mode,
NCmodel* model, NC** ncpp)
new_NC(const NC_Dispatch* dispatcher, const char* path, int mode, NC** ncpp)
{
NC *ncp = (NC*)calloc(1,sizeof(NC));
if(ncp == NULL) return NC_ENOMEM;
ncp->dispatch = dispatcher;
ncp->path = nulldup(path);
ncp->mode = mode;
if((ncp->model = malloc(sizeof(NCmodel)))==NULL)
return NC_ENOMEM;
*ncp->model = *model; /* Make a copy */
if(ncp->path == NULL) { /* fail */
free_NC(ncp);
return NC_ENOMEM;

View File

@ -170,6 +170,7 @@ NC *
find_in_NCList(int ext_ncid)
{
NC* f = NULL;
/* Discard the first two bytes of ext_ncid to get ncid. */
unsigned int ncid = ((unsigned int)ext_ncid) >> ID_SHIFT;
@ -186,7 +187,8 @@ find_in_NCList(int ext_ncid)
* last two bytes) must be zero. If not, then return NULL, which
* will eventually lead to an NC_EBADID error being returned to
* user. */
if (f != NULL && f->model->impl == NC_FORMATX_NC3 && (ext_ncid % (1<<ID_SHIFT)))
if (f != NULL && f->dispatch != NULL
&& f->dispatch->model == NC_FORMATX_NC3 && (ext_ncid % (1<<ID_SHIFT)))
return NULL;
return f;

View File

@ -88,7 +88,7 @@ static void freestringlist(NClist* list);
static void freestringvec(char** list);
static int ncfind(char** params, const char* key);
static char* nclocate(char* p, const char* charlist);
static int parselist(char* ptext, NClist* list);
static int parselist(const char* ptext, NClist* list);
/**************************************************/
/*
@ -112,11 +112,11 @@ IMPORTANT: the client parameter string is assumed to have blanks compressed out.
/**************************************************/
/* Do a simple uri parse: return NCU_OK if success, NCU_XXX if failed */
/* Do a simple uri parse: return NC_NOERR if success, NC_EXXX if failed */
int
ncuriparse(const char* uri0, NCURI** durip)
{
int ret = NCU_OK;
int ret = NC_NOERR;
NCURI tmp;
char* p;
char* q;
@ -132,11 +132,11 @@ ncuriparse(const char* uri0, NCURI** durip)
int pathchar;
if(uri0 == NULL)
{THROW(NCU_EBADURL);}
{THROW(NC_EURL);}
len0 = strlen(uri0);
if(len0 == 0)
{THROW(NCU_EBADURL);}
{THROW(NC_EURL);}
/* Create a local NCURI instance to hold
pointers into the parsed string
@ -149,7 +149,7 @@ ncuriparse(const char* uri0, NCURI** durip)
*/
uri = (char*)malloc(len0+1+1); /* +2 for nul term and for host section terminator */
if(uri == NULL)
{THROW(NCU_ENOMEM);}
{THROW(NC_ENOMEM);}
strncpy(uri,uri0,len0+1);
/* Walk the uri and do the following:
@ -166,8 +166,8 @@ ncuriparse(const char* uri0, NCURI** durip)
if(*p == LBRACKET) {
prefix = p;
ret = collectprefixparams(p,&next); /* collect the prefix */
if(ret != NCU_OK)
{THROW(NCU_EBADURL);}
if(ret != NC_NOERR)
{THROW(NC_EURL);}
p = next;
} else {
prefix = NULL;
@ -196,13 +196,13 @@ ncuriparse(const char* uri0, NCURI** durip)
/* Parse the prefix parameters */
if(prefix != NULL) {
if(parselist(prefix,params) != NCU_OK)
{THROW(NCU_EBADURL);}
if(parselist(prefix,params) != NC_NOERR)
{THROW(NC_EURL);}
}
/* Parse the fragment parameters */
if(tmp.fragment != NULL) {
if(parselist(tmp.fragment,params) != NCU_OK)
{THROW(NCU_EBADURL);}
if(parselist(tmp.fragment,params) != NC_NOERR)
{THROW(NC_EURL);}
}
if(nclistlength(params) > 0) {
nclistpush(params,NULL);
@ -211,8 +211,8 @@ ncuriparse(const char* uri0, NCURI** durip)
tmp.fraglist = NULL;
/* Parse the query */
if(tmp.query != NULL) {
if(parselist(tmp.query,querylist) != NCU_OK)
{THROW(NCU_EBADURL);}
if(parselist(tmp.query,querylist) != NC_NOERR)
{THROW(NC_EURL);}
if(nclistlength(querylist) > 0) {
nclistpush(querylist,NULL);
tmp.querylist = nclistextract(querylist);
@ -226,11 +226,11 @@ ncuriparse(const char* uri0, NCURI** durip)
tmp.protocol = p;
p = strchr(p,':');
if(!p)
{THROW(NCU_EBADURL);}
{THROW(NC_EURL);}
terminate(p); /*overwrite colon*/
p++; /* skip the colon */
if(strlen(tmp.protocol)==0)
{THROW(NCU_EBADURL);}
{THROW(NC_EURL);}
/*
The legal formats for file: urls are a problem since
many variants are often accepted.
@ -242,18 +242,23 @@ ncuriparse(const char* uri0, NCURI** durip)
the format: file:/path.
We also simplify things by assuming the host part is always empty.
which means we can have file:///path, but not file://..../path.
Note in all cases, the leading '/' is considered part of the path,
Note also in all cases, the leading '/' is considered part of the path,
which is then assumed to be an absolute path. But also note that
the windows drive letter has to be taken into account. Our rule is that
if the path looks like D:...,
where D is a single alphabetic letter (a-z or A-Z),
then it is a windows path and can be use in place of a /path.
Note also that it is desirable to support relative paths even
though the RFC technically does not allow this. This will occur
if the form is file://path where path does not start with '/'.
The rules implemented here (for file:) are then as follows
1. file:D:... : assume D: is a windows drive letter and treat D:... as the path
2. file:/X, where X does not start with a slash: treat /X as the path.
3. file://D:... : assume D: is a windows drive letter and treat as the path
4. file:///X, where X does not start with a slash: treat /X as the path.
All other cases are disallowed: specifically including file://X.
5. file://X, where X does not start with a slash: treat X as the
relative path.
All other cases are disallowed.
*/
isfile = (strcmp(tmp.protocol,"file")==0);
@ -269,11 +274,13 @@ ncuriparse(const char* uri0, NCURI** durip)
p = p+2; /* points to the start of the windows path */
} else if(l >= 4 && p[0] == '/' && p[1] == '/' && p[2] == '/' && p[3] != '/') { /* case 4 */
p += 2; /* points to the start of the path */
} else if(l >= 4 && p[0] == '/' && p[1] == '/' && p[2] != '/') { /* case 5 */
p += 2; /* points to the start of the path */
} else /* everything else is illegal */
{THROW(NCU_EPATH);}
{THROW(NC_EACCESS);}
} else {
if(p[0] != '/' || p[1] != '/') /* must be proto:// */
{THROW(NCU_EPATH);}
{THROW(NC_EACCESS);}
p += 2;
hashost = 1; /* Assume we have a hostname */
}
@ -305,20 +312,20 @@ ncuriparse(const char* uri0, NCURI** durip)
char* newhost = strchr(tmp.host,'@');
if(newhost != NULL) {
if(newhost == tmp.host)
{THROW(NCU_EUSRPWD);} /* we have proto://@ */
{THROW(NC_EURL);} /* we have proto://@ */
terminate(newhost); /* overwrite '@' */
newhost++; /* should point past usr+pwd */
tmp.user = tmp.host;
/* Break user+pwd into two pieces */
pp = strchr(tmp.user,':');
if(pp == NULL)
{THROW(NCU_EUSRPWD);} /* we have user only */
{THROW(NC_EURL);} /* we have user only */
terminate(pp); /* overwrite ':' */
pp++;
if(strlen(tmp.user)==0)
{THROW(NCU_EUSRPWD);} /* we have empty user */
{THROW(NC_EURL);} /* we have empty user */
if(strlen(pp)==0)
{THROW(NCU_EUSRPWD);} /* we have empty password */
{THROW(NC_EURL);} /* we have empty password */
tmp.password = pp;
tmp.host = newhost;
}
@ -329,14 +336,14 @@ ncuriparse(const char* uri0, NCURI** durip)
terminate(pp); /* overwrite ':' */
pp++; /* skip colon */
if(strlen(tmp.host) == 0)
{THROW(NCU_EBADURL);} /* empty host */
{THROW(NC_EURL);} /* empty host */
if(strlen(pp)==0)
{THROW(NCU_EBADURL);} /* empty port */
{THROW(NC_EURL);} /* empty port */
tmp.port = pp;
/* The port must look something like a number */
for(pp=tmp.port;*pp;pp++) {
if(strchr("0123456789-",*pp) == NULL)
{THROW(NCU_EPORT);} /* probably not a real port, fail */
{THROW(NC_EURL);} /* probably not a real port, fail */
}
} /* else no port */
}
@ -344,7 +351,7 @@ ncuriparse(const char* uri0, NCURI** durip)
/* Fill in duri from tmp */
duri = (NCURI*)calloc(1,sizeof(NCURI));
if(duri == NULL)
{THROW(NCU_ENOMEM);}
{THROW(NC_ENOMEM);}
/* save original uri */
duri->uri = strdup(uri0);
duri->protocol = nulldup(tmp.protocol);
@ -446,14 +453,14 @@ ncurisetprotocol(NCURI* duri,const char* protocol)
{
nullfree(duri->protocol);
duri->protocol = strdup(protocol);
return (NCU_OK);
return (NC_NOERR);
}
/* Replace the query */
int
ncurisetquery(NCURI* duri,const char* query)
{
int ret = NCU_OK;
int ret = NC_NOERR;
freestringvec(duri->querylist);
nullfree(duri->query);
duri->query = NULL;
@ -462,7 +469,7 @@ ncurisetquery(NCURI* duri,const char* query)
NClist* params = nclistnew();
duri->query = strdup(query);
ret = parselist(duri->query,params);
if(ret != NCU_OK)
if(ret != NC_NOERR)
{THROW(NC_EURL);}
nclistpush(params,NULL);
duri->querylist = nclistextract(params);
@ -472,6 +479,29 @@ done:
return ret;
}
/* Replace the fragments*/
int
ncurisetfragments(NCURI* duri,const char* fragments)
{
int ret = NC_NOERR;
freestringvec(duri->fraglist);
nullfree(duri->fragment);
duri->fragment = NULL;
duri->fraglist = NULL;
if(fragments != NULL && strlen(fragments) > 0) {
NClist* params = nclistnew();
duri->fragment = strdup(fragments);
ret = parselist(duri->fragment,params);
if(ret != NC_NOERR)
{THROW(NC_EURL);}
nclistpush(params,NULL);
duri->fraglist = nclistextract(params);
nclistfree(params);
}
done:
return ret;
}
#if 0
/* Replace the constraints */
int
@ -488,7 +518,7 @@ ncurisetconstraints(NCURI* duri,const char* constraints)
duri->projection = NULL;
duri->selection = NULL;
if(constraints == NULL || strlen(constraints)==0) return (NCU_ECONSTRAINTS);
if(constraints == NULL || strlen(constraints)==0) return (NC_ECONSTRAINTS);
duri->constraint = nulldup(constraints);
if(*duri->constraint == '?')
@ -513,7 +543,7 @@ ncurisetconstraints(NCURI* duri,const char* constraints)
}
duri->projection = proj;
duri->selection = select;
return NCU_OK;
return NC_NOERR;
}
#endif
@ -664,7 +694,7 @@ ncuriremoveparam(NCURI* uri, const char* key)
char** p;
char** q = NULL;
if(uri->fraglist == NULL) return NCU_OK;
if(uri->fraglist == NULL) return NC_NOERR;
for(q=uri->fraglist,p=uri->fraglist;*p;) {
if(strcmp(key,*p)==0) {
p += 2; /* skip this entry */
@ -673,7 +703,7 @@ ncuriremoveparam(NCURI* uri, const char* key)
*q++ = *p++; /* move value */
}
}
return NCU_OK;
return NC_NOERR;
}
#endif
@ -899,15 +929,15 @@ ncuridecodepartial(char* s, const char* decodeset)
static int
collectprefixparams(char* text, char** nextp)
{
int ret = NCU_OK;
int ret = NC_NOERR;
char* sp;
char* ep;
char* last;
if(text == NULL) return NCU_EBADURL;
if(text == NULL) return NC_EURL;
if(strlen(text) == 0) {
if(nextp) *nextp = text;
return NCU_OK;
return NC_NOERR;
}
/* pass 1: locate last rbracket and nul term the prefix */
sp = text;
@ -919,7 +949,7 @@ collectprefixparams(char* text, char** nextp)
}
/* use nclocate because \\ escapes might be present */
ep = nclocate(sp,RBRACKETSTR);
if(ep == NULL) {ret = NCU_EPARAMS; goto done;} /* malformed */
if(ep == NULL) {ret = NC_EINVAL; goto done;} /* malformed */
last = ep; /* save this position */
ep++; /* move past rbracket */
sp = ep;
@ -948,10 +978,12 @@ done:
}
static int
parselist(char* ptext, NClist* list)
parselist(const char* text, NClist* list)
{
int ret = NCU_OK;
int ret = NC_NOERR;
char* ptext = NULL;
char* p;
ptext = strdup(text); /* We need to modify */
p = ptext; /* start of next parameter */
for(;;) {
char* sp = p;
@ -981,5 +1013,6 @@ parselist(char* ptext, NClist* list)
if(ep == NULL)
break;
}
nullfree(ptext);
return ret;
}

View File

@ -655,7 +655,7 @@ nc4_open_file(const char *path, int mode, void* parameters, int ncid)
/* Find pointer to NC. */
if ((retval = NC_check_id(ncid, &nc)))
return retval;
assert(nc && nc->model->impl == NC_FORMATX_NC4);
assert(nc);
/* Determine the HDF5 open flag to use. */
flags = (mode & NC_WRITE) ? H5F_ACC_RDWR : H5F_ACC_RDONLY;
@ -678,7 +678,7 @@ nc4_open_file(const char *path, int mode, void* parameters, int ncid)
#ifdef ENABLE_BYTERANGE
/* See if we want the byte range protocol */
if(nc->model->iosp == NC_IOSP_HTTP) {
if(NC_testmode(path,"bytes")) {
h5->http.iosp = 1;
/* Kill off any conflicting modes flags */
mode &= ~(NC_WRITE|NC_DISKLESS|NC_PERSIST|NC_INMEMORY);

View File

@ -18,6 +18,7 @@
#include "netcdf_mem.h"
#include "rnd.h"
#include "ncx.h"
#include "ncrc.h"
/* These have to do with version numbers. */
#define MAGIC_NUM_LEN 4
@ -1175,7 +1176,7 @@ NC3_open(const char *path, int ioflags, int basepe, size_t *chunksizehintp,
/* If the model specified the use of byte-ranges, then signal by
a temporary hack using one of the flags in the ioflags.
*/
if(nc->model->iosp == NC_IOSP_HTTP)
if(NC_testmode(path,"bytes"))
ioflags |= NC_HTTP;
#endif /*ENABLE_BYTERANGE*/

View File

@ -544,39 +544,42 @@ H5Z_filter_reg(unsigned int flags, size_t cd_nelmts,
fprintf(stderr,"nbytes=%ld\n",(long)nbytes);
if (flags & H5Z_FLAG_REVERSE) {
/* Replace buffer */
#ifdef HDF5_HAS_ALLOCATE_MEMORY
#ifdef HAVE_H5ALLOCATE_MEMORY
newbuf = H5allocate_memory(*buf_size,0);
#else
newbuf = malloc(*buf_size * sizeof(void));
newbuf = malloc(*buf_size);
#endif
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);
/* reclaim old buffer */
#ifdef HDF5_HAS_H5FREE
H5free_memory(*buf);
if(*buf != NULL) {
memcpy(newbuf,*buf,*buf_size);
/* reclaim old buffer */
#ifdef HAVE_H5FREE_MEMORY
H5free_memory(*buf);
#else
free(*buf);
free(*buf);
#endif
}
*buf = newbuf;
} else {
/* Replace buffer */
#ifdef HDF5_HAS_ALLOCATE_MEMORY
newbuf = H5allocate_memory(*buf_size,0);
#ifdef HAVE_H5ALLOCATE_MEMORY
newbuf = H5allocate_memory(*buf_size,0);
#else
newbuf = malloc(*buf_size * sizeof(void));
newbuf = malloc(*buf_size);
#endif
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);
/* reclaim old buffer */
#ifdef HDF5_HAS_H5FREE
H5free_memory(*buf);
if(newbuf == NULL) abort();
if(*buf != NULL) {
memcpy(newbuf,*buf,*buf_size);
/* reclaim old buffer */
#ifdef HAVE_H5FREE_MEMORY
H5free_memory(*buf);
#else
free(*buf);
free(*buf);
#endif
}
*buf = newbuf;
}

View File

@ -303,7 +303,7 @@ main(int argc, char **argv)
}
/* Compile the url */
if(ncuriparse(ocopt.surl,&ocopt.url) != NCU_OK) {
if(ncuriparse(ocopt.surl,&ocopt.url)) {
fprintf(stderr,"malformed source url: %s\n",ocopt.surl);
exit(1);
}
@ -346,7 +346,7 @@ main(int argc, char **argv)
ocopt.surl = ncuribuild(ocopt.url,NULL,NULL,NCURIALL);
/* Reparse */
if(ncuriparse(ocopt.surl,&ocopt.url) != NCU_OK) {
if(ncuriparse(ocopt.surl,&ocopt.url)) {
fprintf(stderr,"malformed source url: %s\n",ocopt.surl);
exit(1);
}

View File

@ -99,7 +99,7 @@ ocopen(OCstate** statep, const char* url)
if(!ocinitialized)
ocinternalinitialize();
if(ncuriparse(url,&tmpurl) != NCU_OK) {
if(ncuriparse(url,&tmpurl)) {
OCTHROWCHK(stat=OC_EBADURL);
goto fail;
}

View File

@ -122,7 +122,7 @@ H5Z_filter_test(unsigned int flags, size_t cd_nelmts,
#ifdef HAVE_H5ALLOCATE_MEMORY
newbuf = H5allocate_memory(*buf_size,0);
#else
newbuf = malloc(*buf_size * sizeof(void));
newbuf = malloc(*buf_size);
#endif
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);
@ -140,7 +140,7 @@ H5Z_filter_test(unsigned int flags, size_t cd_nelmts,
#ifdef HAVE_H5ALLOCATE_MEMORY
newbuf = H5allocate_memory(*buf_size,0);
#else
newbuf = malloc(*buf_size * sizeof(void));
newbuf = malloc(*buf_size);
#endif
if(newbuf == NULL) abort();
memcpy(newbuf,*buf,*buf_size);

View File

@ -18,8 +18,8 @@ if USE_NETCDF4
NC4_TESTS = tst_nc4internal
endif # USE_NETCDF4
check_PROGRAMS = tst_nclist $(NC4_TESTS)
TESTS = tst_nclist $(NC4_TESTS)
check_PROGRAMS = tst_nclist test_ncuri test_pathcvt $(NC4_TESTS)
TESTS = tst_nclist test_ncuri test_pathcvt $(NC4_TESTS)
EXTRA_DIST = CMakeLists.txt

View File

@ -10,6 +10,7 @@ Test the ncuri parsing
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "netcdf.h"
#include "ncuri.h"
typedef struct Test {
@ -42,12 +43,12 @@ static Test TESTS[] = {
{"http://localhost","http://localhost/"},
{"http:///x","http:///x"},
{"file:///home/osboxes/git/dap4/dap4_test/daptestfiles/test_anon_dim.2.syn#dap4&debug=copy&substratename=./results/test_anon_dim.2.syn.nc","file:///home/osboxes/git/dap4/dap4_test/daptestfiles/test_anon_dim.2.syn#dap4&debug=copy&substratename=./results/test_anon_dim.2.syn.nc"},
{"file://x/y","file://x/y"},
{NULL,NULL}
};
/* Tests that should fail */
static char* XTESTS[] = {
"file://x/y",
"[dap4http://localhost:8081/x",
NULL
};
@ -63,7 +64,7 @@ main(int argc, char** argv)
int ret = 0;
NCURI* uri = NULL;
ret = ncuriparse(test->url,&uri);
if(ret != NCU_OK) {
if(ret != NC_NOERR) {
fprintf(stderr,"Parse fail: %s\n",test->url);
failcount++;
} else {
@ -83,10 +84,8 @@ main(int argc, char** argv)
}
for(xtest=XTESTS;*xtest;xtest++) {
int ret = 0;
NCURI* uri = NULL;
ret = ncuriparse(*xtest,&uri);
if(ret == NCU_OK) {
if(!ncuriparse(*xtest,&uri)) {
fprintf(stderr,"XTEST succeeded: %s\n",*xtest);
failcount++;
}

View File

@ -34,7 +34,6 @@ main(int argc, char **argv)
"nc4_file_list_add()...");
{
NC *ncp;
NCmodel model;
char *path;
/* The NC3_dispatch_table is defined in nc3dispatch.c and
* externed in ncdispatch.h. But it will be 0 because we have
@ -47,9 +46,8 @@ main(int argc, char **argv)
* has an ncid of TEST_VAL_42. */
if (nc4_file_list_add(TEST_VAL_42, FILE_NAME, 0, NULL) != NC_EBADID) ERR;
/* Create the NC* instance and insert its dispatcher and
* model. */
if (new_NC(dispatcher, FILE_NAME, mode, &model, &ncp)) ERR;
/* Create the NC* instance and insert its dispatcher */
if (new_NC(dispatcher, FILE_NAME, mode, &ncp)) ERR;
/* Add to array of open files nc_filelist and define
* ext_ncid by left-shifting the index 16 bits. */
@ -84,16 +82,14 @@ main(int argc, char **argv)
"nc4_nc4f_list_add()...");
{
NC *ncp, *ncp_in, *ncp_in2;
NCmodel model;
char *path;
void *dispatchdata_in;
int mode = 0, mode_in;
NC_GRP_INFO_T *grp, *grp2;
NC_FILE_INFO_T *h5, *h52;
/* Create the NC* instance and insert its dispatcher and
* model. */
if (new_NC(NC3_dispatch_table, FILE_NAME, mode, &model, &ncp)) ERR;
/* Create the NC* instance and insert its dispatcher */
if (new_NC(NC3_dispatch_table, FILE_NAME, mode, &ncp)) ERR;
/* Add to array of open files nc_filelist and define
* ext_ncid by left-shifting the index 16 bits. */
@ -153,14 +149,12 @@ main(int argc, char **argv)
printf("Testing adding new var to nc4internal file...");
{
NC *ncp, *ncp_in;
NCmodel model;
NC_GRP_INFO_T *grp;
NC_VAR_INFO_T *var, *var_in;
NC_FILE_INFO_T *h5;
/* Create the NC* instance and insert its dispatcher and
* model. */
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &model, &ncp)) ERR;
/* Create the NC* instance and insert its dispatcher */
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &ncp)) ERR;
/* Add to array of open files nc_filelist and define
* ext_ncid by left-shifting the index 16 bits. */
@ -205,13 +199,12 @@ main(int argc, char **argv)
printf("Testing adding new dim to nc4internal file...");
{
NC *ncp;
NCmodel model;
NC_GRP_INFO_T *grp, *dim_grp;
NC_DIM_INFO_T *dim, *dim_in;
/* Create the NC, add it to nc_filelist array, add and init
* NC_FILE_INFO_T. */
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &model, &ncp)) ERR;
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &ncp)) ERR;
add_to_NCList(ncp);
if (nc4_file_list_add(ncp->ext_ncid, FILE_NAME, 0, NULL)) ERR;
if (nc4_find_nc_grp_h5(ncp->ext_ncid, NULL, &grp, NULL)) ERR;
@ -236,14 +229,13 @@ main(int argc, char **argv)
printf("Testing adding new type to nc4internal file...");
{
NC *ncp;
NCmodel model;
NC_GRP_INFO_T *grp;
NC_TYPE_INFO_T *type, *type_in;
NC_FILE_INFO_T *h5;
/* Create the NC, add it to nc_filelist array, add and init
* NC_FILE_INFO_T. */
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &model, &ncp)) ERR;
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &ncp)) ERR;
add_to_NCList(ncp);
if (nc4_file_list_add(ncp->ext_ncid, FILE_NAME, 0, NULL)) ERR;
if (nc4_find_nc_grp_h5(ncp->ext_ncid, NULL, &grp, &h5)) ERR;
@ -268,14 +260,13 @@ main(int argc, char **argv)
printf("Testing changing ncid...");
{
NC *ncp;
NCmodel model;
NC_GRP_INFO_T *grp;
NC_FILE_INFO_T *h5;
int old_ncid;
/* Create the NC, add it to nc_filelist array, add and init
* NC_FILE_INFO_T. */
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &model, &ncp)) ERR;
if (new_NC(NC3_dispatch_table, FILE_NAME, 0, &ncp)) ERR;
add_to_NCList(ncp);
if (nc4_file_list_add(ncp->ext_ncid, FILE_NAME, 0, NULL)) ERR;
if (nc4_find_nc_grp_h5(ncp->ext_ncid, NULL, &grp, &h5)) ERR;

View File

@ -37,11 +37,10 @@ main(int argc, char **argv)
int ncid;
NC *ncp, *ncp2;
int mode = 0;
NCmodel model;
int ret;
/* Create the NC* instance and insert its dispatcher and model. */
if ((ret = new_NC(NULL, FILE_NAME, mode, &model, &ncp))) ERR;
if ((ret = new_NC(NULL, FILE_NAME, mode, &ncp))) ERR;
/* Nothing to find yet. */
if (find_in_NCList(TEST_VAL_42)) ERR;
@ -82,11 +81,10 @@ main(int argc, char **argv)
int ncid;
NC *ncp, *ncp2;
int mode = 0;
NCmodel model;
int ret;
/* Create the NC* instance and add it to list. */
if ((ret = new_NC(NULL, FILE_NAME, mode, &model, &ncp))) ERR;
if ((ret = new_NC(NULL, FILE_NAME, mode, &ncp))) ERR;
add_to_NCList(ncp);
/* Find it in the list. */
@ -122,7 +120,7 @@ main(int argc, char **argv)
/* Fill the NC list. */
for (i = 0; i < max_num_nc; i++)
{
if ((ret = new_NC(NULL, FILE_NAME, mode, &model, &ncp))) ERR;
if ((ret = new_NC(NULL, FILE_NAME, mode, &ncp))) ERR;
if (add_to_NCList(ncp)) ERR;
}