123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800 |
- /*********************************************************************
- * Copyright 1993, UCAR/Unidata
- * See netcdf/COPYRIGHT file for copying and redistribution conditions.
- *********************************************************************/
- #include "ncdap3.h"
- #include "nc3dispatch.h"
- #include "ncd3dispatch.h"
- #include "dapalign.h"
- #include "dapdump.h"
- #include "oc.h"
- #define getncid(drno) (((NC*)drno)->ext_ncid)
- /*Forward*/
- static NCerror getseqdimsize(NCDAPCOMMON*, CDFnode* seq, size_t* sizep);
- static int fieldindex(CDFnode* parent, CDFnode* child);
- static NCerror countsequence(NCDAPCOMMON*, CDFnode* node, size_t*);
- static NCerror makeseqdim(NCDAPCOMMON*, CDFnode* node, size_t, CDFnode**);
- static NCerror computeseqcountconstraints3(NCDAPCOMMON*,CDFnode*,NCbytes*);
- static void computeseqcountconstraints3r(NCDAPCOMMON*, CDFnode*, CDFnode**);
- void
- freegetvara(Getvara* vara)
- {
- if(vara == NULL) return;
- dcefree((DCEnode*)vara->varaprojection);
- nullfree(vara);
- }
- NCerror
- freeNCDAPCOMMON(NCDAPCOMMON* dapcomm)
- {
- /* abort the metadata file */
- (void)nc_abort(getncid(dapcomm));
- freenccache(dapcomm,dapcomm->cdf.cache);
- nclistfree(dapcomm->cdf.varnodes);
- nclistfree(dapcomm->cdf.seqnodes);
- nclistfree(dapcomm->cdf.gridnodes);
- nclistfree(dapcomm->cdf.usertypes);
- nullfree(dapcomm->cdf.recorddimname);
- /* free the trees */
- freecdfroot34(dapcomm->cdf.ddsroot);
- dapcomm->cdf.ddsroot = NULL;
- freecdfroot34(dapcomm->cdf.fullddsroot);
- dapcomm->cdf.fullddsroot = NULL;
- if(dapcomm->oc.ocdasroot != NULL)
- oc_root_free(dapcomm->oc.conn,dapcomm->oc.ocdasroot);
- dapcomm->oc.ocdasroot = NULL;
- oc_close(dapcomm->oc.conn); /* also reclaims remaining OC trees */
- nc_urifree(dapcomm->oc.url);
- nullfree(dapcomm->oc.urltext);
- nullfree(dapcomm->oc.rawurltext);
- dcefree((DCEnode*)dapcomm->oc.dapconstraint);
- dapcomm->oc.dapconstraint = NULL;
- free(dapcomm);
- return NC_NOERR;
- }
- NCerror
- addstringdims(NCDAPCOMMON* dapcomm)
- {
- /* for all variables of string type, we will need another dimension
- to represent the string; Accumulate the needed sizes and create
- the dimensions with a specific name: either as specified
- in DODS{...} attribute set or defaulting to the variable name.
- All such dimensions are global.
- */
- int i;
- NClist* varnodes = dapcomm->cdf.varnodes;
- CDFnode* globalsdim = NULL;
- char dimname[4096];
- size_t dimsize;
- /* Start by creating the global string dimension */
- snprintf(dimname,sizeof(dimname),"maxStrlen%lu",
- (unsigned long)dapcomm->cdf.defaultstringlength);
- globalsdim = makecdfnode34(dapcomm, dimname, OC_Dimension, OCNULL,
- dapcomm->cdf.ddsroot);
- nclistpush(dapcomm->cdf.ddsroot->tree->nodes,(ncelem)globalsdim);
- DIMFLAGSET(globalsdim,CDFDIMSTRING);
- globalsdim->dim.declsize = dapcomm->cdf.defaultstringlength;
- globalsdim->dim.declsize0 = globalsdim->dim.declsize;
- globalsdim->dim.array = dapcomm->cdf.ddsroot;
- globalsdim->ncbasename = cdflegalname3(dimname);
- globalsdim->ncfullname = nulldup(globalsdim->ncbasename);
- dapcomm->cdf.globalstringdim = globalsdim;
- for(i=0;i<nclistlength(varnodes);i++) {
- CDFnode* var = (CDFnode*)nclistget(varnodes,i);
- CDFnode* sdim = NULL;
- /* Does this node need a string dim? */
- if(var->etype != NC_STRING && var->etype != NC_URL) continue;
- dimsize = 0;
- if(var->dodsspecial.maxstrlen > 0)
- dimsize = var->dodsspecial.maxstrlen;
- else
- dimsize = var->maxstringlength;
- /* check is a variable-specific string length was specified */
- if(dimsize == 0)
- sdim = dapcomm->cdf.globalstringdim; /* use default */
- else {
- /* create a psuedo dimension for the charification of the string*/
- if(var->dodsspecial.dimname != NULL)
- strncpy(dimname,var->dodsspecial.dimname,sizeof(dimname));
- else
- snprintf(dimname,sizeof(dimname),"maxStrlen%lu",
- (unsigned long)dimsize);
- sdim = makecdfnode34(dapcomm, dimname, OC_Dimension, OCNULL,
- dapcomm->cdf.ddsroot);
- if(sdim == NULL) return THROW(NC_ENOMEM);
- nclistpush(dapcomm->cdf.ddsroot->tree->nodes,(ncelem)sdim);
- DIMFLAGSET(sdim,CDFDIMSTRING);
- sdim->dim.declsize = dimsize;
- sdim->dim.declsize0 = dimsize;
- sdim->dim.array = var;
- sdim->ncbasename = cdflegalname3(sdim->ocname);
- sdim->ncfullname = nulldup(sdim->ncbasename);
- }
- /* tag the variable with its string dimension*/
- var->array.stringdim = sdim;
- }
- return NC_NOERR;
- }
- NCerror
- defrecorddim3(NCDAPCOMMON* dapcomm)
- {
- unsigned int i;
- NCerror ncstat = NC_NOERR;
- NClist* basedims;
- if(dapcomm->cdf.recorddimname == NULL) return NC_NOERR; /* ignore */
- /* Locate the base dimension matching the record dim */
- basedims = dapcomm->cdf.dimnodes;
- for(i=0;i<nclistlength(basedims);i++) {
- CDFnode* dim = (CDFnode*)nclistget(basedims,i);
- if(strcmp(dim->ocname,dapcomm->cdf.recorddimname) != 0) continue;
- DIMFLAGSET(dim,CDFDIMRECORD);
- dapcomm->cdf.recorddim = dim;
- break;
- }
- return ncstat;
- }
- NCerror
- defseqdims(NCDAPCOMMON* dapcomm)
- {
- unsigned int i;
- NCerror ncstat = NC_NOERR;
- int seqdims = 1; /* default is to compute seq dims counts */
- /* Does the user want to compute actual sequence sizes? */
- if(paramvalue34(dapcomm,"noseqdims")) seqdims = 0;
- /*
- Compute and define pseudo dimensions for sequences
- meeting the following qualifications:
- 1. all parents (transitively) of the sequence must
- be either a dataset or a scalar structure.
- 2. it must be possible to find a usable sequence constraint.
- All other sequences will be ignored.
- */
- for(i=0;i<nclistlength(dapcomm->cdf.seqnodes);i++) {
- CDFnode* seq = (CDFnode*)nclistget(dapcomm->cdf.seqnodes,i);
- size_t seqsize;
- CDFnode* sqdim = NULL;
- CDFnode* container;
- /* Does this sequence match the requirements for use ? */
- seq->usesequence = 1; /* assume */
- for(container=seq->container;container != NULL;container=container->container) {
- if(container->nctype == NC_Dataset) break;
- if(container->nctype != NC_Structure
- || nclistlength(container->array.dimset0) > 0)
- {seq->usesequence = 0; break;}/* no good */
- }
- /* Does the user want us to compute the actual sequence dim size? */
- if(seq->usesequence && seqdims) {
- ncstat = getseqdimsize(dapcomm,seq,&seqsize);
- if(ncstat != NC_NOERR) {
- /* Cannot read sequence; mark as unusable */
- seq->usesequence = 0;
- }
- } else { /* !seqdims default to size = 1 */
- seqsize = 1;
- }
- if(seq->usesequence) {
- /* Note: we are making the dimension in the dds root tree */
- ncstat = makeseqdim(dapcomm,seq,seqsize,&sqdim);
- if(ncstat) goto fail;
- seq->array.seqdim = sqdim;
- } else
- seq->array.seqdim = NULL;
- }
- fail:
- return ncstat;
- }
- static NCerror
- getseqdimsize(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t* sizep)
- {
- NCerror ncstat = NC_NOERR;
- OCerror ocstat = OC_NOERR;
- OCconnection conn = dapcomm->oc.conn;
- OCdata rootcontent = OCNULL;
- OCobject ocroot;
- CDFnode* dxdroot;
- CDFnode* xseq;
- NCbytes* seqcountconstraints = ncbytesnew();
- size_t seqsize;
- /* Read the minimal amount of data in order to get the count */
- /* If the url is unconstrainable, then get the whole thing */
- computeseqcountconstraints3(dapcomm,seq,seqcountconstraints);
- #ifdef DEBUG
- fprintf(stderr,"seqcountconstraints: %s\n",ncbytescontents(seqcountconstraints));
- #endif
- /* Fetch the minimal data */
- if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
- ocstat = dap_fetch(dapcomm,conn,NULL,OCDATADDS,&ocroot);
- else
- ocstat = dap_fetch(dapcomm,conn,ncbytescontents(seqcountconstraints),OCDATADDS,&ocroot);
- if(ocstat) goto fail;
- ncstat = buildcdftree34(dapcomm,ocroot,OCDATA,&dxdroot);
- if(ncstat) goto fail;
- /* attach DATADDS to DDS */
- ncstat = attach34(dxdroot,seq);
- if(ncstat) goto fail;
- /* WARNING: we are now switching to datadds tree */
- xseq = seq->attachment;
- ncstat = countsequence(dapcomm,xseq,&seqsize);
- if(ncstat) goto fail;
- #ifdef DEBUG
- fprintf(stderr,"sequencesize: %s = %lu\n",seq->ocname,(unsigned long)seqsize);
- #endif
- /* throw away the fetch'd trees */
- unattach34(dapcomm->cdf.ddsroot);
- freecdfroot34(dxdroot);
- if(ncstat != NC_NOERR) {
- /* Cannot get DATADDDS*/
- char* code;
- char* msg;
- long httperr;
- oc_svcerrordata(dapcomm->oc.conn,&code,&msg,&httperr);
- if(code != NULL) {
- nclog(NCLOGERR,"oc_fetch_datadds failed: %s %s %l",
- code,msg,httperr);
- }
- ocstat = OC_NOERR;
- }
- if(sizep) *sizep = seqsize;
- fail:
- ncbytesfree(seqcountconstraints);
- oc_data_free(conn,rootcontent);
- if(ocstat) ncstat = ocerrtoncerr(ocstat);
- return ncstat;
- }
- static NCerror
- makeseqdim(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t count, CDFnode** sqdimp)
- {
- CDFnode* sqdim;
- CDFnode* root = seq->root;
- CDFtree* tree = root->tree;
- /* build the dimension with given size; keep the dimension anonymous */
- sqdim = makecdfnode34(dapcomm,seq->ocname,OC_Dimension,OCNULL,root);
- if(sqdim == NULL) return THROW(NC_ENOMEM);
- nclistpush(tree->nodes,(ncelem)sqdim);
- /* Assign a name to the sequence node */
- sqdim->ncbasename = cdflegalname3(seq->ocname);
- sqdim->ncfullname = nulldup(sqdim->ncbasename);
- DIMFLAGSET(sqdim,CDFDIMSEQ);
- sqdim->dim.declsize = count;
- sqdim->dim.declsize0 = count;
- sqdim->dim.array = seq;
- if(sqdimp) *sqdimp = sqdim;
- return NC_NOERR;
- }
- static NCerror
- countsequence(NCDAPCOMMON* dapcomm, CDFnode* xseq, size_t* sizep)
- {
- unsigned int i;
- NClist* path = nclistnew();
- int index;
- OCerror ocstat = OC_NOERR;
- NCerror ncstat = NC_NOERR;
- OCconnection conn = dapcomm->oc.conn;
- size_t recordcount;
- CDFnode* xroot;
- CDFnode* current;
- OCdata datacontainer = OCNULL;
- OCmode mode;
- ASSERT((xseq->nctype == NC_Sequence));
- /* collect the path to the sequence node */
- collectnodepath3(xseq,path,WITHDATASET);
- /* Get tree root */
- xroot = xseq->root;
- datacontainer = oc_data_new(conn);
- ocstat = oc_data_root(conn,xroot->tree->ocroot,datacontainer);
- if(ocstat) goto fail;
- /* walk to the sequence object; control the movement to the next node
- based on mode */
- current = (CDFnode*)nclistget(path,0);
- for(i=0;;) {
- OCdata child = OCNULL;
- CDFnode* next = NULL;
- ocstat = oc_data_mode(conn,datacontainer,&mode);
- if(ocstat != OC_NOERR) goto fail;
- switch (mode) {
- case OCFIELDMODE:
- i++;
- next = (CDFnode*)nclistget(path,i);
- index = fieldindex(current,next);
- break;
- case OCARRAYMODE:
- index = 0;
- break;
- case OCSEQUENCEMODE:
- goto exitloop;
- default:
- PANIC("unexpected mode");
- return NC_EINVAL;
- }
- child = oc_data_new(conn);
- ocstat = oc_data_ith(conn,datacontainer,index,child);
- if(ocstat) goto fail;
- /* move to the next node only if it is defined */
- if(next != NULL)
- current = next;
- oc_data_free(conn,datacontainer);
- datacontainer = child;
- }
- exitloop:
- ASSERT(current == xseq && mode == OCSEQUENCEMODE);
- oc_data_count(conn,datacontainer,&recordcount);
- if(sizep) *sizep = recordcount;
- fail:
- oc_data_free(conn,datacontainer);
- nclistfree(path);
- if(ocstat) ncstat = ocerrtoncerr(ocstat);
- return THROW(ncstat);
- }
- static int
- fieldindex(CDFnode* parent, CDFnode* child)
- {
- unsigned int i;
- for(i=0;i<nclistlength(parent->subnodes);i++) {
- CDFnode* node = (CDFnode*)nclistget(parent->subnodes,i);
- if(node == child) return i;
- }
- return -1;
- }
- NCerror
- showprojection3(NCDAPCOMMON* dapcomm, CDFnode* var)
- {
- int i,rank;
- NCerror ncstat = NC_NOERR;
- NCbytes* projection = ncbytesnew();
- NClist* path = nclistnew();
- NC* drno = dapcomm->controller;
- /* Collect the set of DDS node name forming the xpath */
- collectnodepath3(var,path,WITHOUTDATASET);
- for(i=0;i<nclistlength(path);i++) {
- CDFnode* node = (CDFnode*)nclistget(path,i);
- if(i > 0) ncbytescat(projection,".");
- ncbytescat(projection,node->ocname);
- }
- /* Now, add the dimension info */
- rank = nclistlength(var->array.dimset0);
- for(i=0;i<rank;i++) {
- CDFnode* dim = (CDFnode*)nclistget(var->array.dimset0,i);
- char tmp[32];
- ncbytescat(projection,"[");
- snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)dim->dim.declsize);
- ncbytescat(projection,tmp);
- ncbytescat(projection,"]");
- }
- /* Define the attribute */
- ncstat = nc_put_att_text(getncid(drno),var->ncid,
- "_projection",
- ncbyteslength(projection),
- ncbytescontents(projection));
- return ncstat;
- }
- /*
- This is more complex than one might think. We want to find
- a path to a variable inside the given node so that we can
- ask for a single instance of that variable to minimize the
- amount of data we retrieve. However, we want to avoid passing
- through any nested sequence. This is possible because of the way
- that sequencecheck() works.
- TODO: some servers will not accept an unconstrained fetch, so
- make sure we always have a constraint.
- */
- static NCerror
- computeseqcountconstraints3(NCDAPCOMMON* dapcomm, CDFnode* seq, NCbytes* seqcountconstraints)
- {
- int i,j;
- NClist* path = NULL;
- CDFnode* var = NULL;
- ASSERT(seq->nctype == NC_Sequence);
- computeseqcountconstraints3r(dapcomm,seq,&var);
- ASSERT((var != NULL));
- /* Compute var path */
- path = nclistnew();
- collectnodepath3(var,path,WITHOUTDATASET);
- /* construct the projection path using minimal index values */
- for(i=0;i<nclistlength(path);i++) {
- CDFnode* node = (CDFnode*)nclistget(path,i);
- if(i > 0) ncbytescat(seqcountconstraints,".");
- ncbytescat(seqcountconstraints,node->ocname);
- if(node == seq) {
- /* Use the limit */
- if(node->sequencelimit > 0) {
- char tmp[64];
- snprintf(tmp,sizeof(tmp),"[0:%lu]",
- (unsigned long)(node->sequencelimit - 1));
- ncbytescat(seqcountconstraints,tmp);
- }
- } else if(nclistlength(node->array.dimset0) > 0) {
- int ndims = nclistlength(node->array.dimset0);
- for(j=0;j<ndims;j++) {
- CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j);
- if(DIMFLAG(dim,CDFDIMSTRING)) {
- ASSERT((j == (ndims - 1)));
- break;
- }
- ncbytescat(seqcountconstraints,"[0]");
- }
- }
- }
- /* Finally, add in any selection from the original URL */
- if(dapcomm->oc.url->selection != NULL)
- ncbytescat(seqcountconstraints,dapcomm->oc.url->selection);
- nclistfree(path);
- return NC_NOERR;
- }
- /* Given an existing candidate, see if we prefer newchoice */
- static CDFnode*
- prefer(CDFnode* candidate, CDFnode* newchoice)
- {
- nc_type newtyp;
- nc_type cantyp;
- int newisstring;
- int canisstring;
- int newisscalar;
- int canisscalar;
- /* always choose !null over null */
- if(newchoice == NULL)
- return candidate;
- if(candidate == NULL)
- return newchoice;
- newtyp = newchoice->etype;
- cantyp = candidate->etype;
- newisstring = (newtyp == NC_STRING || newtyp == NC_URL);
- canisstring = (cantyp == NC_STRING || cantyp == NC_URL);
- newisscalar = (nclistlength(newchoice->array.dimset0) == 0);
- canisscalar = (nclistlength(candidate->array.dimset0) == 0);
- ASSERT(candidate->nctype == NC_Primitive && newchoice->nctype == NC_Primitive);
-
- /* choose non-string over string */
- if(canisstring && !newisstring)
- return newchoice;
- if(!canisstring && newisstring)
- return candidate;
- /* choose scalar over array */
- if(canisscalar && !newisscalar)
- return candidate;
- if(!canisscalar && newisscalar)
- return candidate;
- /* otherwise choose existing candidate */
- return candidate;
- }
- /* computeseqcountconstraints3 recursive helper function */
- static void
- computeseqcountconstraints3r(NCDAPCOMMON* dapcomm, CDFnode* node, CDFnode** candidatep)
- {
- CDFnode* candidate;
- CDFnode* compound;
- unsigned int i;
- candidate = NULL;
- compound = NULL;
- for(i=0;i<nclistlength(node->subnodes);i++){
- CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,i);
- if(subnode->nctype == NC_Structure || subnode->nctype == NC_Grid)
- compound = subnode; /* save for later recursion */
- else if(subnode->nctype == NC_Primitive) {
- candidate = prefer(candidate,subnode);
- }
- }
- if(candidate == NULL && compound == NULL) {
- PANIC("cannot find candidate for seqcountconstraints for a sequence");
- } else if(candidate != NULL && candidatep != NULL) {
- *candidatep = candidate;
- } else { /* compound != NULL by construction */
- /* recurse on a nested grids or strucures */
- computeseqcountconstraints3r(dapcomm,compound,candidatep);
- }
- }
- static unsigned long
- cdftotalsize3(NClist* dimensions)
- {
- unsigned int i;
- unsigned long total = 1;
- if(dimensions != NULL) {
- for(i=0;i<nclistlength(dimensions);i++) {
- CDFnode* dim = (CDFnode*)nclistget(dimensions,i);
- total *= dim->dim.declsize;
- }
- }
- return total;
- }
- /* Estimate variables sizes and then resort the variable list
- by that size
- */
- void
- estimatevarsizes3(NCDAPCOMMON* dapcomm)
- {
- int ivar;
- unsigned int rank;
- size_t totalsize = 0;
- for(ivar=0;ivar<nclistlength(dapcomm->cdf.varnodes);ivar++) {
- CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,ivar);
- NClist* ncdims = var->array.dimset0;
- rank = nclistlength(ncdims);
- if(rank == 0) { /* use instance size of the type */
- var->estimatedsize = nctypesizeof(var->etype);
- #ifdef DEBUG1
- fprintf(stderr,"scalar %s.estimatedsize = %lu\n",
- makecdfpathstring3(var,"."),var->estimatedsize);
- #endif
- } else {
- unsigned long size = cdftotalsize3(ncdims);
- size *= nctypesizeof(var->etype);
- #ifdef DEBUG1
- fprintf(stderr,"array %s(%u).estimatedsize = %lu\n",
- makecdfpathstring3(var,"."),rank,size);
- #endif
- var->estimatedsize = size;
- }
- totalsize += var->estimatedsize;
- }
- #ifdef DEBUG1
- fprintf(stderr,"total estimatedsize = %lu\n",totalsize);
- #endif
- dapcomm->cdf.totalestimatedsize = totalsize;
- }
- NCerror
- fetchtemplatemetadata3(NCDAPCOMMON* dapcomm)
- {
- NCerror ncstat = NC_NOERR;
- OCerror ocstat = OC_NOERR;
- OCobject ocroot = OCNULL;
- CDFnode* ddsroot = NULL;
- char* ce = NULL;
- /* Temporary hack: we need to get the selection string
- from the url
- */
- /* Get (almost) unconstrained DDS; In order to handle functions
- correctly, those selections must always be included
- */
- if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
- ce = NULL;
- else
- ce = nulldup(dapcomm->oc.url->selection);
- /* Get selection constrained DDS */
- ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDDS,&ocroot);
- if(ocstat != OC_NOERR) {
- /* Special Hack. If the protocol is file, then see if
- we can get the dds from the .dods file
- */
- if(strcmp(dapcomm->oc.url->protocol,"file") != 0) {
- THROWCHK(ocstat); goto done;
- }
- /* Fetch the data dds */
- ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDATADDS,&ocroot);
- if(ocstat != OC_NOERR) {
- THROWCHK(ocstat); goto done;
- }
- /* Note what we did */
- nclog(NCLOGWARN,"Cannot locate .dds file, using .dods file");
- }
- /* Get selection constrained DAS */
- ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDAS,&dapcomm->oc.ocdasroot);
- if(ocstat != OC_NOERR) {
- /* Ignore but complain */
- nclog(NCLOGWARN,"Could not read DAS; ignored");
- dapcomm->oc.ocdasroot = OCNULL;
- ocstat = OC_NOERR;
- }
- /* Construct our parallel dds tree */
- ncstat = buildcdftree34(dapcomm,ocroot,OCDDS,&ddsroot);
- if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
- dapcomm->cdf.fullddsroot = ddsroot;
- done:
- nullfree(ce);
- if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
- return ncstat;
- }
- NCerror
- fetchconstrainedmetadata3(NCDAPCOMMON* dapcomm)
- {
- NCerror ncstat = NC_NOERR;
- OCerror ocstat = OC_NOERR;
- OCobject ocroot;
- CDFnode* ddsroot; /* constrained */
- char* ce = NULL;
- if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
- ce = NULL;
- else
- ce = buildconstraintstring3(dapcomm->oc.dapconstraint);
- {
- ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDDS,&ocroot);
- if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;}
- /* Construct our parallel dds tree; including attributes*/
- ncstat = buildcdftree34(dapcomm,ocroot,OCDDS,&ddsroot);
- if(ncstat) goto fail;
- dapcomm->cdf.ddsroot = ddsroot;
- if(!FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
- /* fix DAP server problem by adding back any missing grid structure nodes */
- ncstat = regrid3(ddsroot,dapcomm->cdf.fullddsroot,dapcomm->oc.dapconstraint->projections);
- if(ncstat) goto fail;
- }
- #ifdef DEBUG
- fprintf(stderr,"constrained:\n%s",dumptree(ddsroot));
- #endif
- /* Combine DDS and DAS */
- if(dapcomm->oc.ocdasroot != NULL) {
- ncstat = dapmerge3(dapcomm,ddsroot,dapcomm->oc.ocdasroot);
- if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;}
- }
- /* map the constrained DDS to the unconstrained DDS */
- ncstat = mapnodes3(ddsroot,dapcomm->cdf.fullddsroot);
- if(ncstat) goto fail;
- }
- fail:
- nullfree(ce);
- if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
- return ncstat;
- }
- /* Suppress variables not in usable sequences*/
- NCerror
- suppressunusablevars3(NCDAPCOMMON* dapcomm)
- {
- int i,j;
- int found = 1;
- NClist* path = nclistnew();
- while(found) {
- found = 0;
- /* Walk backwards to aid removal semantics */
- for(i=nclistlength(dapcomm->cdf.varnodes)-1;i>=0;i--) {
- CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,i);
- /* See if this var is under an unusable sequence */
- nclistclear(path);
- collectnodepath3(var,path,WITHOUTDATASET);
- for(j=0;j<nclistlength(path);j++) {
- CDFnode* node = (CDFnode*)nclistget(path,j);
- if(node->nctype == NC_Sequence
- && !node->usesequence) {
- #ifdef DEBUG
- fprintf(stderr,"suppressing var in unusable sequence: %s.%s\n",node->ncfullname,var->ncbasename);
- #endif
- found = 1;
- break;
- }
- }
- if(found) break;
- }
- if(found) nclistremove(dapcomm->cdf.varnodes,i);
- }
- nclistfree(path);
- return NC_NOERR;
- }
- /*
- For variables which have a zero size dimension,
- make them invisible.
- */
- NCerror
- fixzerodims3(NCDAPCOMMON* dapcomm)
- {
- int i,j;
- for(i=0;i<nclistlength(dapcomm->cdf.varnodes);i++) {
- CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,i);
- NClist* ncdims = var->array.dimsetplus;
- if(nclistlength(ncdims) == 0) continue;
- for(j=0;j<nclistlength(ncdims);j++) {
- CDFnode* dim = (CDFnode*)nclistget(ncdims,j);
- if(dim->dim.declsize == 0) {
- /* make node invisible */
- var->visible = 0;
- var->zerodim = 1;
- }
- }
- }
- return NC_NOERR;
- }
- void
- applyclientparamcontrols3(NCDAPCOMMON* dapcomm)
- {
- /* clear the flags */
- CLRFLAG(dapcomm->controls,NCF_CACHE);
- CLRFLAG(dapcomm->controls,NCF_PREFETCH);
- CLRFLAG(dapcomm->controls,NCF_SHOWFETCH);
- CLRFLAG(dapcomm->controls,NCF_NC3);
- CLRFLAG(dapcomm->controls,NCF_NCDAP);
- /* Turn on any default on flags */
- SETFLAG(dapcomm->controls,DFALT_ON_FLAGS);
- SETFLAG(dapcomm->controls,(NCF_NC3|NCF_NCDAP));
- /* enable/disable caching */
- if(paramcheck34(dapcomm,"cache",NULL))
- SETFLAG(dapcomm->controls,NCF_CACHE);
- else if(paramcheck34(dapcomm,"nocache",NULL))
- CLRFLAG(dapcomm->controls,NCF_CACHE);
- /* enable/disable cache prefetch */
- if(paramcheck34(dapcomm,"prefetch",NULL))
- SETFLAG(dapcomm->controls,NCF_PREFETCH);
- else if(paramcheck34(dapcomm,"noprefetch",NULL))
- CLRFLAG(dapcomm->controls,NCF_PREFETCH);
- if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
- SETFLAG(dapcomm->controls,NCF_CACHE);
- if(paramcheck34(dapcomm,"show","fetch"))
- SETFLAG(dapcomm->controls,NCF_SHOWFETCH);
- nclog(NCLOGNOTE,"Caching=%d",FLAGSET(dapcomm->controls,NCF_CACHE));
- }
|