netcdf-c/libdispatch/ddispatch.c

224 lines
5.9 KiB
C
Raw Normal View History

#include "ncdispatch.h"
#include "ncuri.h"
2010-12-16 05:45:05 +08:00
#define MAXSERVERURL 4096
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*/
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-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 */
};
/* Define the default servers to ping in order;
make the order attempt to optimize
against future changes.
*/
static const char* default_servers[] = {
"http://remotetest.unidata.ucar.edu",
NULL
};
2010-07-31 06:16:15 +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);
*/
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;
}
/* search list of servers and return first that succeeds when
concatenated with the specified path part.
Search list can be prefixed by the second argument.
*/
char*
NC_findtestserver(const char* path, const char** servers)
{
#ifdef USE_DAP
#ifdef ENABLE_DAP_REMOTE_TESTS
2014-04-23 03:59:47 +08:00
/* NCDAP_ping is defined in libdap2/ncdap.c */
const char** svc;
int stat;
char* url = (char*)malloc(MAXSERVERURL);
if(path == NULL) path = "";
if(strlen(path) > 0 && path[0] == '/')
path++;
if(servers != NULL) {
for(svc=servers;*svc != NULL;svc++) {
snprintf(url,MAXSERVERURL,"%s/%s",*svc,path);
stat = NCDAP_ping(url);
if(stat == NC_NOERR)
return url;
}
}
/* not found in user supplied list; try defaults */
for(svc=default_servers;*svc != NULL;svc++) {
snprintf(url,MAXSERVERURL,"%s/%s",*svc,path);
stat = NCDAP_ping(url);
if(stat == NC_NOERR)
return url;
}
2014-10-07 00:48:11 +08:00
if(url) free(url);
#endif
#endif
return NULL;
}
2010-12-16 05:45:05 +08:00
/* return 1 if path looks like a url; 0 otherwise */
int
NC_testurl(const char* path)
{
2011-01-21 05:45:29 +08:00
int isurl = 0;
NCURI* tmpurl = NULL;
2011-01-21 05:45:29 +08:00
char* p;
if(path == NULL) return 0;
/* find leading non-blank */
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 */
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;
2014-10-07 00:48:11 +08:00
}
2011-01-21 05:45:29 +08:00
}
ncurifree(tmpurl);
2011-01-21 05:45:29 +08:00
return isurl;
}
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
*/
int
NC_urlmodel(const char* path)
{
int model = 0;
NCURI* tmpurl = NULL;
2010-12-16 05:45:05 +08:00
struct NCPROTOCOLLIST* protolist;
if(!ncuriparse(path,&tmpurl)) goto done;
2010-12-16 05:45:05 +08:00
/* Look at any prefixed parameters */
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);
} 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);
} 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-12-16 05:45:05 +08:00
2011-06-11 02:47:26 +08:00
if(model == 0) {
for(protolist=ncprotolist;protolist->protocol;protolist++) {
if(strcmp(tmpurl->protocol,protolist->protocol) == 0) {
model |= protolist->modelflags;
if(protolist->substitute) {
2014-08-18 02:03:23 +08:00
free(tmpurl->protocol);
2011-06-11 02:47:26 +08:00
tmpurl->protocol = strdup(protolist->substitute);
}
2014-10-07 00:48:11 +08:00
break;
}
2010-12-16 05:45:05 +08:00
}
2014-10-07 00:48:11 +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:
ncurifree(tmpurl);
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;
int i;
size_t count = sizeof(NC_Dispatch) / sizeof(void*);
/* 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;
}