source: XIOS/trunk/extern/src_netcdf4/ncdap3a.c @ 409

Last change on this file since 409 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 23.6 KB
Line 
1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *********************************************************************/
5
6#include "ncdap3.h"
7#include "nc3dispatch.h"
8#include "ncd3dispatch.h"
9#include "dapalign.h"
10#include "dapdump.h"
11#include "oc.h"
12
13#define getncid(drno) (((NC*)drno)->ext_ncid)
14
15/*Forward*/
16static NCerror getseqdimsize(NCDAPCOMMON*, CDFnode* seq, size_t* sizep);
17static int fieldindex(CDFnode* parent, CDFnode* child);
18static NCerror countsequence(NCDAPCOMMON*, CDFnode* node, size_t*);
19static NCerror makeseqdim(NCDAPCOMMON*, CDFnode* node, size_t, CDFnode**);
20static NCerror computeseqcountconstraints3(NCDAPCOMMON*,CDFnode*,NCbytes*);
21static void computeseqcountconstraints3r(NCDAPCOMMON*, CDFnode*, CDFnode**);
22
23void
24freegetvara(Getvara* vara)
25{
26    if(vara == NULL) return;
27    dcefree((DCEnode*)vara->varaprojection);
28    nullfree(vara);
29}
30
31NCerror
32freeNCDAPCOMMON(NCDAPCOMMON* dapcomm)
33{
34    /* abort the metadata file */
35    (void)nc_abort(getncid(dapcomm));
36    freenccache(dapcomm,dapcomm->cdf.cache);
37    nclistfree(dapcomm->cdf.varnodes);
38    nclistfree(dapcomm->cdf.seqnodes);
39    nclistfree(dapcomm->cdf.gridnodes);
40    nclistfree(dapcomm->cdf.usertypes);
41    nullfree(dapcomm->cdf.recorddimname);
42
43    /* free the trees */
44    freecdfroot34(dapcomm->cdf.ddsroot);
45    dapcomm->cdf.ddsroot = NULL;
46    freecdfroot34(dapcomm->cdf.fullddsroot);
47    dapcomm->cdf.fullddsroot = NULL;
48    if(dapcomm->oc.ocdasroot != NULL)
49        oc_root_free(dapcomm->oc.conn,dapcomm->oc.ocdasroot);
50    dapcomm->oc.ocdasroot = NULL;
51    oc_close(dapcomm->oc.conn); /* also reclaims remaining OC trees */
52    nc_urifree(dapcomm->oc.url);
53    nullfree(dapcomm->oc.urltext);
54    nullfree(dapcomm->oc.rawurltext);
55
56    dcefree((DCEnode*)dapcomm->oc.dapconstraint);
57    dapcomm->oc.dapconstraint = NULL;
58
59    free(dapcomm);
60
61    return NC_NOERR;
62}
63
64NCerror
65addstringdims(NCDAPCOMMON* dapcomm)
66{
67    /* for all variables of string type, we will need another dimension
68       to represent the string; Accumulate the needed sizes and create
69       the dimensions with a specific name: either as specified
70       in DODS{...} attribute set or defaulting to the variable name.
71       All such dimensions are global.
72    */
73    int i;
74    NClist* varnodes = dapcomm->cdf.varnodes;
75    CDFnode* globalsdim = NULL;
76    char dimname[4096];
77    size_t dimsize;
78
79    /* Start by creating the global string dimension */
80    snprintf(dimname,sizeof(dimname),"maxStrlen%lu",
81            (unsigned long)dapcomm->cdf.defaultstringlength);
82    globalsdim = makecdfnode34(dapcomm, dimname, OC_Dimension, OCNULL,
83                                 dapcomm->cdf.ddsroot);
84    nclistpush(dapcomm->cdf.ddsroot->tree->nodes,(ncelem)globalsdim);
85    DIMFLAGSET(globalsdim,CDFDIMSTRING);
86    globalsdim->dim.declsize = dapcomm->cdf.defaultstringlength;
87    globalsdim->dim.declsize0 = globalsdim->dim.declsize;
88    globalsdim->dim.array = dapcomm->cdf.ddsroot;
89    globalsdim->ncbasename = cdflegalname3(dimname);
90    globalsdim->ncfullname = nulldup(globalsdim->ncbasename);
91    dapcomm->cdf.globalstringdim = globalsdim;
92
93    for(i=0;i<nclistlength(varnodes);i++) {
94        CDFnode* var = (CDFnode*)nclistget(varnodes,i);
95        CDFnode* sdim = NULL;
96
97        /* Does this node need a string dim? */
98        if(var->etype != NC_STRING && var->etype != NC_URL) continue;
99
100        dimsize = 0;
101        if(var->dodsspecial.maxstrlen > 0)
102            dimsize = var->dodsspecial.maxstrlen;
103        else
104            dimsize = var->maxstringlength;
105
106        /* check is a variable-specific string length was specified */
107        if(dimsize == 0) 
108            sdim = dapcomm->cdf.globalstringdim; /* use default */
109        else {
110            /* create a psuedo dimension for the charification of the string*/
111            if(var->dodsspecial.dimname != NULL)
112                strncpy(dimname,var->dodsspecial.dimname,sizeof(dimname));
113            else
114                snprintf(dimname,sizeof(dimname),"maxStrlen%lu",
115                         (unsigned long)dimsize);
116            sdim = makecdfnode34(dapcomm, dimname, OC_Dimension, OCNULL,
117                                 dapcomm->cdf.ddsroot);
118            if(sdim == NULL) return THROW(NC_ENOMEM);
119            nclistpush(dapcomm->cdf.ddsroot->tree->nodes,(ncelem)sdim);
120            DIMFLAGSET(sdim,CDFDIMSTRING);
121            sdim->dim.declsize = dimsize;
122            sdim->dim.declsize0 = dimsize;
123            sdim->dim.array = var;
124            sdim->ncbasename = cdflegalname3(sdim->ocname);
125            sdim->ncfullname = nulldup(sdim->ncbasename);
126        }
127        /* tag the variable with its string dimension*/
128        var->array.stringdim = sdim;
129    }
130    return NC_NOERR;
131}
132
133NCerror
134defrecorddim3(NCDAPCOMMON* dapcomm)
135{
136    unsigned int i;
137    NCerror ncstat = NC_NOERR;
138    NClist* basedims;
139
140    if(dapcomm->cdf.recorddimname == NULL) return NC_NOERR; /* ignore */
141    /* Locate the base dimension matching the record dim */
142    basedims = dapcomm->cdf.dimnodes;
143    for(i=0;i<nclistlength(basedims);i++) {
144        CDFnode* dim = (CDFnode*)nclistget(basedims,i);
145        if(strcmp(dim->ocname,dapcomm->cdf.recorddimname) != 0) continue;
146        DIMFLAGSET(dim,CDFDIMRECORD);
147        dapcomm->cdf.recorddim = dim;
148        break;
149    }
150
151    return ncstat;
152}
153
154NCerror
155defseqdims(NCDAPCOMMON* dapcomm)
156{
157    unsigned int i;
158    NCerror ncstat = NC_NOERR;
159    int seqdims = 1; /* default is to compute seq dims counts */
160
161    /* Does the user want to compute actual sequence sizes? */
162    if(paramvalue34(dapcomm,"noseqdims")) seqdims = 0;
163
164    /*
165        Compute and define pseudo dimensions for sequences
166        meeting the following qualifications:
167        1. all parents (transitively) of the sequence must
168           be either a dataset or a scalar structure.
169        2. it must be possible to find a usable sequence constraint.
170        All other sequences will be ignored.
171    */
172
173    for(i=0;i<nclistlength(dapcomm->cdf.seqnodes);i++) {
174        CDFnode* seq = (CDFnode*)nclistget(dapcomm->cdf.seqnodes,i);
175        size_t seqsize;
176        CDFnode* sqdim = NULL;
177        CDFnode* container;
178        /* Does this sequence match the requirements for use ? */
179        seq->usesequence = 1; /* assume */
180        for(container=seq->container;container != NULL;container=container->container) {
181            if(container->nctype == NC_Dataset) break;
182            if(container->nctype != NC_Structure
183               || nclistlength(container->array.dimset0) > 0)
184                {seq->usesequence = 0; break;}/* no good */
185        }       
186        /* Does the user want us to compute the actual sequence dim size? */
187        if(seq->usesequence && seqdims) {
188            ncstat = getseqdimsize(dapcomm,seq,&seqsize);
189            if(ncstat != NC_NOERR) {
190                /* Cannot read sequence; mark as unusable */
191                seq->usesequence = 0;
192            }
193        } else { /* !seqdims default to size = 1 */
194            seqsize = 1; 
195        }
196        if(seq->usesequence) {
197            /* Note: we are making the dimension in the dds root tree */
198            ncstat = makeseqdim(dapcomm,seq,seqsize,&sqdim);
199            if(ncstat) goto fail;
200            seq->array.seqdim = sqdim;
201        } else
202            seq->array.seqdim = NULL;
203    }
204
205fail:
206    return ncstat;
207}
208
209static NCerror
210getseqdimsize(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t* sizep)
211{
212    NCerror ncstat = NC_NOERR;
213    OCerror ocstat = OC_NOERR;
214    OCconnection conn = dapcomm->oc.conn;
215    OCdata rootcontent = OCNULL;
216    OCobject ocroot;
217    CDFnode* dxdroot;
218    CDFnode* xseq;
219    NCbytes* seqcountconstraints = ncbytesnew();
220    size_t seqsize;
221
222    /* Read the minimal amount of data in order to get the count */
223    /* If the url is unconstrainable, then get the whole thing */
224    computeseqcountconstraints3(dapcomm,seq,seqcountconstraints);
225#ifdef DEBUG
226fprintf(stderr,"seqcountconstraints: %s\n",ncbytescontents(seqcountconstraints));
227#endif
228
229    /* Fetch the minimal data */
230    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
231        ocstat = dap_fetch(dapcomm,conn,NULL,OCDATADDS,&ocroot);
232    else
233        ocstat = dap_fetch(dapcomm,conn,ncbytescontents(seqcountconstraints),OCDATADDS,&ocroot);
234    if(ocstat) goto fail;
235
236    ncstat = buildcdftree34(dapcomm,ocroot,OCDATA,&dxdroot);
237    if(ncstat) goto fail;       
238    /* attach DATADDS to DDS */
239    ncstat = attach34(dxdroot,seq);
240    if(ncstat) goto fail;       
241
242    /* WARNING: we are now switching to datadds tree */
243    xseq = seq->attachment;
244    ncstat = countsequence(dapcomm,xseq,&seqsize);
245    if(ncstat) goto fail;
246
247#ifdef DEBUG
248fprintf(stderr,"sequencesize: %s = %lu\n",seq->ocname,(unsigned long)seqsize);
249#endif
250
251    /* throw away the fetch'd trees */
252    unattach34(dapcomm->cdf.ddsroot);
253    freecdfroot34(dxdroot);
254    if(ncstat != NC_NOERR) {
255        /* Cannot get DATADDDS*/
256        char* code;
257        char* msg;
258        long httperr;
259        oc_svcerrordata(dapcomm->oc.conn,&code,&msg,&httperr);
260        if(code != NULL) {
261            nclog(NCLOGERR,"oc_fetch_datadds failed: %s %s %l",
262                        code,msg,httperr);
263        }
264        ocstat = OC_NOERR;
265    }           
266    if(sizep) *sizep = seqsize;
267
268fail:
269    ncbytesfree(seqcountconstraints);
270    oc_data_free(conn,rootcontent);
271    if(ocstat) ncstat = ocerrtoncerr(ocstat);
272    return ncstat;
273}
274
275static NCerror
276makeseqdim(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t count, CDFnode** sqdimp)
277{
278    CDFnode* sqdim;
279    CDFnode* root = seq->root;
280    CDFtree* tree = root->tree;
281
282    /* build the dimension with given size; keep the dimension anonymous */
283    sqdim = makecdfnode34(dapcomm,seq->ocname,OC_Dimension,OCNULL,root);
284    if(sqdim == NULL) return THROW(NC_ENOMEM);
285    nclistpush(tree->nodes,(ncelem)sqdim);
286    /* Assign a name to the sequence node */
287    sqdim->ncbasename = cdflegalname3(seq->ocname);
288    sqdim->ncfullname = nulldup(sqdim->ncbasename);
289    DIMFLAGSET(sqdim,CDFDIMSEQ);
290    sqdim->dim.declsize = count;
291    sqdim->dim.declsize0 = count;
292    sqdim->dim.array = seq;
293    if(sqdimp) *sqdimp = sqdim;
294    return NC_NOERR;
295}
296
297static NCerror
298countsequence(NCDAPCOMMON* dapcomm, CDFnode* xseq, size_t* sizep)
299{
300    unsigned int i;
301    NClist* path = nclistnew();
302    int index;
303    OCerror ocstat = OC_NOERR;
304    NCerror ncstat = NC_NOERR;
305    OCconnection conn = dapcomm->oc.conn;
306    size_t recordcount;
307    CDFnode* xroot;
308    CDFnode* current;
309    OCdata datacontainer = OCNULL;
310    OCmode mode;
311
312    ASSERT((xseq->nctype == NC_Sequence));
313
314    /* collect the path to the sequence node */
315    collectnodepath3(xseq,path,WITHDATASET);
316
317    /* Get tree root */
318    xroot = xseq->root;
319    datacontainer = oc_data_new(conn);
320    ocstat = oc_data_root(conn,xroot->tree->ocroot,datacontainer);
321    if(ocstat) goto fail;
322
323    /* walk to the sequence object; control the movement to the next node
324       based on mode */
325    current = (CDFnode*)nclistget(path,0);
326    for(i=0;;) {
327        OCdata child = OCNULL;
328        CDFnode* next = NULL;
329        ocstat = oc_data_mode(conn,datacontainer,&mode);
330        if(ocstat != OC_NOERR) goto fail;
331        switch (mode) {
332        case OCFIELDMODE:
333            i++;
334            next = (CDFnode*)nclistget(path,i);
335            index = fieldindex(current,next);
336            break;         
337        case OCARRAYMODE:
338            index = 0;
339            break;
340        case OCSEQUENCEMODE:
341            goto exitloop;
342        default:
343            PANIC("unexpected mode");
344            return NC_EINVAL;
345        }
346        child = oc_data_new(conn);
347        ocstat = oc_data_ith(conn,datacontainer,index,child);
348        if(ocstat) goto fail;
349        /* move to the next node only if it is defined */
350        if(next != NULL)
351            current = next;
352        oc_data_free(conn,datacontainer);
353        datacontainer = child;
354    }
355exitloop:
356    ASSERT(current == xseq && mode == OCSEQUENCEMODE);
357    oc_data_count(conn,datacontainer,&recordcount);
358    if(sizep) *sizep = recordcount;
359
360fail:
361    oc_data_free(conn,datacontainer);
362    nclistfree(path);
363    if(ocstat) ncstat = ocerrtoncerr(ocstat);
364    return THROW(ncstat);
365}
366
367static int
368fieldindex(CDFnode* parent, CDFnode* child)
369{
370    unsigned int i;
371    for(i=0;i<nclistlength(parent->subnodes);i++) {
372        CDFnode* node = (CDFnode*)nclistget(parent->subnodes,i);
373        if(node == child) return i;
374    }
375    return -1;
376}
377
378NCerror
379showprojection3(NCDAPCOMMON* dapcomm, CDFnode* var)
380{
381    int i,rank;
382    NCerror ncstat = NC_NOERR;
383    NCbytes* projection = ncbytesnew();
384    NClist* path = nclistnew();
385    NC* drno = dapcomm->controller;
386
387    /* Collect the set of DDS node name forming the xpath */
388    collectnodepath3(var,path,WITHOUTDATASET);
389    for(i=0;i<nclistlength(path);i++) {
390        CDFnode* node = (CDFnode*)nclistget(path,i);
391        if(i > 0) ncbytescat(projection,".");
392        ncbytescat(projection,node->ocname);
393    }
394    /* Now, add the dimension info */
395    rank = nclistlength(var->array.dimset0);
396    for(i=0;i<rank;i++) {
397        CDFnode* dim = (CDFnode*)nclistget(var->array.dimset0,i);
398        char tmp[32];
399        ncbytescat(projection,"[");
400        snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)dim->dim.declsize);
401        ncbytescat(projection,tmp);
402        ncbytescat(projection,"]");
403    }   
404    /* Define the attribute */
405    ncstat = nc_put_att_text(getncid(drno),var->ncid,
406                               "_projection",
407                               ncbyteslength(projection),
408                               ncbytescontents(projection));
409    return ncstat;
410}
411
412/*
413This is more complex than one might think. We want to find
414a path to a variable inside the given node so that we can
415ask for a single instance of that variable to minimize the
416amount of data we retrieve. However, we want to avoid passing
417through any nested sequence. This is possible because of the way
418that sequencecheck() works.
419TODO: some servers will not accept an unconstrained fetch, so
420make sure we always have a constraint.
421*/
422
423static NCerror
424computeseqcountconstraints3(NCDAPCOMMON* dapcomm, CDFnode* seq, NCbytes* seqcountconstraints)
425{
426    int i,j;
427    NClist* path = NULL;
428    CDFnode* var = NULL;
429
430    ASSERT(seq->nctype == NC_Sequence);
431    computeseqcountconstraints3r(dapcomm,seq,&var);
432
433    ASSERT((var != NULL));
434
435    /* Compute var path */
436    path = nclistnew();
437    collectnodepath3(var,path,WITHOUTDATASET);
438
439    /* construct the projection path using minimal index values */
440    for(i=0;i<nclistlength(path);i++) {
441        CDFnode* node = (CDFnode*)nclistget(path,i);
442        if(i > 0) ncbytescat(seqcountconstraints,".");
443        ncbytescat(seqcountconstraints,node->ocname);
444        if(node == seq) {
445            /* Use the limit */
446            if(node->sequencelimit > 0) {
447                char tmp[64];
448                snprintf(tmp,sizeof(tmp),"[0:%lu]",
449                         (unsigned long)(node->sequencelimit - 1));
450                ncbytescat(seqcountconstraints,tmp);
451            }
452        } else if(nclistlength(node->array.dimset0) > 0) {
453            int ndims = nclistlength(node->array.dimset0);
454            for(j=0;j<ndims;j++) {
455                CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j);
456                if(DIMFLAG(dim,CDFDIMSTRING)) {
457                    ASSERT((j == (ndims - 1)));
458                    break;
459                }
460                ncbytescat(seqcountconstraints,"[0]");
461            }
462        }
463    }
464    /* Finally, add in any selection from the original URL */
465    if(dapcomm->oc.url->selection != NULL)
466        ncbytescat(seqcountconstraints,dapcomm->oc.url->selection);
467    nclistfree(path);
468    return NC_NOERR;   
469}
470
471
472/* Given an existing candidate, see if we prefer newchoice */
473static CDFnode*
474prefer(CDFnode* candidate, CDFnode* newchoice)
475{
476    nc_type newtyp;
477    nc_type cantyp;
478    int newisstring;
479    int canisstring;
480    int newisscalar;
481    int canisscalar;
482
483    /* always choose !null over null */
484    if(newchoice == NULL)
485        return candidate;
486    if(candidate == NULL)
487        return newchoice;
488
489    newtyp = newchoice->etype;
490    cantyp = candidate->etype;
491    newisstring = (newtyp == NC_STRING || newtyp == NC_URL);
492    canisstring = (cantyp == NC_STRING || cantyp == NC_URL);
493    newisscalar = (nclistlength(newchoice->array.dimset0) == 0);
494    canisscalar = (nclistlength(candidate->array.dimset0) == 0);
495
496    ASSERT(candidate->nctype == NC_Primitive && newchoice->nctype == NC_Primitive);
497   
498    /* choose non-string over string */
499    if(canisstring && !newisstring)
500        return newchoice;
501    if(!canisstring && newisstring)
502        return candidate;
503
504    /* choose scalar over array */
505    if(canisscalar && !newisscalar)
506        return candidate;
507    if(!canisscalar && newisscalar)
508        return candidate;
509
510    /* otherwise choose existing candidate */
511    return candidate;
512}
513
514/* computeseqcountconstraints3 recursive helper function */
515static void
516computeseqcountconstraints3r(NCDAPCOMMON* dapcomm, CDFnode* node, CDFnode** candidatep)
517{
518    CDFnode* candidate;
519    CDFnode* compound;
520    unsigned int i;
521
522    candidate = NULL;
523    compound = NULL;
524
525    for(i=0;i<nclistlength(node->subnodes);i++){
526        CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,i);
527        if(subnode->nctype == NC_Structure || subnode->nctype == NC_Grid)
528            compound = subnode; /* save for later recursion */
529        else if(subnode->nctype == NC_Primitive) {
530            candidate = prefer(candidate,subnode);
531        }
532    }
533    if(candidate == NULL && compound == NULL) {
534        PANIC("cannot find candidate for seqcountconstraints for a sequence");
535    } else if(candidate != NULL && candidatep != NULL) {
536        *candidatep = candidate;
537    } else { /* compound != NULL by construction */
538        /* recurse on a nested grids or strucures */
539        computeseqcountconstraints3r(dapcomm,compound,candidatep);
540    }
541}
542
543
544static unsigned long
545cdftotalsize3(NClist* dimensions)
546{
547    unsigned int i;
548    unsigned long total = 1;
549    if(dimensions != NULL) {
550        for(i=0;i<nclistlength(dimensions);i++) {
551            CDFnode* dim = (CDFnode*)nclistget(dimensions,i);
552            total *= dim->dim.declsize;
553        }
554    }
555    return total;
556}
557
558/* Estimate variables sizes and then resort the variable list
559   by that size
560*/
561void
562estimatevarsizes3(NCDAPCOMMON* dapcomm)
563{
564    int ivar;
565    unsigned int rank;
566    size_t totalsize = 0;
567
568    for(ivar=0;ivar<nclistlength(dapcomm->cdf.varnodes);ivar++) {
569        CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,ivar);
570        NClist* ncdims = var->array.dimset0;
571        rank = nclistlength(ncdims);
572        if(rank == 0) { /* use instance size of the type */
573            var->estimatedsize = nctypesizeof(var->etype);
574#ifdef DEBUG1
575fprintf(stderr,"scalar %s.estimatedsize = %lu\n",
576        makecdfpathstring3(var,"."),var->estimatedsize);
577#endif
578        } else {
579            unsigned long size = cdftotalsize3(ncdims);
580            size *= nctypesizeof(var->etype);
581#ifdef DEBUG1
582fprintf(stderr,"array %s(%u).estimatedsize = %lu\n",
583        makecdfpathstring3(var,"."),rank,size);
584#endif
585            var->estimatedsize = size;
586        }
587        totalsize += var->estimatedsize;
588    }
589#ifdef DEBUG1
590fprintf(stderr,"total estimatedsize = %lu\n",totalsize);
591#endif
592    dapcomm->cdf.totalestimatedsize = totalsize;
593}
594
595NCerror
596fetchtemplatemetadata3(NCDAPCOMMON* dapcomm)
597{
598    NCerror ncstat = NC_NOERR;
599    OCerror ocstat = OC_NOERR;
600    OCobject ocroot = OCNULL;
601    CDFnode* ddsroot = NULL;
602    char* ce = NULL;
603
604    /* Temporary hack: we need to get the selection string
605       from the url
606    */
607    /* Get (almost) unconstrained DDS; In order to handle functions
608       correctly, those selections must always be included
609    */
610    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
611        ce = NULL;
612    else
613        ce = nulldup(dapcomm->oc.url->selection);
614
615    /* Get selection constrained DDS */
616    ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDDS,&ocroot);
617    if(ocstat != OC_NOERR) {
618        /* Special Hack. If the protocol is file, then see if
619           we can get the dds from the .dods file
620        */
621        if(strcmp(dapcomm->oc.url->protocol,"file") != 0) {
622            THROWCHK(ocstat); goto done;
623        }
624        /* Fetch the data dds */
625        ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDATADDS,&ocroot);
626        if(ocstat != OC_NOERR) {
627            THROWCHK(ocstat); goto done;
628        }
629        /* Note what we did */
630        nclog(NCLOGWARN,"Cannot locate .dds file, using .dods file");
631    }
632
633    /* Get selection constrained DAS */
634    ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDAS,&dapcomm->oc.ocdasroot);
635    if(ocstat != OC_NOERR) {
636        /* Ignore but complain */
637        nclog(NCLOGWARN,"Could not read DAS; ignored");
638        dapcomm->oc.ocdasroot = OCNULL; 
639        ocstat = OC_NOERR;
640    }
641
642    /* Construct our parallel dds tree */
643    ncstat = buildcdftree34(dapcomm,ocroot,OCDDS,&ddsroot);
644    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
645    dapcomm->cdf.fullddsroot = ddsroot;
646
647done:
648    nullfree(ce);
649    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
650    return ncstat;
651}
652
653NCerror
654fetchconstrainedmetadata3(NCDAPCOMMON* dapcomm)
655{
656    NCerror ncstat = NC_NOERR;
657    OCerror ocstat = OC_NOERR;
658    OCobject ocroot;
659    CDFnode* ddsroot; /* constrained */
660    char* ce = NULL;
661
662    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
663        ce = NULL;
664    else
665        ce = buildconstraintstring3(dapcomm->oc.dapconstraint);
666
667    {
668        ocstat = dap_fetch(dapcomm,dapcomm->oc.conn,ce,OCDDS,&ocroot);
669        if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto fail;}
670
671        /* Construct our parallel dds tree; including attributes*/
672        ncstat = buildcdftree34(dapcomm,ocroot,OCDDS,&ddsroot);
673        if(ncstat) goto fail;
674
675        dapcomm->cdf.ddsroot = ddsroot;
676
677        if(!FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
678            /* fix DAP server problem by adding back any missing grid structure nodes */
679            ncstat = regrid3(ddsroot,dapcomm->cdf.fullddsroot,dapcomm->oc.dapconstraint->projections);   
680            if(ncstat) goto fail;
681        }
682
683#ifdef DEBUG
684fprintf(stderr,"constrained:\n%s",dumptree(ddsroot));
685#endif
686
687        /* Combine DDS and DAS */
688        if(dapcomm->oc.ocdasroot != NULL) {
689            ncstat = dapmerge3(dapcomm,ddsroot,dapcomm->oc.ocdasroot);
690            if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;}
691        }
692
693        /* map the constrained DDS to the unconstrained DDS */
694        ncstat = mapnodes3(ddsroot,dapcomm->cdf.fullddsroot);
695        if(ncstat) goto fail;
696
697    }
698
699fail:
700    nullfree(ce);
701    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
702    return ncstat;
703}
704
705/* Suppress variables not in usable sequences*/
706NCerror
707suppressunusablevars3(NCDAPCOMMON* dapcomm)
708{
709    int i,j;
710    int found = 1;
711    NClist* path = nclistnew();
712
713    while(found) {
714        found = 0;
715        /* Walk backwards to aid removal semantics */
716        for(i=nclistlength(dapcomm->cdf.varnodes)-1;i>=0;i--) {
717            CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,i);
718            /* See if this var is under an unusable sequence */
719            nclistclear(path);
720            collectnodepath3(var,path,WITHOUTDATASET);
721            for(j=0;j<nclistlength(path);j++) {
722                CDFnode* node = (CDFnode*)nclistget(path,j);
723                if(node->nctype == NC_Sequence
724                   && !node->usesequence) {
725#ifdef DEBUG
726fprintf(stderr,"suppressing var in unusable sequence: %s.%s\n",node->ncfullname,var->ncbasename);
727#endif
728                    found = 1;
729                    break;
730                }
731            }
732            if(found) break;
733        }
734        if(found) nclistremove(dapcomm->cdf.varnodes,i);
735    }
736    nclistfree(path);
737    return NC_NOERR;
738}
739
740
741/*
742For variables which have a zero size dimension,
743make them invisible.
744*/
745NCerror
746fixzerodims3(NCDAPCOMMON* dapcomm)
747{
748    int i,j;
749    for(i=0;i<nclistlength(dapcomm->cdf.varnodes);i++) {
750        CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.varnodes,i);
751        NClist* ncdims = var->array.dimsetplus;
752        if(nclistlength(ncdims) == 0) continue;
753        for(j=0;j<nclistlength(ncdims);j++) {
754            CDFnode* dim = (CDFnode*)nclistget(ncdims,j);
755            if(dim->dim.declsize == 0) {
756                /* make node invisible */
757                var->visible = 0;
758                var->zerodim = 1;
759            }
760        }
761    }
762    return NC_NOERR;
763}
764
765void
766applyclientparamcontrols3(NCDAPCOMMON* dapcomm)
767{
768    /* clear the flags */
769    CLRFLAG(dapcomm->controls,NCF_CACHE);
770    CLRFLAG(dapcomm->controls,NCF_PREFETCH);
771    CLRFLAG(dapcomm->controls,NCF_SHOWFETCH);
772    CLRFLAG(dapcomm->controls,NCF_NC3);
773    CLRFLAG(dapcomm->controls,NCF_NCDAP);
774
775    /* Turn on any default on flags */
776    SETFLAG(dapcomm->controls,DFALT_ON_FLAGS);   
777    SETFLAG(dapcomm->controls,(NCF_NC3|NCF_NCDAP));
778
779    /* enable/disable caching */
780    if(paramcheck34(dapcomm,"cache",NULL))
781        SETFLAG(dapcomm->controls,NCF_CACHE);
782    else if(paramcheck34(dapcomm,"nocache",NULL))
783        CLRFLAG(dapcomm->controls,NCF_CACHE);
784
785    /* enable/disable cache prefetch */
786    if(paramcheck34(dapcomm,"prefetch",NULL))
787        SETFLAG(dapcomm->controls,NCF_PREFETCH);
788    else if(paramcheck34(dapcomm,"noprefetch",NULL))
789        CLRFLAG(dapcomm->controls,NCF_PREFETCH);
790
791
792    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE))
793        SETFLAG(dapcomm->controls,NCF_CACHE);
794
795    if(paramcheck34(dapcomm,"show","fetch"))
796        SETFLAG(dapcomm->controls,NCF_SHOWFETCH);
797
798    nclog(NCLOGNOTE,"Caching=%d",FLAGSET(dapcomm->controls,NCF_CACHE));
799
800}
Note: See TracBrowser for help on using the repository browser.