jira: NCF-232: bad conversion of grids

This commit is contained in:
Dennis Heimbigner 2013-02-26 04:31:06 +00:00
parent ba6bcca272
commit 6cf31dcf2d
22 changed files with 276 additions and 169 deletions

2
cf
View File

@ -20,7 +20,7 @@ cmds=""
#cmds="all"
#cmds="all check"
#cmds="all dist"
#cmds="all distcheck"
cmds="all distcheck"
#cmds="$cmds install"
fi

View File

@ -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;
}

View File

@ -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.

View File

@ -5,7 +5,7 @@
*********************************************************************/
#include "ncdap3.h"
#include "dapdebug.h"
#include "dapdump.h"
#include "dapdump.h"
#include "dceparselex.h"

View File

@ -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,".");
}

View File

@ -6,6 +6,12 @@
#ifndef DEBUG_H
#define DEBUG_H
#if 0
#define DAPDEBUG 1
#define OCDEBUG
#endif
#include "ocdebug.h"
#ifdef DAPDEBUG

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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"

View File

@ -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 \

View File

@ -0,0 +1,9 @@
netcdf synth9 {
dimensions:
lat = 2 ;
long = 2 ;
variables:
int lat(lat) ;
int long(long) ;
float G1(lat, long) ;
}

View File

@ -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 \

View File

View 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

View File

@ -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

View File

@ -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}"

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -205,4 +205,5 @@ extern int ocinternalinitialize(void);
extern OCerror ocsetuseragent(OCstate* state, const char* agent);
#endif /*COMMON_H*/