2010-08-05 10:44:59 +08:00
|
|
|
#include "ncdispatch.h"
|
2012-08-09 07:15:18 +08:00
|
|
|
#include "ncuri.h"
|
2010-12-16 05:45:05 +08:00
|
|
|
|
2011-09-19 04:57:51 +08:00
|
|
|
extern int NCSUBSTRATE_intialize(void);
|
|
|
|
|
2011-09-21 01:30:02 +08:00
|
|
|
/* Define vectors of zeros and ones for use with various nc_get_varX function*/
|
2013-01-24 07:31:34 +08:00
|
|
|
size_t nc_sizevector0[NC_MAX_VAR_DIMS];
|
|
|
|
size_t nc_sizevector1[NC_MAX_VAR_DIMS];
|
|
|
|
ptrdiff_t nc_ptrdiffvector1[NC_MAX_VAR_DIMS];
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
/* Define the known protocols and their manipulations */
|
|
|
|
static struct NCPROTOCOLLIST {
|
|
|
|
char* protocol;
|
|
|
|
char* substitute;
|
|
|
|
int modelflags;
|
|
|
|
} ncprotolist[] = {
|
|
|
|
{"http",NULL,0},
|
|
|
|
{"https",NULL,0},
|
|
|
|
{"file",NULL,NC_DISPATCH_NCD},
|
|
|
|
{"dods","http",NC_DISPATCH_NCD},
|
|
|
|
{"dodss","https",NC_DISPATCH_NCD},
|
|
|
|
{"cdmr","http",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
|
|
|
|
{"cdmrs","https",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
|
|
|
|
{"cdmremote","http",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
|
|
|
|
{"cdmremotes","https",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
|
|
|
|
{NULL,NULL,0} /* Terminate search */
|
|
|
|
};
|
|
|
|
|
2012-06-23 05:54:52 +08:00
|
|
|
/* Define the server to ping in order;
|
|
|
|
make the order attempt to optimize
|
|
|
|
against future changes.
|
|
|
|
*/
|
|
|
|
static const char* servers[] = {
|
2013-03-26 01:44:08 +08:00
|
|
|
"http://remotetest.unidata.ucar.edu",
|
2012-06-23 05:54:52 +08:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2010-07-31 06:16:15 +08:00
|
|
|
/*
|
2010-06-22 21:25:14 +08:00
|
|
|
static nc_type longtype = (sizeof(long) == sizeof(int)?NC_INT:NC_INT64);
|
2010-07-31 06:16:15 +08:00
|
|
|
static nc_type ulongtype = (sizeof(unsigned long) == sizeof(unsigned int)?NC_UINT:NC_UINT64);
|
|
|
|
*/
|
2010-06-22 21:25:14 +08:00
|
|
|
|
2011-09-19 04:57:51 +08:00
|
|
|
/* Allow dispatch to do initialization */
|
|
|
|
int
|
|
|
|
NCDISPATCH_initialize(void)
|
|
|
|
{
|
2011-09-21 01:30:02 +08:00
|
|
|
extern int NCSUBSTRATE_initialize(void);
|
|
|
|
int i;
|
2011-09-19 04:57:51 +08:00
|
|
|
NCSUBSTRATE_initialize();
|
2011-09-21 01:30:02 +08:00
|
|
|
for(i=0;i<NC_MAX_VAR_DIMS;i++) {
|
|
|
|
nc_sizevector0[i] = 0;
|
|
|
|
nc_sizevector1[i] = 1;
|
|
|
|
nc_ptrdiffvector1[i] = 1;
|
|
|
|
}
|
2011-09-19 04:57:51 +08:00
|
|
|
return NC_NOERR;
|
|
|
|
}
|
|
|
|
|
2012-06-23 05:54:52 +08:00
|
|
|
/* search list of servers and return first that succeeds when
|
|
|
|
concatenated with the specified path part
|
|
|
|
*/
|
|
|
|
const char*
|
|
|
|
NC_findtestserver(const char* path)
|
|
|
|
{
|
|
|
|
#ifdef USE_DAP
|
2014-03-09 11:41:30 +08:00
|
|
|
#ifdef ENABLE_DAP_REMOTE_TESTS
|
2014-04-23 03:59:47 +08:00
|
|
|
/* NCDAP_ping is defined in libdap2/ncdap.c */
|
2012-06-23 05:54:52 +08:00
|
|
|
const char** svc;
|
|
|
|
if(path == NULL) path = "";
|
|
|
|
for(svc=servers;*svc != NULL;svc++) {
|
2012-07-17 04:34:31 +08:00
|
|
|
int stat;
|
2012-06-23 05:54:52 +08:00
|
|
|
char url[4096];
|
|
|
|
snprintf(url,sizeof(url),"%s%s%s",
|
|
|
|
*svc,
|
|
|
|
(path[0] == '/' ? "" : "/"),
|
|
|
|
path);
|
2012-07-17 04:34:31 +08:00
|
|
|
stat = NCDAP_ping(url);
|
2012-06-23 05:54:52 +08:00
|
|
|
if(stat == NC_NOERR)
|
|
|
|
return *svc;
|
|
|
|
}
|
2014-03-09 11:41:30 +08:00
|
|
|
#endif
|
2012-06-23 05:54:52 +08:00
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
/* return 1 if path looks like a url; 0 otherwise */
|
2010-06-22 21:25:14 +08:00
|
|
|
int
|
|
|
|
NC_testurl(const char* path)
|
|
|
|
{
|
2011-01-21 05:45:29 +08:00
|
|
|
int isurl = 0;
|
2012-08-09 07:15:18 +08:00
|
|
|
NCURI* tmpurl = NULL;
|
2011-01-21 05:45:29 +08:00
|
|
|
char* p;
|
|
|
|
|
|
|
|
if(path == NULL) return 0;
|
|
|
|
|
|
|
|
/* find leading non-blank */
|
2011-04-07 02:38:35 +08:00
|
|
|
for(p=(char*)path;*p;p++) {if(*p != ' ') break;}
|
2011-01-21 05:45:29 +08:00
|
|
|
|
|
|
|
/* Do some initial checking to see if this looks like a file path */
|
|
|
|
if(*p == '/') return 0; /* probably an absolute file path */
|
|
|
|
|
|
|
|
/* Ok, try to parse as a url */
|
2012-08-09 07:15:18 +08:00
|
|
|
if(ncuriparse(path,&tmpurl)) {
|
2011-01-21 05:45:29 +08:00
|
|
|
/* Do some extra testing to make sure this really is a url */
|
|
|
|
/* Look for a knownprotocol */
|
|
|
|
struct NCPROTOCOLLIST* protolist;
|
|
|
|
for(protolist=ncprotolist;protolist->protocol;protolist++) {
|
|
|
|
if(strcmp(tmpurl->protocol,protolist->protocol) == 0) {
|
|
|
|
isurl=1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-08-09 07:15:18 +08:00
|
|
|
ncurifree(tmpurl);
|
2011-01-21 05:45:29 +08:00
|
|
|
return isurl;
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
/*
|
|
|
|
Return the OR of some of the NC_DISPATCH flags
|
|
|
|
Assumes that the path is known to be a url
|
|
|
|
*/
|
|
|
|
|
2010-06-22 21:25:14 +08:00
|
|
|
int
|
|
|
|
NC_urlmodel(const char* path)
|
|
|
|
{
|
|
|
|
int model = 0;
|
2012-08-09 07:15:18 +08:00
|
|
|
NCURI* tmpurl = NULL;
|
2010-12-16 05:45:05 +08:00
|
|
|
struct NCPROTOCOLLIST* protolist;
|
|
|
|
|
2012-08-09 07:15:18 +08:00
|
|
|
if(!ncuriparse(path,&tmpurl)) goto done;
|
2010-12-16 05:45:05 +08:00
|
|
|
|
|
|
|
/* Look at any prefixed parameters */
|
2012-08-09 07:15:18 +08:00
|
|
|
if(ncurilookup(tmpurl,"netcdf4",NULL)
|
|
|
|
|| ncurilookup(tmpurl,"netcdf-4",NULL)) {
|
2010-12-16 05:45:05 +08:00
|
|
|
model = (NC_DISPATCH_NC4|NC_DISPATCH_NCD);
|
2012-08-09 07:15:18 +08:00
|
|
|
} else if(ncurilookup(tmpurl,"netcdf3",NULL)
|
|
|
|
|| ncurilookup(tmpurl,"netcdf-3",NULL)) {
|
2010-12-16 05:45:05 +08:00
|
|
|
model = (NC_DISPATCH_NC3|NC_DISPATCH_NCD);
|
2012-08-09 07:15:18 +08:00
|
|
|
} else if(ncurilookup(tmpurl,"cdmremote",NULL)
|
|
|
|
|| ncurilookup(tmpurl,"cdmr",NULL)) {
|
2010-12-16 05:45:05 +08:00
|
|
|
model = (NC_DISPATCH_NCR|NC_DISPATCH_NC4);
|
2010-06-22 21:25:14 +08:00
|
|
|
}
|
2010-12-16 05:45:05 +08:00
|
|
|
|
2011-06-11 02:47:26 +08:00
|
|
|
if(model == 0) {
|
|
|
|
/* Now look at the protocol */
|
|
|
|
for(protolist=ncprotolist;protolist->protocol;protolist++) {
|
|
|
|
if(strcmp(tmpurl->protocol,protolist->protocol) == 0) {
|
|
|
|
model |= protolist->modelflags;
|
|
|
|
if(protolist->substitute) {
|
|
|
|
if(tmpurl->protocol) free(tmpurl->protocol);
|
|
|
|
tmpurl->protocol = strdup(protolist->substitute);
|
|
|
|
}
|
|
|
|
break;
|
2011-05-13 01:51:32 +08:00
|
|
|
}
|
2010-12-16 05:45:05 +08:00
|
|
|
}
|
|
|
|
}
|
2011-06-11 02:47:26 +08:00
|
|
|
|
2010-12-16 05:45:05 +08:00
|
|
|
/* Force NC_DISPATCH_NC3 if necessary */
|
|
|
|
if((model & NC_DISPATCH_NC4) == 0)
|
|
|
|
model |= (NC_DISPATCH_NC3 | NC_DISPATCH_NCD);
|
|
|
|
|
|
|
|
done:
|
2012-08-09 07:15:18 +08:00
|
|
|
ncurifree(tmpurl);
|
2010-06-22 21:25:14 +08:00
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Override dispatch table management */
|
|
|
|
static NC_Dispatch* NC_dispatch_override = NULL;
|
|
|
|
|
|
|
|
/* Override dispatch table management */
|
|
|
|
NC_Dispatch*
|
|
|
|
NC_get_dispatch_override(void) {
|
|
|
|
return NC_dispatch_override;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NC_set_dispatch_override(NC_Dispatch* d)
|
|
|
|
{
|
|
|
|
NC_dispatch_override = d;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Overlay by treating the tables as arrays of void*.
|
|
|
|
Overlay rules are:
|
|
|
|
overlay base merge
|
|
|
|
------- ---- -----
|
|
|
|
null null null
|
|
|
|
null y y
|
|
|
|
x null x
|
|
|
|
x y x
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
NC_dispatch_overlay(const NC_Dispatch* overlay, const NC_Dispatch* base, NC_Dispatch* merge)
|
|
|
|
{
|
|
|
|
void** voverlay = (void**)overlay;
|
|
|
|
void** vmerge;
|
2014-03-11 02:09:36 +08:00
|
|
|
int i;
|
|
|
|
size_t count = sizeof(NC_Dispatch) / sizeof(void*);
|
2010-06-22 21:25:14 +08:00
|
|
|
/* dispatch table must be exact multiple of sizeof(void*) */
|
|
|
|
assert(count * sizeof(void*) == sizeof(NC_Dispatch));
|
|
|
|
*merge = *base;
|
|
|
|
vmerge = (void**)merge;
|
|
|
|
for(i=0;i<count;i++) {
|
|
|
|
if(voverlay[i] == NULL) continue;
|
|
|
|
vmerge[i] = voverlay[i];
|
|
|
|
}
|
|
|
|
/* Finally, the merge model should always be the overlay model */
|
|
|
|
merge->model = overlay->model;
|
|
|
|
return NC_NOERR;
|
|
|
|
}
|