mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
jira: NCF-232: bad conversion of grids
This commit is contained in:
parent
ba6bcca272
commit
6cf31dcf2d
2
cf
2
cf
@ -20,7 +20,7 @@ cmds=""
|
||||
#cmds="all"
|
||||
#cmds="all check"
|
||||
#cmds="all dist"
|
||||
#cmds="all distcheck"
|
||||
cmds="all distcheck"
|
||||
#cmds="$cmds install"
|
||||
fi
|
||||
|
||||
|
195
libdap2/cdf3.c
195
libdap2/cdf3.c
@ -8,12 +8,18 @@
|
||||
#include "daputil.h"
|
||||
#include "dapdump.h"
|
||||
|
||||
#ifdef DAPDEBUG
|
||||
extern char* ocfqn(OCddsnode);
|
||||
#endif
|
||||
|
||||
CDFnode* v4node = NULL;
|
||||
|
||||
/* Forward*/
|
||||
static NCerror sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq);
|
||||
static NCerror restruct3r(CDFnode*, CDFnode*);
|
||||
static NCerror restruct3r(CDFnode*, CDFnode*, NClist*);
|
||||
static NCerror repairgrids(NClist*);
|
||||
static NCerror structwrap3(CDFnode*, CDFnode*, int, CDFnode*, int);
|
||||
static int findin(CDFnode* parent, CDFnode* child);
|
||||
static CDFnode* makenewstruct3(CDFnode* node, CDFnode* template);
|
||||
static NCerror mapnodes3r(CDFnode*, CDFnode*, int depth);
|
||||
static NCerror mapfcn(CDFnode* dstnode, CDFnode* srcnode);
|
||||
@ -268,9 +274,17 @@ sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq)
|
||||
}
|
||||
|
||||
/*
|
||||
OPeNDAP is in the process of changing servers so that
|
||||
partial grids are converted to structures. However, not all
|
||||
servers do this, and not consistently.
|
||||
Originally, if one did a constraint on a Grid such that only
|
||||
one array or map in the grid was returned, that element was
|
||||
returned as a top level variable. This is incorrect because
|
||||
it loses the Grid scope information.
|
||||
|
||||
Eventually, this behavior was changed so that such partial
|
||||
grids are converted to structures where the structure name
|
||||
is the grid name. This preserves the proper scoping.
|
||||
However, it is still the case that some servers do the old
|
||||
behavior.
|
||||
|
||||
The rules that most old-style servers appear to adhere to are these.
|
||||
1. Asking for just a grid array or a single grid map
|
||||
returns just the array not wrapped in a structure.
|
||||
@ -285,6 +299,8 @@ with case 2. Case 3 should cause an error with a malformed grid.
|
||||
|
||||
[Note: for some reason, this code has been difficult to get right;
|
||||
I have rewritten 6 times and it probably is still not right.]
|
||||
[2/25/2013 Sigh! Previous fixes have introducted another bug,
|
||||
so now we fix the fix.]
|
||||
|
||||
Input is
|
||||
(1) the root of the dds that needs to be re-gridded
|
||||
@ -297,6 +313,7 @@ NCerror
|
||||
restruct3(CDFnode* ddsroot, CDFnode* template, NClist* projections)
|
||||
{
|
||||
NCerror ncstat = NC_NOERR;
|
||||
NClist* repairs = nclistnew();
|
||||
|
||||
/* The current restruct assumes that the ddsroot tree
|
||||
has missing grids compared to the template.
|
||||
@ -310,14 +327,15 @@ fprintf(stderr,"restruct: ddsroot=%s\n",dumptree(ddsroot));
|
||||
fprintf(stderr,"restruct: template=%s\n",dumptree(template));
|
||||
#endif
|
||||
|
||||
/* Try to match this node against the template */
|
||||
/* Match roots */
|
||||
if(!simplenodematch34(ddsroot,template))
|
||||
{ncstat = NC_EDATADDS; goto done;}
|
||||
|
||||
ncstat = restruct3r(ddsroot,template);
|
||||
ddsroot->tree->restructed = 1;
|
||||
|
||||
done:
|
||||
ncstat = NC_EDATADDS;
|
||||
else if(!restruct3r(ddsroot,template,repairs))
|
||||
ncstat = NC_EDATADDS;
|
||||
else if(nclistlength(repairs) > 0) {
|
||||
/* Do the repairs */
|
||||
ncstat = repairgrids(repairs);
|
||||
}
|
||||
return THROW(ncstat);
|
||||
}
|
||||
|
||||
@ -326,95 +344,122 @@ Locate nodes in the tree rooted at node
|
||||
that correspond to a single grid field in the template
|
||||
when the template is a grid.
|
||||
Wrap that grid field in a synthesized structure.
|
||||
|
||||
The key thing to look for is the case where
|
||||
we have an atomic variable that appear where
|
||||
we expected a grid.
|
||||
|
||||
*/
|
||||
static NCerror
|
||||
restruct3r(CDFnode* node, CDFnode* template)
|
||||
|
||||
static int
|
||||
restruct3r(CDFnode* parentnode, CDFnode* templateparent, NClist* repairlist)
|
||||
{
|
||||
unsigned int inode, itemp, i;
|
||||
NCerror ncstat = NC_NOERR;
|
||||
int index, i, j, match;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"restruct: matched: %s -> %s\n",
|
||||
node->ocname,template->ocname);
|
||||
ocfqn(parentnode->ocnode),ocfqn(templateparent->ocnode));
|
||||
#endif
|
||||
|
||||
/* this part is tricky; except for nodes needing
|
||||
wrapping, the set of children of the node better
|
||||
be a subset of the children in the template.
|
||||
*/
|
||||
|
||||
/* walk each node child and locate its match
|
||||
in the template's children; recurse on matches,
|
||||
non-matches should be nodes needing wrapping.
|
||||
non-matches may be nodes needing wrapping.
|
||||
*/
|
||||
for(inode=0;inode<nclistlength(node->subnodes);inode++) {
|
||||
CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,inode);
|
||||
CDFnode* wrap = NULL;
|
||||
int wrapindex = 0;
|
||||
int match = 0;
|
||||
for(itemp=0;itemp<nclistlength(template->subnodes);itemp++) {
|
||||
CDFnode* subtemp = (CDFnode*)nclistget(template->subnodes,itemp);
|
||||
if(simplenodematch34(subnode,subtemp)) {
|
||||
/* this subnode of the node matches the corresponding
|
||||
node of the template, so it is ok =>
|
||||
recurse looking for nested mis-matches
|
||||
*/
|
||||
ncstat = restruct3r(subnode,subtemp);
|
||||
if(ncstat != NC_NOERR) return THROW(ncstat);
|
||||
match = 1; /* indicate that we matched */
|
||||
break;
|
||||
} else if(subtemp->nctype == NC_Grid || subtemp->nctype == NC_Structure) {
|
||||
/* See if we can match this subnode to a subnode
|
||||
of the grid or structure */
|
||||
for(i=0;i<nclistlength(subtemp->subnodes);i++) {
|
||||
CDFnode* level2 = (CDFnode*)nclistget(subtemp->subnodes,i);
|
||||
if(simplenodematch34(subnode,level2)) {
|
||||
/* ASSUME that subnode needs rewrap wrt subtemp */
|
||||
wrap = subtemp;
|
||||
wrapindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!match && wrap == NULL) {
|
||||
/* This should never occur */
|
||||
ncstat = NC_EDATADDS; goto done;
|
||||
}
|
||||
if(wrap != NULL) { /* This subnode should need wrapping */
|
||||
ASSERT(wrap->nctype == NC_Grid || wrap->nctype == NC_Structure);
|
||||
ncstat = structwrap3(subnode,node,inode,wrap,wrapindex);
|
||||
if(ncstat != NC_NOERR) goto done;
|
||||
/* since grids are terminal, there will be no
|
||||
need to continue the recursion */
|
||||
}
|
||||
}
|
||||
done:
|
||||
return THROW(ncstat);
|
||||
|
||||
for(index=0;index<nclistlength(parentnode->subnodes);index++) {
|
||||
CDFnode* subnode = (CDFnode*)nclistget(parentnode->subnodes,index);
|
||||
CDFnode* matchnode = NULL;
|
||||
int matchindex = -1;
|
||||
|
||||
/* Look for a matching template node with same ocname */
|
||||
for(i=0;i<nclistlength(templateparent->subnodes);i++) {
|
||||
CDFnode* subtemp = (CDFnode*)nclistget(templateparent->subnodes,i);
|
||||
if(strcmp(subnode->ocname,subtemp->ocname) == 0) {
|
||||
matchnode = subtemp;
|
||||
matchindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(simplenodematch34(subnode,matchnode)) {
|
||||
/* this subnode of the node matches the corresponding
|
||||
node of the template, so it is ok =>
|
||||
recurse looking for nested mis-matches
|
||||
*/
|
||||
return restruct3r(subnode,matchnode,repairlist);
|
||||
}
|
||||
/* If we do not have a direct match, then we need to look
|
||||
at all the grids to see if this node matches a field
|
||||
in one of the grids
|
||||
*/
|
||||
for(match=0,i=0;!match && i<nclistlength(templateparent->subnodes);i++) {
|
||||
CDFnode* subtemp = (CDFnode*)nclistget(templateparent->subnodes,i);
|
||||
if(subtemp->nctype == NC_Grid) { /* look inside */
|
||||
for(j=0;j<nclistlength(templateparent->subnodes);j++) {
|
||||
CDFnode* gridfield = (CDFnode*)nclistget(subtemp->subnodes,j);
|
||||
if(simplenodematch34(subnode,gridfield)) {
|
||||
/* We need to do this repair */
|
||||
nclistpush(repairlist,(void*)subnode);
|
||||
nclistpush(repairlist,(void*)gridfield);
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!match) return 0; /* we failed */
|
||||
}
|
||||
return 1; /* we matched everything at this level */
|
||||
}
|
||||
|
||||
/* Wrap the node wrt the template grid or template struct */
|
||||
|
||||
static NCerror
|
||||
repairgrids(NClist* repairlist)
|
||||
{
|
||||
NCerror ncstat = NC_NOERR;
|
||||
int i;
|
||||
assert(nclistlength(repairlist) % 2 == 0);
|
||||
for(i=0;i<nclistlength(repairlist);i+=2) {
|
||||
CDFnode* node = (CDFnode*)nclistget(repairlist,i);
|
||||
CDFnode* template = (CDFnode*)nclistget(repairlist,i+1);
|
||||
int index = findin(node->container,node);
|
||||
int tindex = findin(template->container,template);
|
||||
ncstat = structwrap3(node,node->container,index,
|
||||
template->container,tindex);
|
||||
}
|
||||
return ncstat;
|
||||
}
|
||||
|
||||
static NCerror
|
||||
structwrap3(CDFnode* node, CDFnode* parent, int parentindex,
|
||||
CDFnode* templategrid, int gridindex)
|
||||
{
|
||||
NCerror ncstat = NC_NOERR;
|
||||
CDFnode* newstruct;
|
||||
|
||||
ASSERT((templategrid->nctype == NC_Grid || templategrid->nctype == NC_Structure));
|
||||
ASSERT((templategrid->nctype == NC_Grid));
|
||||
|
||||
newstruct = makenewstruct3(node,templategrid);
|
||||
if(newstruct == NULL) {ncstat = NC_ENOMEM; goto done;}
|
||||
if(newstruct == NULL) {return THROW(NC_ENOMEM);}
|
||||
|
||||
/* replace the node with the new structure
|
||||
in the parent's list of children*/
|
||||
nclistremove(parent->subnodes,parentindex);
|
||||
nclistinsert(parent->subnodes,parentindex,(void*)newstruct);
|
||||
nclistset(parent->subnodes,parentindex,(void*)newstruct);
|
||||
|
||||
/* Update the list of all nodes in the tree */
|
||||
nclistpush(node->root->tree->nodes,(void*)newstruct);
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
done:
|
||||
return ncstat;
|
||||
static int
|
||||
findin(CDFnode* parent, CDFnode* child)
|
||||
{
|
||||
int i;
|
||||
NClist* subnodes = parent->subnodes;
|
||||
for(i=0;i<nclistlength(subnodes);i++) {
|
||||
if(nclistget(subnodes,i) == child)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create a structure to surround projected grid array or map;
|
||||
@ -471,7 +516,7 @@ mapnodes3r(CDFnode* connode, CDFnode* fullnode, int depth)
|
||||
#ifdef DEBUG
|
||||
{
|
||||
char* path1 = makecdfpathstring3(fullnode,".");
|
||||
char * path2 = makecdfpathstring3(connode,".");
|
||||
char* path2 = makecdfpathstring3(connode,".");
|
||||
fprintf(stderr,"mapnode: %s->%s\n",path1,path2);
|
||||
nullfree(path1); nullfree(path2);
|
||||
}
|
||||
@ -664,7 +709,7 @@ fprintf(stderr,"dimsetall: recurse to container%s\n",node->container->ocname);
|
||||
}
|
||||
node->array.dimsetall = dimsetall;
|
||||
#ifdef DEBUG1
|
||||
fprintf(stderr,"dimsetall: |%s|=%d\n",node->ocname,nclistlength(dimsetall));
|
||||
fprintf(stderr,"dimsetall: |%s|=%d\n",node->ocname,(int)nclistlength(dimsetall));
|
||||
#endif
|
||||
return ncstat;
|
||||
}
|
||||
|
@ -697,30 +697,43 @@ nodematch34(CDFnode* node1, CDFnode* node2)
|
||||
return simplenodematch34(node1,node2);
|
||||
}
|
||||
|
||||
/*
|
||||
Try to figure out if two nodes
|
||||
are the "related" =>
|
||||
same name && same nc_type and same arity
|
||||
but: Allow Grid == Structure
|
||||
*/
|
||||
|
||||
int
|
||||
simplenodematch34(CDFnode* node1, CDFnode* node2)
|
||||
{
|
||||
if(node1 == NULL) return (node2==NULL);
|
||||
if(node2 == NULL) return 0;
|
||||
if(node1->nctype != node2->nctype) {
|
||||
/* Check for Grid->Structure match */
|
||||
if((node1->nctype == NC_Structure && node2->nctype == NC_Grid)
|
||||
|| (node2->nctype == NC_Structure && node1->nctype == NC_Grid)){
|
||||
if(node1->ocname == NULL || node2->ocname == NULL
|
||||
|| strcmp(node1->ocname,node2->ocname) !=0) return 0;
|
||||
} else return 0;
|
||||
}
|
||||
/* Test all the obvious stuff */
|
||||
if(node1 == NULL || node2 == NULL)
|
||||
return 0;
|
||||
if(strcmp(node1->ocname,node2->ocname)!=0) /* same names */
|
||||
return 0;
|
||||
if(nclistlength(node1->array.dimset0)
|
||||
!= nclistlength(node2->array.dimset0)) /* same arity */
|
||||
return 0;
|
||||
|
||||
/* Add hack to address the screwed up Columbia server */
|
||||
if(node1->nctype == NC_Dataset) return 1;
|
||||
if(node1->nctype == NC_Atomic
|
||||
&& node1->etype != node2->etype) return 0;
|
||||
if(node1->ocname != NULL && node2->ocname != NULL
|
||||
&& strcmp(node1->ocname,node2->ocname)!=0) return 0;
|
||||
if(nclistlength(node1->array.dimset0)
|
||||
!= nclistlength(node2->array.dimset0)) return 0;
|
||||
|
||||
if(node1->nctype != node2->nctype) {
|
||||
/* test for struct-grid match */
|
||||
int structgrid = ((node1->nctype == NC_Grid && node2->nctype == NC_Structure)
|
||||
|| (node1->nctype == NC_Structure && node2->nctype == NC_Grid) ? 1 : 0);
|
||||
if(!structgrid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(node1->nctype == NC_Atomic && node1->etype != node2->etype)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Given DDS node, locate the node
|
||||
in a DATADDS that matches the DDS node.
|
||||
|
@ -5,7 +5,7 @@
|
||||
*********************************************************************/
|
||||
|
||||
#include "ncdap3.h"
|
||||
#include "dapdebug.h"
|
||||
#include "dapdump.h"
|
||||
#include "dapdump.h"
|
||||
#include "dceparselex.h"
|
||||
|
||||
|
@ -8,8 +8,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nclog.h"
|
||||
#include "oc.h"
|
||||
#include "dapdebug.h"
|
||||
#include "ncdap3.h"
|
||||
|
||||
int ncdap3debug = 0;
|
||||
|
||||
@ -42,3 +41,16 @@ dappanic(const char* fmt, ...)
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Provide a way to print the oc full name for
|
||||
an ocnode
|
||||
*/
|
||||
|
||||
char*
|
||||
ocfqn(OCddsnode node)
|
||||
{
|
||||
OClink conn;
|
||||
oc_get_connection(node,&conn);
|
||||
return makeocpathstring3(conn,node,".");
|
||||
}
|
||||
|
@ -6,6 +6,12 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
|
||||
#if 0
|
||||
#define DAPDEBUG 1
|
||||
#define OCDEBUG
|
||||
#endif
|
||||
|
||||
#include "ocdebug.h"
|
||||
|
||||
#ifdef DAPDEBUG
|
||||
|
@ -301,7 +301,7 @@ dumptreer1(CDFnode* root, NCbytes* buf, int indent, char* tag, int visible)
|
||||
}
|
||||
dumpindent(indent,buf);
|
||||
ncbytescat(buf,"} ");
|
||||
ncbytescat(buf,root->ncbasename);
|
||||
ncbytescat(buf,(root->ncbasename?root->ncbasename:"<?>"));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -344,7 +344,7 @@ dumptreer(CDFnode* root, NCbytes* buf, int indent, int visible)
|
||||
dumpindent(indent,buf);
|
||||
ncbytescat(buf,primtype);
|
||||
ncbytescat(buf," ");
|
||||
ncbytescat(buf,root->ncbasename);
|
||||
ncbytescat(buf,(root->ncbasename?root->ncbasename:"<?>"));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -27,7 +27,10 @@ dapodom_fromsegment(DCEsegment* segment, size_t startslice, size_t stopslice)
|
||||
odom->count[i] = segment->slices[i+startslice].count;
|
||||
odom->stride[i] = segment->slices[i+startslice].stride;
|
||||
odom->declsize[i] = segment->slices[i+startslice].declsize;
|
||||
odom->stop[i] = odom->start[i] + (odom->count[i]*odom->stride[i]);
|
||||
odom->stop[i] = odom->start[i] + odom->count[i];
|
||||
/* should the above line be instead?
|
||||
odom->stop[i] = odom->start[i] + (odom->count[i]*odom->stride[i]);
|
||||
*/
|
||||
odom->index[i] = odom->start[i];
|
||||
}
|
||||
return odom;
|
||||
@ -50,7 +53,7 @@ dapodom_new(size_t rank,
|
||||
odom->stride[i] = (size_t)(stride != NULL ? stride[i] : 1);
|
||||
odom->declsize[i] = (size != NULL ? size[i]
|
||||
: (odom->start[i]+odom->count[i]));
|
||||
odom->stop[i] = odom->start[i] + (odom->count[i]*odom->stride[i]);
|
||||
odom->stop[i] = odom->start[i] + odom->count[i];
|
||||
odom->index[i] = odom->start[i];
|
||||
}
|
||||
return odom;
|
||||
|
@ -350,93 +350,88 @@ collectocpath(OClink conn, OCddsnode node, NClist* path)
|
||||
OCtype octype;
|
||||
if(node == NULL) return;
|
||||
oc_dds_class(conn,node,&octype);
|
||||
if(octype == OC_Dataset) return;
|
||||
oc_dds_container(conn,node,&container);
|
||||
if(container != NULL)
|
||||
collectocpath(conn,container,path);
|
||||
if(octype != OC_Dataset) {
|
||||
oc_dds_container(conn,node,&container);
|
||||
if(container != NULL)
|
||||
collectocpath(conn,container,path);
|
||||
}
|
||||
nclistpush(path,(void*)node);
|
||||
}
|
||||
|
||||
char*
|
||||
makeocpathstring3(OClink conn, OCddsnode node, const char* sep)
|
||||
{
|
||||
int slen,i,len,first,seplen;
|
||||
char* pathname;
|
||||
int i,len,first;
|
||||
char* result;
|
||||
char* name;
|
||||
OCtype octype;
|
||||
NClist* ocpath = nclistnew();
|
||||
NClist* ocpath = NULL;
|
||||
NCbytes* pathname = NULL;
|
||||
|
||||
/* If we are asking for the dataset path only,
|
||||
then nclude it, otherwise elide it
|
||||
*/
|
||||
oc_dds_type(conn,node,&octype);
|
||||
if(octype == OC_Dataset) {
|
||||
oc_dds_name(conn,node,&name);
|
||||
return nulldup(name);
|
||||
}
|
||||
|
||||
ocpath = nclistnew();
|
||||
collectocpath(conn,node,ocpath);
|
||||
len = nclistlength(ocpath);
|
||||
assert(len > 0); /* dataset at least */
|
||||
|
||||
oc_dds_type(conn,node,&octype);
|
||||
if(octype == OC_Dataset)
|
||||
{pathname = nulldup(""); goto done;} /* Dataset */
|
||||
|
||||
seplen = strlen(sep);
|
||||
for(slen=0,i=0;i<len;i++) {
|
||||
pathname = ncbytesnew();
|
||||
for(first=1,i=1;i<len;i++) { /* start at 1 to skip dataset name */
|
||||
OCddsnode node = (OCddsnode)nclistget(ocpath,i);
|
||||
char* name;
|
||||
oc_dds_type(conn,node,&octype);
|
||||
if(octype == OC_Dataset) continue;
|
||||
oc_dds_name(conn,node,&name);
|
||||
slen += (name == NULL? 0 : strlen(name));
|
||||
slen += seplen;
|
||||
nullfree(name);
|
||||
}
|
||||
slen += 1; /* for null terminator*/
|
||||
pathname = (char*)malloc(slen);
|
||||
MEMCHECK(pathname,NULL);
|
||||
pathname[0] = '\0';
|
||||
for(first=1,i=0;i<len;i++) {
|
||||
OCddsnode node = (OCddsnode)nclistget(ocpath,i);
|
||||
char* name;
|
||||
oc_dds_type(conn,node,&octype);
|
||||
if(octype == OC_Dataset) continue;
|
||||
oc_dds_name(conn,node,&name);
|
||||
if(!first) strcat(pathname,sep);
|
||||
if(name != NULL) strcat(pathname,name);
|
||||
if(!first) ncbytescat(pathname,sep);
|
||||
ncbytescat(pathname,name);
|
||||
nullfree(name);
|
||||
first = 0;
|
||||
}
|
||||
done:
|
||||
result = ncbytesextract(pathname);
|
||||
ncbytesfree(pathname);
|
||||
nclistfree(ocpath);
|
||||
return pathname;
|
||||
return result;
|
||||
}
|
||||
|
||||
char*
|
||||
makepathstring3(NClist* path, const char* separator, int flags)
|
||||
{
|
||||
int slen,i,len,first,seplen;
|
||||
char* pathname;
|
||||
int i,len,first;
|
||||
NCbytes* pathname = NULL;
|
||||
char* result;
|
||||
CDFnode* node;
|
||||
|
||||
len = nclistlength(path);
|
||||
ASSERT(len > 0); /* dataset at least */
|
||||
seplen = strlen(separator);
|
||||
ASSERT(seplen > 0);
|
||||
for(slen=0,i=0;i<len;i++) {
|
||||
CDFnode* node = (CDFnode*)nclistget(path,i);
|
||||
if(node->nctype == NC_Dataset) continue;
|
||||
slen += strlen(node->ncbasename);
|
||||
slen += seplen;
|
||||
|
||||
if(len == 1) {/* dataset only */
|
||||
node = (CDFnode*)nclistget(path,0);
|
||||
return nulldup(node->ncbasename);
|
||||
}
|
||||
slen += 1; /* for null terminator*/
|
||||
pathname = (char*)malloc(slen);
|
||||
MEMCHECK(pathname,NULL);
|
||||
pathname[0] = '\0';
|
||||
|
||||
pathname = ncbytesnew();
|
||||
for(first=1,i=0;i<len;i++) {
|
||||
CDFnode* node = (CDFnode*)nclistget(path,i);
|
||||
char* name;
|
||||
if(!node->elided || (flags & PATHELIDE)==0) {
|
||||
if(node->nctype != NC_Dataset) {
|
||||
name = node->ncbasename;
|
||||
if(!first) strcat(pathname,separator);
|
||||
strcat(pathname,name);
|
||||
assert(name != NULL);
|
||||
if(!first) ncbytescat(pathname,separator);
|
||||
ncbytescat(pathname,name);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathname;
|
||||
result = ncbytesextract(pathname);
|
||||
ncbytesfree(pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* convert path to string using the ncname field */
|
||||
|
18
libdap2/env
18
libdap2/env
@ -10,11 +10,9 @@ PROG="$TOP/ncdump/ncdump"
|
||||
|
||||
P=`pwd`
|
||||
|
||||
#F="http://motherlode.ucar.edu:9080/thredds/dodsC/grib/NCEP/NAM/CONUS_12km/best"
|
||||
F="file://${TOP}/ncdap_test/testdata3/synth1"
|
||||
|
||||
#CON="OneD.amp,TwoD.amp,ThreeD.amp"
|
||||
|
||||
#F="http://geoport.whoi.edu/thredds/dodsC/bathy/crm_vol1.nc"
|
||||
#F="http://motherlode.ucar.edu:8081/dts/ingrid"
|
||||
F="file:///home/dmh/mach/trunk/ncdap_test/testdata3/synth9"
|
||||
|
||||
PARMS="[log]"
|
||||
#PARMS="${PARMS}[netcdf3]"
|
||||
@ -22,9 +20,9 @@ PARMS="[log]"
|
||||
#PARMS="${PARMS}[cache]"
|
||||
#PARMS="${PARMS}[prefetch]"
|
||||
#PARMS="${PARMS}[nocache]"
|
||||
#PARMS="${PARMS}[noprefetch]"
|
||||
PARMS="${PARMS}[noprefetch]"
|
||||
#PARMS="${PARMS}[wholevar]"
|
||||
#PARMS="${PARMS}[show=fetch]"
|
||||
PARMS="${PARMS}[show=fetch]"
|
||||
|
||||
# Pick in order
|
||||
if test "x$PROG" = x ; then
|
||||
@ -103,6 +101,8 @@ F="file://$TOP/ncdap_test/testdata3/$T"
|
||||
#F="http://motherlode.ucar.edu:8081/dts/test.06"
|
||||
#F="http://motherlode.ucar.edu:8081/thredds/dodsC/testdods/nametest3.nc"
|
||||
#F="http://ingrid.ldeo.columbia.edu/SOURCES/.USTOPO/dods"
|
||||
F="http://goldsmr2.sci.gsfc.nasa.gov/opendap/hyrax/MERRA/MAT1NXSLV.5.2.0/1990/01/MERRA100.prod.assim.tavg1_2d_slv_Nx.19900101.hdf"
|
||||
CON="U50M_EOSGRID_Data_Fields[0:23][282:282][441:441]"
|
||||
#F="http://motherlode.ucar.edu:9080/thredds/dodsC/grib/NCEP/NAM/CONUS_12km/best"
|
||||
#CON="OneD.amp,TwoD.amp,ThreeD.amp"
|
||||
fi
|
||||
|
||||
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include "fbits.h"
|
||||
#include "dceconstraints.h"
|
||||
|
||||
#include "oc.h"
|
||||
|
||||
#include "netcdf.h"
|
||||
#include "ncdispatch.h"
|
||||
#include "nc.h"
|
||||
@ -34,6 +32,8 @@
|
||||
/* netcdf overrides*/
|
||||
#include "dapnc.h"
|
||||
|
||||
#include "oc.h"
|
||||
|
||||
#include "dapdebug.h"
|
||||
#include "daputil.h"
|
||||
|
||||
|
@ -17,7 +17,7 @@ nestedDAS.dmp NestedSeq2.dmp NestedSeq.dmp \
|
||||
OverideExample.dmp pbug0001b.dmp saco1.nc.dmp \
|
||||
SimpleDrdsExample.dmp synth1.dmp synth2.dmp \
|
||||
synth3.dmp synth4.dmp synth5.dmp \
|
||||
synth6.dmp synth7.dmp synth8.dmp synth10.dmp \
|
||||
synth6.dmp synth7.dmp synth8.dmp synth9.dmp synth10.dmp \
|
||||
test.01.dmp test.02.dmp test.03.dmp \
|
||||
test.04.dmp test.05.dmp test.06a.dmp \
|
||||
test.07a.dmp test.07.dmp test.21.dmp \
|
||||
|
9
ncdap_test/expected3/synth9.dmp
Normal file
9
ncdap_test/expected3/synth9.dmp
Normal file
@ -0,0 +1,9 @@
|
||||
netcdf synth9 {
|
||||
dimensions:
|
||||
lat = 2 ;
|
||||
long = 2 ;
|
||||
variables:
|
||||
int lat(lat) ;
|
||||
int long(long) ;
|
||||
float G1(lat, long) ;
|
||||
}
|
@ -14,6 +14,7 @@ synth5.das synth5.dds synth5.dods \
|
||||
synth6.das synth6.dds synth6.dods \
|
||||
synth7.das synth7.dds synth7.dods \
|
||||
synth8.das synth8.dds synth8.dods \
|
||||
synth9.das synth9.dds synth9.dods \
|
||||
synth10.das synth10.dds synth10.dods \
|
||||
123bears.nc.das 123bears.nc.dds 123bears.nc.dods \
|
||||
123.nc.das 123.nc.dds 123.nc.dods \
|
||||
|
0
ncdap_test/testdata3/synth9.dods
Normal file
0
ncdap_test/testdata3/synth9.dods
Normal file
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
#set -x
|
||||
set -x
|
||||
quiet=0
|
||||
leakcheck=0
|
||||
|
||||
@ -23,6 +23,8 @@ expected4="${srcdir}/expected4"
|
||||
# get the list of test files
|
||||
. ${srcdir}/tst_ncdap_shared.sh
|
||||
|
||||
FLAGS=
|
||||
|
||||
case "$mode" in
|
||||
*3)
|
||||
EXPECTED="$expected3"
|
||||
@ -41,6 +43,11 @@ file*)
|
||||
TESTURL="$FILEURL"
|
||||
TESTSET="$FILETESTS"
|
||||
;;
|
||||
dds*)
|
||||
TESTURL="[noprefetch]$FILEURL"
|
||||
TESTSET="$DDSTESTS"
|
||||
FLAGS="-h"
|
||||
;;
|
||||
remote*)
|
||||
TESTURL="$REMOTEURL"
|
||||
TITLE="Remote $TITLE"
|
||||
@ -50,7 +57,7 @@ esac
|
||||
|
||||
RESULTSDIR="./results"
|
||||
# Locate some tools
|
||||
NCDUMP="${builddir}/ncdump/ncdump"
|
||||
NCDUMP="${builddir}/ncdump/ncdump $FLAGS"
|
||||
if test "x$leakcheck" = "x1" ; then
|
||||
VALGRIND="valgrind -q --error-exitcode=2 --leak-check=full"
|
||||
else
|
||||
|
@ -28,5 +28,6 @@ fi
|
||||
cd ${builddir}/ncdap_test
|
||||
|
||||
|
||||
exec sh $X ${srcdir}/tst_ncdap.sh "$srcdir" "$builddir" "file3" $grind
|
||||
#exec sh $X ${srcdir}/tst_ncdap.sh "$srcdir" "$builddir" "file3" $grind
|
||||
exec sh $X ${srcdir}/tst_ncdap.sh "$srcdir" "$builddir" "dds3" $grind
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
FILEURL="file://${testdata3}"
|
||||
|
||||
# Synth8 still fails
|
||||
|
||||
SYNTHETICDATA="synth1 synth2 synth3 synth4 synth5 synth6 synth7 synth10"
|
||||
SYNTHETICDDS="synth9"
|
||||
|
||||
|
||||
ACTUALDATA1=\
|
||||
@ -50,4 +52,6 @@ if [ `uname | cut -d "_" -f 1` = "MINGW32" ]; then
|
||||
fi
|
||||
|
||||
FILETESTS="${SYNTHETICDATA} ${ACTUALDATA1} ${ACTUALDATA2}"
|
||||
#DDSTESTS intersect FILETESTS should empty
|
||||
DDSTESTS="${SYNTHETICDDS}"
|
||||
|
||||
|
12
oc2/oc.c
12
oc2/oc.c
@ -1750,6 +1750,18 @@ oc_get_lastmodified_data(OCobject link)
|
||||
return state->datalastmodified;
|
||||
}
|
||||
|
||||
/* Given an arbitrary OCnode, return the connection of which it is a part */
|
||||
OCerror
|
||||
oc_get_connection(OCobject ddsnode, OCobject* linkp)
|
||||
{
|
||||
OCnode* node;
|
||||
OCVERIFY(OC_Node,ddsnode);
|
||||
OCDEREF(OCnode*,node,ddsnode);
|
||||
if(linkp) *linkp = node->root->tree->state;
|
||||
return OC_NOERR;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Attempt to retrieve a dataset using a specified URL
|
||||
and using the DAP protocol.
|
||||
|
3
oc2/oc.h
3
oc2/oc.h
@ -510,6 +510,9 @@ extern OCerror oc_svcerrordata(OClink link, char** codep,
|
||||
/**************************************************/
|
||||
/* Experimental/Undocumented */
|
||||
|
||||
/* Given an arbitrary OCnode, return the connection of which it is a part */
|
||||
extern OCerror oc_get_connection(OCobject ocnode, OCobject* linkp);
|
||||
|
||||
/* Resend a url as a head request to check the Last-Modified time */
|
||||
extern OCerror oc_update_lastmodified_data(OClink);
|
||||
|
||||
|
@ -8,13 +8,8 @@
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define OCDEBUG
|
||||
#define DAPDEBUG 1
|
||||
#endif
|
||||
|
||||
#ifdef OCDEBUG
|
||||
#define OCVERBOSE
|
||||
#ifndef OCDEBUG
|
||||
#undef OCDEBUG
|
||||
#endif
|
||||
|
||||
/* OCCATCHERROR is used to detect errors as close
|
||||
|
@ -205,4 +205,5 @@ extern int ocinternalinitialize(void);
|
||||
|
||||
extern OCerror ocsetuseragent(OCstate* state, const char* agent);
|
||||
|
||||
|
||||
#endif /*COMMON_H*/
|
||||
|
Loading…
Reference in New Issue
Block a user