source: XIOS/dev/dev_cmip6_omp/extern/src_netcdf4/ncdap3.c @ 1606

Last change on this file since 1606 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: 20.5 KB
Line 
1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/libncdap3/ncdap3.c,v 1.94 2010/05/28 01:05:34 dmh Exp $
5 *********************************************************************/
6
7#include "ncdap3.h"
8
9#ifdef HAVE_GETRLIMIT
10#  ifdef HAVE_SYS_RESOURCE_H
11#    include <sys/time.h>
12#  endif
13#  ifdef HAVE_SYS_RESOURCE_H
14#    include <sys/resource.h>
15#  endif
16#endif
17
18#include "nc3dispatch.h"
19#include "ncd3dispatch.h"
20#include "dapalign.h"
21#include "dapdump.h"
22
23static NCerror buildncstructures3(NCDAPCOMMON*);
24static NCerror builddims(NCDAPCOMMON*);
25static NCerror buildvars(NCDAPCOMMON*);
26static NCerror buildglobalattrs3(NCDAPCOMMON*,CDFnode* root);
27static NCerror buildattribute3a(NCDAPCOMMON*, NCattribute*, nc_type, int);
28
29
30static char* getdefinename(CDFnode* node);
31
32extern CDFnode* v4node;
33int nc3dinitialized = 0;
34
35/**************************************************/
36/* Add an extra function whose sole purpose is to allow
37   configure(.ac) to test for the presence of thiscode.
38*/
39int nc__opendap(void) {return 0;}
40
41/**************************************************/
42/* Do local initialization */
43
44int
45nc3dinitialize(void)
46{
47    compute_nccalignments();
48    nc3dinitialized = 1;
49    return NC_NOERR;
50}
51
52/**************************************************/
53
54/* See ncd3dispatch.c for other version */
55int
56NCD3_open(const char * path, int mode,
57               int basepe, size_t *chunksizehintp,
58               int useparallel, void* mpidata,
59               NC_Dispatch* dispatch, NC** ncpp)
60{
61    NCerror ncstat = NC_NOERR;
62    OCerror ocstat = OC_NOERR;
63    NC* drno = NULL;
64    NCDAPCOMMON* dapcomm = NULL;
65    const char* value;
66    /* We will use a fake file descriptor as our internal in-memory filename */
67    char tmpname[32];
68
69    if(!nc3dinitialized) nc3dinitialize();
70
71    if(path == NULL)
72        return NC_EDAPURL;
73    if(dispatch == NULL) PANIC("NC3D_open: no dispatch table");
74
75    /* Setup our NC and NCDAPCOMMON state*/
76    drno = (NC*)calloc(1,sizeof(NC));
77    if(drno == NULL) {ncstat = NC_ENOMEM; goto done;}
78
79    /* compute an ncid */
80    ncstat = add_to_NCList(drno);
81    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
82
83    dapcomm = (NCDAPCOMMON*)calloc(1,sizeof(NCDAPCOMMON));
84    if(dapcomm == NULL) {ncstat = NC_ENOMEM; goto done;}
85
86    drno->dispatch = dispatch;
87    drno->dispatchdata = dapcomm;
88    drno->int_ncid = nc__pseudofd(); /* create a unique id */
89    dapcomm->controller = (NC*)drno;
90
91    dapcomm->cdf.separator = ".";
92    dapcomm->cdf.smallsizelimit = DFALTSMALLLIMIT;
93    dapcomm->cdf.cache = createnccache();
94
95#ifdef HAVE_GETRLIMIT
96    { struct rlimit rl;
97      if(getrlimit(RLIMIT_NOFILE, &rl) >= 0) {
98        dapcomm->cdf.cache->cachecount = (size_t)(rl.rlim_cur / 2);
99      }
100    }
101#endif
102
103#ifdef OCCOMPILEBYDEFAULT
104    /* set the compile flag by default */
105    dapcomm->oc.rawurltext = (char*)emalloc(strlen(path)+strlen("[compile]")+1);
106    strcpy(dapcomm->oc.rawurltext,"[compile]");
107    strcat(dapcomm->oc.rawurltext, path);   
108#else
109    dapcomm->oc.rawurltext = strdup(path);
110#endif
111
112    nc_uriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url);
113
114    /* parse the client parameters */
115    nc_uridecodeparams(dapcomm->oc.url);
116
117    if(!constrainable34(dapcomm->oc.url))
118        SETFLAG(dapcomm->controls,NCF_UNCONSTRAINABLE);
119
120    /* Use libsrc code for storing metadata */
121
122    snprintf(tmpname,sizeof(tmpname),"%d",drno->int_ncid);
123    /* Now, use the file to create the netcdf file */
124    if(sizeof(size_t) == sizeof(unsigned int))
125        ncstat = nc_create(tmpname,NC_DISKLESS,&drno->substrate);
126    else
127        ncstat = nc_create(tmpname,NC_DISKLESS|NC_64BIT_OFFSET,&drno->substrate);
128    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
129
130    /* Avoid fill */
131    nc_set_fill(drno->substrate,NC_NOFILL,NULL);
132
133    dapcomm->oc.dapconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT);
134    dapcomm->oc.dapconstraint->projections = nclistnew();
135    dapcomm->oc.dapconstraint->selections = nclistnew();
136
137    /* Parse constraints to make sure they are syntactically correct */
138    ncstat = parsedapconstraints(dapcomm,dapcomm->oc.url->constraint,dapcomm->oc.dapconstraint);
139    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
140
141    /* Complain if we are unconstrainable but have constraints */
142    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
143        if(dapcomm->oc.url->constraint != NULL
144           && strlen(dapcomm->oc.url->constraint) > 0) {
145            nclog(NCLOGWARN,"Attempt to constrain an unconstrainable data source: %s",
146                   dapcomm->oc.url->constraint);
147        }
148    }
149
150    /* Construct a url for oc minus any parameters */
151    dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,
152                                (NC_URIALL ^ NC_URICONSTRAINTS));
153
154    /* Pass to OC */
155    ocstat = oc_open(dapcomm->oc.urltext,&dapcomm->oc.conn);
156    if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;}
157
158    nullfree(dapcomm->oc.urltext); /* clean up */
159    dapcomm->oc.urltext = NULL;
160
161    /* process control client parameters */
162    applyclientparamcontrols3(dapcomm);
163
164    /* Turn on logging; only do this after oc_open*/
165    if((value = paramvalue34(dapcomm,"log")) != NULL) {
166        ncloginit();
167        ncsetlogging(1);
168        nclogopen(value);
169        oc_loginit();
170        oc_setlogging(1);
171        oc_logopen(value);
172    }
173
174    /* fetch and build the (almost) unconstrained DDS for use as
175       template */
176    ncstat = fetchtemplatemetadata3(dapcomm);
177    if(ncstat != NC_NOERR) goto done;
178
179    /* fetch and build the constrained DDS */
180    ncstat = fetchconstrainedmetadata3(dapcomm);
181    if(ncstat != NC_NOERR) goto done;
182
183#ifdef DEBUG2
184fprintf(stderr,"constrained dds: %s\n",dumptree(dapcomm->cdf.ddsroot));
185#endif
186
187
188    /* The following actions are (mostly) WRT to the constrained tree */
189
190    /* Accumulate useful nodes sets  */
191    ncstat = computecdfnodesets3(dapcomm);
192    if(ncstat) {THROWCHK(ncstat); goto done;}
193
194    /* Fix grids */
195    ncstat = fixgrids3(dapcomm);
196    if(ncstat) {THROWCHK(ncstat); goto done;}
197
198    /* Locate and mark usable sequences */
199    ncstat = sequencecheck3(dapcomm);
200    if(ncstat) {THROWCHK(ncstat); goto done;}
201
202    /* suppress variables not in usable sequences */
203    ncstat = suppressunusablevars3(dapcomm);
204    if(ncstat) {THROWCHK(ncstat); goto done;}
205
206    /* apply client parameters */
207    ncstat = applyclientparams34(dapcomm);
208    if(ncstat) {THROWCHK(ncstat); goto done;}
209
210    /* Add (as needed) string dimensions*/
211    ncstat = addstringdims(dapcomm);
212    if(ncstat) {THROWCHK(ncstat); goto done;}
213
214    if(nclistlength(dapcomm->cdf.seqnodes) > 0) {
215        /* Build the sequence related dimensions */
216        ncstat = defseqdims(dapcomm);
217        if(ncstat) {THROWCHK(ncstat); goto done;}
218    }
219
220    /* Define the dimsetplus and dimsetall lists */
221    ncstat = definedimsets3(dapcomm);
222    if(ncstat) {THROWCHK(ncstat); goto done;}
223
224    /* Re-compute the dimension names*/
225    ncstat = computecdfdimnames34(dapcomm);
226    if(ncstat) {THROWCHK(ncstat); goto done;}
227
228    /* Deal with zero size dimensions */
229    ncstat = fixzerodims3(dapcomm);
230    if(ncstat) {THROWCHK(ncstat); goto done;}
231
232    /* Attempt to use the DODS_EXTRA info to turn
233       one of the dimensions into unlimited.
234       Assume computecdfdimnames34 has already been called.
235    */
236    ncstat = defrecorddim3(dapcomm);
237    if(ncstat) {THROWCHK(ncstat); goto done;}
238    if(dapcomm->cdf.recorddimname != NULL
239       && nclistlength(dapcomm->cdf.seqnodes) > 0) {
240        /*nclog(NCLOGWARN,"unlimited dimension specified, but sequences exist in DDS");*/
241        PANIC("unlimited dimension specified, but sequences exist in DDS");     
242    }
243
244    /* Re-compute the var names*/
245    ncstat = computecdfvarnames3(dapcomm,dapcomm->cdf.ddsroot,dapcomm->cdf.varnodes);
246    if(ncstat) {THROWCHK(ncstat); goto done;}
247
248    /* Transfer data from the unconstrained DDS data to the unconstrained DDS */
249    ncstat = dimimprint3(dapcomm);
250    if(ncstat) goto done;
251
252    /* Process the constraints to map to the constrained CDF tree */
253    /* (must follow fixgrids3 */
254    ncstat = mapconstraints3(dapcomm->oc.dapconstraint,dapcomm->cdf.ddsroot);
255    if(ncstat != NC_NOERR) goto done;
256
257    /* Canonicalize the constraint */
258    ncstat = fixprojections(dapcomm->oc.dapconstraint->projections);
259    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
260
261    /* Fill in segment information */
262    ncstat = qualifyconstraints3(dapcomm->oc.dapconstraint);
263    if(ncstat != NC_NOERR) goto done;
264
265    /* using the modified constraint, rebuild the constraint string */
266    if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) {
267        /* ignore all constraints */
268        dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,0);
269    } else {
270        char* constraintstring = buildconstraintstring3(dapcomm->oc.dapconstraint);
271        nc_urisetconstraints(dapcomm->oc.url,constraintstring);
272        nullfree(constraintstring);
273        dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,NC_URICONSTRAINTS);
274    }
275
276#ifdef DEBUG
277fprintf(stderr,"ncdap3: final constraint: %s\n",dapcomm->oc.url->constraint);
278#endif
279
280    /* Estimate the variable sizes */
281    estimatevarsizes3(dapcomm);
282
283    /* Build the meta data */
284    ncstat = buildncstructures3(dapcomm);
285    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
286
287    /* Do any necessary data prefetch */
288    if(FLAGSET(dapcomm->controls,NCF_PREFETCH)) {
289        ncstat = prefetchdata3(dapcomm);
290        if(ncstat != NC_NOERR) {
291            del_from_NCList((NC*)drno); /* undefine here */
292            {THROWCHK(ncstat); goto done;}
293        }
294    }
295
296#ifdef BUG
297    /* The libsrc code (NC_begins) assumes that
298       a created files is new and hence must have an
299       unlimited dimension of 0 initially, which will
300       wipe out the effect of the NC_set_numrecs in builddims.
301       There is no easy workaround, so we suppress the call
302       to nc_enddef
303    */
304    ncstat = nc_enddef(drno->substrate);
305    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
306#endif
307
308    if(ncpp) *ncpp = (NC*)drno;
309
310    return ncstat;
311
312done:
313    if(drno != NULL) NCD3_close(drno->ext_ncid);
314    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
315    return THROW(ncstat);
316}
317
318int
319NCD3_close(int ncid)
320{
321    NC* drno;
322    NCDAPCOMMON* dapcomm;
323    int ncstatus = NC_NOERR;
324
325    ncstatus = NC_check_id(ncid, (NC**)&drno); 
326    if(ncstatus != NC_NOERR) return THROW(ncstatus);
327
328    dapcomm = (NCDAPCOMMON*)drno->dispatchdata;
329    ncstatus = nc_abort(drno->substrate);
330
331    /* remove ourselves from NClist */
332    del_from_NCList(drno);
333    /* clean NC* */
334    freeNCDAPCOMMON(dapcomm);
335    if(drno->path != NULL) free(drno->path);
336    free(drno);
337    return THROW(ncstatus);
338}
339
340/**************************************************/
341static NCerror
342buildncstructures3(NCDAPCOMMON* dapcomm)
343{
344    NCerror ncstat = NC_NOERR;
345    CDFnode* dds = dapcomm->cdf.ddsroot;
346    NC* ncsub;
347    NC_check_id(dapcomm->controller->substrate,&ncsub);
348
349    ncstat = buildglobalattrs3(dapcomm,dds);
350    if(ncstat != NC_NOERR) goto done;
351
352    ncstat = builddims(dapcomm);
353    if(ncstat != NC_NOERR) goto done;
354
355    ncstat = buildvars(dapcomm);
356    if(ncstat != NC_NOERR) goto done;
357
358done:
359    return THROW(ncstat);
360}
361
362static NCerror
363builddims(NCDAPCOMMON* dapcomm)
364{
365    int i;
366    NCerror ncstat = NC_NOERR;
367    int dimid;
368    NClist* dimset = NULL;
369    NC* drno = dapcomm->controller;
370    NC* ncsub;
371    char* definename;
372
373    /* collect all dimensions from variables */
374    dimset = dapcomm->cdf.dimnodes;
375
376    /* Sort by fullname just for the fun of it */
377    for(;;) {
378        int last = nclistlength(dimset) - 1;
379        int swap = 0;
380        for(i=0;i<last;i++) {
381            CDFnode* dim1 = (CDFnode*)nclistget(dimset,i);
382            CDFnode* dim2 = (CDFnode*)nclistget(dimset,i+1);
383            if(strcmp(dim1->ncfullname,dim2->ncfullname) > 0) {
384                nclistset(dimset,i,(ncelem)dim2);
385                nclistset(dimset,i+1,(ncelem)dim1);
386                swap = 1;
387                break;
388            }
389        }
390        if(!swap) break;
391    }
392
393    /* Define unlimited only if needed */ 
394    if(dapcomm->cdf.recorddim != NULL) {
395        CDFnode* unlimited = dapcomm->cdf.recorddim;
396        definename = getdefinename(unlimited);
397        ncstat = nc_def_dim(drno->substrate,
398                        definename,
399                        NC_UNLIMITED,
400                        &unlimited->ncid);
401        nullfree(definename);
402        if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
403
404        /* get the id for the substrate */
405        ncstat = NC_check_id(drno->substrate,&ncsub);
406        if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
407
408        /* Set the effective size of UNLIMITED;
409           note that this cannot easily be done thru the normal API.*/
410        NC_set_numrecs(ncsub,unlimited->dim.declsize);
411    }
412
413    for(i=0;i<nclistlength(dimset);i++) {
414        CDFnode* dim = (CDFnode*)nclistget(dimset,i);
415        if(dim->dim.basedim != NULL) continue; /* handle below */
416        if(DIMFLAG(dim,CDFDIMRECORD)) continue; /* defined above */
417#ifdef DEBUG1
418fprintf(stderr,"define: dim: %s=%ld\n",dim->ncfullname,(long)dim->dim.declsize);
419#endif
420        definename = getdefinename(dim);
421        ncstat = nc_def_dim(drno->substrate,definename,dim->dim.declsize,&dimid);
422        if(ncstat != NC_NOERR) {
423            THROWCHK(ncstat); goto done;
424        }
425        nullfree(definename);
426        dim->ncid = dimid;
427    }
428
429    /* Make all duplicate dims have same dimid as basedim*/
430    /* (see computecdfdimnames)*/
431    for(i=0;i<nclistlength(dimset);i++) {
432        CDFnode* dim = (CDFnode*)nclistget(dimset,i);
433        if(dim->dim.basedim != NULL) {
434            dim->ncid = dim->dim.basedim->ncid;
435        }
436    }
437done:
438    nclistfree(dimset);
439    return THROW(ncstat);
440}
441
442/* Simultaneously build any associated attributes*/
443/* and any necessary pseudo-dimensions for string types*/
444static NCerror
445buildvars(NCDAPCOMMON* dapcomm)
446{
447    int i,j;
448    NCerror ncstat = NC_NOERR;
449    int varid;
450    NClist* varnodes = dapcomm->cdf.varnodes;
451    NC* drno = dapcomm->controller;
452    char* definename;
453
454    ASSERT((varnodes != NULL));
455    for(i=0;i<nclistlength(varnodes);i++) {
456        CDFnode* var = (CDFnode*)nclistget(varnodes,i);
457        int dimids[NC_MAX_VAR_DIMS];
458        unsigned int ncrank;
459        NClist* vardims = NULL;
460
461        if(!var->visible) continue;
462        if(var->array.basevar != NULL) continue;
463
464#ifdef DEBUG1
465fprintf(stderr,"buildvars.candidate=|%s|\n",var->ncfullname);
466#endif
467
468        vardims = var->array.dimsetall;
469        ncrank = nclistlength(vardims);
470        if(ncrank > 0) {
471            for(j=0;j<ncrank;j++) {
472                CDFnode* dim = (CDFnode*)nclistget(vardims,j);
473                dimids[j] = dim->ncid;
474            }
475        }   
476
477
478
479        definename = getdefinename(var);
480
481#ifdef DEBUG1
482fprintf(stderr,"define: var: %s/%s",
483                definename,var->ocname);
484if(ncrank > 0) {
485int k;
486for(k=0;k<ncrank;k++) {
487CDFnode* dim = (CDFnode*)nclistget(vardims,k);
488fprintf(stderr,"[%ld]",dim->dim.declsize);
489 }
490 }
491fprintf(stderr,"\n");
492#endif
493        ncstat = nc_def_var(drno->substrate,
494                        definename,
495                        var->externaltype,
496                        ncrank,
497                        (ncrank==0?NULL:dimids),
498                        &varid);
499        nullfree(definename);
500        if(ncstat != NC_NOERR) {
501            THROWCHK(ncstat);
502            goto done;
503        }
504        var->ncid = varid;
505        if(var->attributes != NULL) {
506            for(j=0;j<nclistlength(var->attributes);j++) {
507                NCattribute* att = (NCattribute*)nclistget(var->attributes,j);
508                ncstat = buildattribute3a(dapcomm,att,var->etype,varid);
509                if(ncstat != NC_NOERR) goto done;
510            }
511        }
512        /* Tag the variable with its DAP path */
513        if(paramcheck34(dapcomm,"show","projection"))
514            showprojection3(dapcomm,var);
515    }   
516done:
517    return THROW(ncstat);
518}
519
520static NCerror
521buildglobalattrs3(NCDAPCOMMON* dapcomm, CDFnode* root)
522{
523    int i;
524    NCerror ncstat = NC_NOERR;
525    const char* txt;
526    char *nltxt, *p;
527    NCbytes* buf = NULL;
528    NClist* cdfnodes;
529    NC* drno = dapcomm->controller;
530
531    if(root->attributes != NULL) {
532        for(i=0;i<nclistlength(root->attributes);i++) {
533            NCattribute* att = (NCattribute*)nclistget(root->attributes,i);
534            ncstat = buildattribute3a(dapcomm,att,NC_NAT,NC_GLOBAL);
535            if(ncstat != NC_NOERR) goto done;
536        }
537    }
538
539    /* Add global attribute identifying the sequence dimensions */
540    if(paramcheck34(dapcomm,"show","seqdims")) {
541        buf = ncbytesnew();
542        cdfnodes = dapcomm->cdf.ddsroot->tree->nodes;
543        for(i=0;i<nclistlength(cdfnodes);i++) {
544            CDFnode* dim = (CDFnode*)nclistget(cdfnodes,i);
545            if(dim->nctype != NC_Dimension) continue;
546            if(DIMFLAG(dim,CDFDIMSEQ)) {
547                char* cname = cdflegalname3(dim->ocname);
548                if(ncbyteslength(buf) > 0) ncbytescat(buf,", ");
549                ncbytescat(buf,cname);
550                nullfree(cname);
551            }
552        }
553        if(ncbyteslength(buf) > 0) {
554            ncstat = nc_put_att_text(drno->substrate,NC_GLOBAL,"_sequence_dimensions",
555                   ncbyteslength(buf),ncbytescontents(buf));
556        }
557    }
558
559    /* Define some additional system global attributes
560       depending on show= clientparams*/
561    /* Ignore failures*/
562
563    if(paramcheck34(dapcomm,"show","translate")) {
564        /* Add a global attribute to show the translation */
565        ncstat = nc_put_att_text(drno->substrate,NC_GLOBAL,"_translate",
566                   strlen("netcdf-3"),"netcdf-3");
567    }
568    if(paramcheck34(dapcomm,"show","url")) {
569        if(dapcomm->oc.rawurltext != NULL)
570            ncstat = nc_put_att_text(drno->substrate,NC_GLOBAL,"_url",
571                                       strlen(dapcomm->oc.rawurltext),dapcomm->oc.rawurltext);
572    }
573    if(paramcheck34(dapcomm,"show","dds")) {
574        txt = NULL;
575        if(dapcomm->cdf.ddsroot != NULL)
576            txt = oc_inq_text(dapcomm->oc.conn,dapcomm->cdf.ddsroot->ocnode);
577        if(txt != NULL) {
578            /* replace newlines with spaces*/
579            nltxt = nulldup(txt);
580            for(p=nltxt;*p;p++) {if(*p == '\n' || *p == '\r' || *p == '\t') {*p = ' ';}};
581            ncstat = nc_put_att_text(drno->substrate,NC_GLOBAL,"_dds",strlen(nltxt),nltxt);
582            nullfree(nltxt);
583        }
584    }
585    if(paramcheck34(dapcomm,"show","das")) {
586        txt = NULL;
587        if(dapcomm->oc.ocdasroot != OCNULL)
588            txt = oc_inq_text(dapcomm->oc.conn,dapcomm->oc.ocdasroot);
589        if(txt != NULL) {
590            nltxt = nulldup(txt);
591            for(p=nltxt;*p;p++) {if(*p == '\n' || *p == '\r' || *p == '\t') {*p = ' ';}};
592            ncstat = nc_put_att_text(drno->substrate,NC_GLOBAL,"_das",strlen(nltxt),nltxt);
593            nullfree(nltxt);
594        }
595    }
596
597done:
598    ncbytesfree(buf);
599    return THROW(ncstat);
600}
601
602static NCerror
603buildattribute3a(NCDAPCOMMON* dapcomm, NCattribute* att, nc_type vartype, int varid)
604{
605    int i;
606    NCerror ncstat = NC_NOERR;
607    unsigned int nvalues = nclistlength(att->values);
608    NC* drno = dapcomm->controller;
609
610    /* If the type of the attribute is string, then we need*/
611    /* to convert to a single character string by concatenation.
612        modified: 10/23/09 to insert newlines.
613        modified: 10/28/09 to interpret escapes
614    */
615    if(att->etype == NC_STRING || att->etype == NC_URL) {
616        char* newstring;
617        size_t newlen = 0;
618        for(i=0;i<nvalues;i++) {
619            char* s = (char*)nclistget(att->values,i);
620            newlen += (1+strlen(s));
621        }
622        newstring = (char*)malloc(newlen);
623        MEMCHECK(newstring,NC_ENOMEM);
624        newstring[0] = '\0';
625        for(i=0;i<nvalues;i++) {
626            char* s = (char*)nclistget(att->values,i);
627            if(i > 0) strcat(newstring,"\n");
628            strcat(newstring,s);
629        }
630        dapexpandescapes(newstring);
631        if(newstring[0]=='\0')
632            ncstat = nc_put_att_text(drno->substrate,varid,att->name,1,newstring);
633        else
634            ncstat = nc_put_att_text(drno->substrate,varid,att->name,strlen(newstring),newstring);
635        free(newstring);
636    } else {
637        nc_type atype;
638        unsigned int typesize;
639        void* mem;
640        /* It turns out that some servers upgrade the type
641           of _FillValue in order to correctly preserve the
642           original value. However, since the type of the
643           underlying variable is not changes, we get a type
644           mismatch. So, make sure the type of the fillvalue
645           is the same as that of the controlling variable.
646        */
647        if(varid != NC_GLOBAL && strcmp(att->name,"_FillValue")==0)
648            atype = nctypeconvert(dapcomm,vartype);
649        else
650            atype = nctypeconvert(dapcomm,att->etype);
651        typesize = nctypesizeof(atype);
652        mem = malloc(typesize * nvalues);
653        ncstat = dapcvtattrval3(atype,mem,att->values);
654        ncstat = nc_put_att(drno->substrate,varid,att->name,atype,nvalues,mem);
655        nullfree(mem);
656    }
657    return THROW(ncstat);
658}
659
660static char*
661getdefinename(CDFnode* node)
662{
663    char* spath = NULL;
664    NClist* path = NULL;
665
666    switch (node->nctype) {
667    case NC_Primitive:
668        /* The define name is same as the fullname with elided nodes */
669        path = nclistnew();
670        collectnodepath3(node,path,!WITHDATASET);
671        spath = makepathstring3(path,".",PATHNC|PATHELIDE);
672        nclistfree(path);
673        break;
674
675    case NC_Dimension:
676        /* Return just the node's ncname */
677        spath = nulldup(node->ncbasename);     
678        break;
679
680    default:
681        PANIC("unexpected nctype");
682    }
683    return spath;
684}
685
686int
687NCDAP_ping(const char* url)
688{
689    OCerror ocstat = OC_NOERR;
690    ocstat = oc_ping(url);
691    return ocerrtoncerr(ocstat);
692}
Note: See TracBrowser for help on using the repository browser.