static NCerror moveto(NCDAPCOMMON* nccomm, Getvara* xgetvar, CDFnode* xrootnode, void* memory) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = nccomm->oc.conn; OCdatanode xrootcontent; OCddsnode ocroot; NClist* path = nclistnew(); struct NCMEMORY memstate; memstate.next = (memstate.memory = memory); /* Get the root content*/ ocroot = xrootnode->tree->ocroot; ocstat = oc_data_getroot(conn,ocroot,&xrootcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} /* Remember: xgetvar->target is in DATADDS tree */ collectnodepath3(xgetvar->target,path,WITHDATASET); ncstat = movetor(nccomm,xrootcontent, path,0,xgetvar,0,&memstate, xgetvar->varaprojection->var->segments); done: nclistfree(path); oc_data_free(conn,xrootcontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
/* Extract data for a netcdf variable that has a string dimension. */ static int extractstring( NCDAPCOMMON* nccomm, Getvara* xgetvar, CDFnode* xnode, DCEsegment* segment, size_t dimindex, /*notused*/ OClink conn, OCdatanode currentcontent, struct NCMEMORY* memory ) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; int i; size_t rank0; NClist* strings = NULL; Dapodometer* odom = NULL; ASSERT(xnode->etype == NC_STRING || xnode->etype == NC_URL); /* Compute rank minus string dimension */ rank0 = nclistlength(xnode->array.dimset0); /* keep whole extracted strings stored in an NClist */ strings = nclistnew(); if(rank0 == 0) {/*=> scalar*/ char* value = NULL; ocstat = oc_data_readscalar(conn,currentcontent,sizeof(value),&value); if(ocstat != OC_NOERR) goto done; nclistpush(strings,(void*)value); } else { /* Use the odometer to walk to the appropriate fields*/ odom = dapodom_fromsegment(segment,0,rank0); while(dapodom_more(odom)) { char* value = NULL; ocstat = oc_data_readn(conn,currentcontent,odom->index,1,sizeof(value),&value); if(ocstat != OC_NOERR) goto done; nclistpush(strings,(void*)value); dapodom_next(odom); } dapodom_free(odom); } /* Get each string in turn, slice it by applying the string dimm and store in user supplied memory */ for(i=0;i<nclistlength(strings);i++) { char* s = (char*)nclistget(strings,i); slicestring(conn,s,&segment->slices[rank0],memory); free(s); } nclistfree(strings); done: if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
NCerror fetchtemplatemetadata3(NCDAPCOMMON* dapcomm) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; OCddsnode ocroot = NULL; 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 = NULL; ocstat = OC_NOERR; } /* Construct the netcdf cdf tree corresponding to the 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; }
static NCerror movetofield(NCDAPCOMMON* nccomm, OCdatanode currentcontent, NClist* path, int depth, /* depth is position in segment list*/ Getvara* xgetvar, size_t dimindex, /* dimindex is position in xgetvar->slices*/ struct NCMEMORY* memory, NClist* segments) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; size_t fieldindex,gridindex; OClink conn = nccomm->oc.conn; CDFnode* xnode = (CDFnode*)nclistget(path,depth); OCdatanode reccontent = NULL; OCdatanode dimcontent = NULL; OCdatanode fieldcontent = NULL; CDFnode* xnext; int newdepth; /* currentcontent points to the grid/dataset/structure/record instance */ xnext = (CDFnode*)nclistget(path,depth+1); ASSERT((xnext != NULL)); fieldindex = findfield(xnode,xnext); /* If the next node is a nc_virtual node, then we need to effectively ignore it and use the appropriate subnode. If the next node is a re-struct'd node, then use it as is. */ if(xnext->nc_virtual) { CDFnode* xgrid = xnext; xnext = (CDFnode*)nclistget(path,depth+2); /* real node */ gridindex = fieldindex; fieldindex = findfield(xgrid,xnext); fieldindex += gridindex; newdepth = depth+2; } else { newdepth = depth+1; } /* Move to appropriate field */ ocstat = oc_data_ithfield(conn,currentcontent,fieldindex,&fieldcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} ncstat = movetor(nccomm,fieldcontent, path,newdepth,xgetvar,dimindex,memory, segments); done: oc_data_free(conn,dimcontent); oc_data_free(conn,fieldcontent); oc_data_free(conn,reccontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
NCerror fetchconstrainedmetadata3(NCDAPCOMMON* dapcomm) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; OCddsnode 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; ocroot = NULL; /* avoid duplicate reclaim */ dapcomm->cdf.ddsroot = ddsroot; ddsroot = NULL; /* to avoid double reclamation */ if(!FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) { /* fix DAP server problem by adding back any inserting needed structure nodes */ ncstat = restruct3(dapcomm->cdf.ddsroot,dapcomm->cdf.fullddsroot,dapcomm->oc.dapconstraint->projections); if(ncstat) goto fail; } #ifdef DEBUG fprintf(stderr,"constrained:\n%s",dumptree(dapcomm->cdf.ddsroot)); #endif /* Combine DDS and DAS */ if(dapcomm->oc.ocdasroot != NULL) { ncstat = dapmerge3(dapcomm,dapcomm->cdf.ddsroot->ocnode, dapcomm->oc.ocdasroot); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } /* map the constrained DDS to the unconstrained DDS */ ncstat = mapnodes3(dapcomm->cdf.ddsroot,dapcomm->cdf.fullddsroot); if(ncstat) goto fail; } fail: nullfree(ce); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return ncstat; }
NCerror dapmerge3(NCDRNO* drno, CDFnode* node) { unsigned int i; char* aname; unsigned int nvalues,nattrs; void* values; OCtype atype; OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; NCattribute* att; if(node->dds == OCNULL) goto done; OCHECK(oc_inq_nattr(drno->dap.conn,node->dds,&nattrs)); if(nattrs == 0) goto done; if(node->attributes == NULL) node->attributes = nclistnew(); for(i=0;i<nattrs;i++) { ocstat = oc_inq_attr(drno->dap.conn,node->dds,i, &aname, &atype, &nvalues, &values); if(ocstat != OC_NOERR) continue; /* ignore */ if(aname == NULL || nvalues == 0 || values == NULL) continue; /* nothing to do */ ncstat = buildattribute(aname,octypetonc(atype), nvalues,values,&att); if(ncstat == NC_NOERR) nclistpush(node->attributes,(ncelem)att); efree(aname); oc_attr_reclaim(atype,nvalues,values); } done: if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
static NCerror movetor(NCDAPCOMMON* nccomm, OCdatanode currentcontent, NClist* path, int depth, /* depth is position in segment list*/ Getvara* xgetvar, size_t dimindex, /* dimindex is position in xgetvar->slices*/ struct NCMEMORY* memory, NClist* segments) { OCerror ocstat = OC_NOERR; NCerror ncstat = NC_NOERR; OClink conn = nccomm->oc.conn; CDFnode* xnode = (CDFnode*)nclistget(path,depth); OCdatanode reccontent = NULL; OCdatanode dimcontent = NULL; OCdatanode fieldcontent = NULL; Dapodometer* odom = NULL; int hasstringdim = 0; DCEsegment* segment; OCDT mode; /* Note that we use depth-1 because the path contains the DATASET but the segment list does not */ segment = (DCEsegment*)nclistget(segments,depth-1); /*may be NULL*/ if(xnode->etype == NC_STRING || xnode->etype == NC_URL) hasstringdim = 1; /* Get the mode */ mode = oc_data_mode(conn,currentcontent); #ifdef DEBUG2 fprintf(stderr,"moveto: nctype=%d depth=%d dimindex=%d mode=%s", xnode->nctype, depth,dimindex,oc_data_modestring(mode)); fprintf(stderr," segment=%s hasstringdim=%d\n", dcetostring((DCEnode*)segment),hasstringdim); #endif switch (xnode->nctype) { #if 0 #define OCDT_FIELD ((OCDT)(1)) /* field of a container */ #define OCDT_ELEMENT ((OCDT)(2)) /* element of a structure array */ #define OCDT_RECORD ((OCDT)(4)) /* record of a sequence */ #define OCDT_ARRAY ((OCDT)(8)) /* is structure array */ #define OCDT_SEQUENCE ((OCDT)(16)) /* is sequence */ #define OCDT_ATOMIC ((OCDT)(32)) /* is atomic leaf */ #endif default: goto done; case NC_Grid: case NC_Dataset: case NC_Structure: /* Separate out the case where structure is dimensioned */ if(oc_data_indexable(conn,currentcontent)) { /* => dimensioned structure */ /* The current segment should reflect the proper parts of the nc_get_vara argument */ /* Create odometer for this structure's part of the projection */ odom = dapodom_fromsegment(segment,0,segment->rank); while(dapodom_more(odom)) { /* Compute which instance to move to*/ ocstat = oc_data_ithelement(conn,currentcontent, odom->index,&dimcontent); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} ASSERT(oc_data_indexed(conn,dimcontent)); ncstat = movetor(nccomm,dimcontent, path,depth,/*keep same depth*/ xgetvar,dimindex+segment->rank, memory,segments); dapodom_next(odom); } dapodom_free(odom); } else {/* scalar instance */ ncstat = movetofield(nccomm,currentcontent,path,depth,xgetvar,dimindex,memory,segments); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} } break; case NC_Sequence: if(fIsSet(mode,OCDT_SEQUENCE)) { ASSERT((xnode->attachment != NULL)); ASSERT((segment != NULL)); ASSERT((segment->rank == 1)); /* Build an odometer for walking the sequence, however, watch out for the case when the user set a limit and that limit is not actually reached in this request. */ /* By construction, this sequence represents the first (and only) dimension of this segment */ odom = dapodom_fromsegment(segment,0,1); while(dapodom_more(odom)) { size_t recordindex = dapodom_count(odom); ocstat = oc_data_ithrecord(conn,currentcontent, recordindex,&reccontent); if(ocstat != OC_NOERR) { if(ocstat == OC_EINDEX) ocstat = OC_EINVALCOORDS; THROWCHK(ocstat); goto done; } ncstat = movetor(nccomm,reccontent, path,depth, xgetvar,dimindex+1, memory,segments); if(ncstat != OC_NOERR) {THROWCHK(ncstat); goto done;} dapodom_next(odom); } } else if(fIsSet(mode,OCDT_RECORD)) { /* Treat like structure */ /* currentcontent points to the record instance */ ncstat = movetofield(nccomm,currentcontent,path,depth,xgetvar,dimindex,memory,segments); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} } break; case NC_Atomic: if(hasstringdim) ncstat = extractstring(nccomm, xgetvar, xnode, segment, dimindex, conn, currentcontent, memory); else ncstat = extract(nccomm, xgetvar, xnode, segment, dimindex, conn, currentcontent, memory); break; } done: oc_data_free(conn,dimcontent); oc_data_free(conn,fieldcontent); oc_data_free(conn,reccontent); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
static int mergedas1(OCconnection conn, CDFnode* dds, OCobject das) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; unsigned int i,j; unsigned int nsubnodes; OCobject* subnodes = NULL; OCobject* dodsnodes = NULL; unsigned int ndodsnodes; if(dds == NULL || das == OCNULL) return NC_NOERR; /* nothing to do */ if(dds->attributes == NULL) dds->attributes = nclistnew(); /* assign the simple attributes in the das set to this dds node*/ OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes)); OCHECK(oc_inq_subnodes(conn,das,&subnodes)); for(i=0;i<nsubnodes;i++) { OCobject attnode = subnodes[i]; OCtype octype, ocetype; char* ocname = NULL; unsigned int ocnvalues; OCHECK(oc_inq_name(conn,attnode,&ocname)); OCHECK(oc_inq_class(conn,attnode,&octype)); if(octype == OC_Attribute) { NCattribute* att = NULL; NClist* stringvalues; OCHECK(oc_inq_primtype(conn,attnode,&ocetype)); OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues)); stringvalues = nclistnew(); for(j=0;j<ocnvalues;j++) { char* stringval; OCHECK(oc_inq_dasattr(conn,attnode,j,&ocetype,&stringval)); nclistpush(stringvalues,(ncelem)stringval); } ncstat = buildattribute(ocname, octypetonc(ocetype), stringvalues, &att); if(ncstat) goto done; nclistpush(dds->attributes,(ncelem)att); } else if(octype == OC_Attributeset && strcmp(ocname,"DODS")==0) { /* This is a DODS special attribute set */ OCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes)); OCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes)); for(j=0;j<ndodsnodes;j++) { char* dodsname = NULL; char* stringval; OCobject dodsnode = dodsnodes[j]; OCHECK(oc_inq_class(conn,dodsnode,&octype)); if(octype != OC_Attribute) continue; OCHECK(oc_inq_name(conn,dodsnode,&dodsname)); OCHECK(oc_inq_dasattr_nvalues(conn,dodsnode,&ocnvalues)); if(strcmp(dodsname,"strlen")==0) { unsigned int maxstrlen = 0; if(ocnvalues > 0) { OCHECK(oc_inq_dasattr(conn,dodsnode,0,NULL,&stringval)); if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0; efree(stringval); } dds->dodsspecial.maxstrlen = maxstrlen; #ifdef DEBUG fprintf(stderr,"%s.maxstrlen=%d\n",dds->name,(int)dds->dodsspecial.maxstrlen); #endif } else if(strcmp(dodsname,"dimName")==0) { if(ocnvalues > 0) { OCHECK(oc_inq_dasattr(conn,dodsnode,0,NULL, &dds->dodsspecial.dimname)); #ifdef DEBUG fprintf(stderr,"%s.dimname=%s\n",dds->name,dds->dodsspecial.dimname); #endif } else dds->dodsspecial.dimname = NULL; } /* else ignore */ efree(dodsname); } efree(dodsnodes); } /* else ignore */ efree(ocname); } done: efree(subnodes); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
int dapmerge3(NCDRNO* drno, CDFnode* ddsroot, OCobject dasroot) { unsigned int i,j; NCerror ncerr = NC_NOERR; OCerror ocstat = OC_NOERR; OCconnection conn = drno->dap.conn; unsigned int nsubnodes, nobjects; OCobject* dasobjects = NULL; NClist* dasglobals = nclistnew(); NClist* dodsextra = nclistnew(); NClist* dasnodes = nclistnew(); NClist* varnodes = nclistnew(); NClist* allddsnodes = ddsroot->tree->nodes; nobjects = oc_inq_nobjects(conn,dasroot); dasobjects = oc_inq_objects(conn,dasroot); /* 1. collect all the relevant DAS nodes; namely those that contain at least one attribute value. Simultaneously look for potential ambiguities if found; complain but continue: result are indeterminate. also collect globals and DODS_EXTRAs separately*/ for(i=0;i<nobjects;i++) { OCobject das = dasobjects[i]; OCtype octype; char* ocname = NULL; int isglobal = 0; int hasattributes = 0; OCobject* subnodes; OCHECK(oc_inq_class(conn,das,&octype)); if(octype == OC_Attribute) continue; /* ignore these for now*/ OCHECK(oc_inq_name(conn,das,&ocname)); OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes)); isglobal = (ocname == NULL ? 0 : isglobalname3(ocname)); if(ocname == NULL || isglobal) { nclistpush(dasglobals,(ncelem)das); efree(ocname); continue; } if(ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) { nclistpush(dodsextra,(ncelem)das); efree(ocname); continue; } OCHECK(oc_inq_subnodes(conn,das,&subnodes)); for(j=0;j<nsubnodes;j++) { OCobject subnode = subnodes[j]; OCtype ocsubtype; OCHECK(oc_inq_class(conn,subnode,&ocsubtype)); if(ocsubtype == OC_Attribute) {hasattributes = 1; break;} } efree(subnodes); if(hasattributes) { /* Look for previously collected nodes with same name*/ for(j=0;j<nclistlength(dasnodes);j++) { OCobject das2 = (OCobject)nclistget(dasnodes,j); char* ocname2; OCHECK(oc_inq_name(conn,das2,&ocname2)); if(ocname2 == NULL || ocname == NULL) goto loop; if(strcmp(ocname2,"DODS")==0) goto loop; if(strcmp(ocname,ocname2)==0) oc_log(OCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2); loop: efree(ocname2); } nclistpush(dasnodes,(ncelem)das); } efree(ocname); } /* 2. collect all the leaf DDS nodes (of type NC_Primitive)*/ for(i=0;i<nclistlength(allddsnodes);i++) { CDFnode* dds = (CDFnode*)nclistget(allddsnodes,i); if(dds->nctype == NC_Primitive) nclistpush(varnodes,(ncelem)dds); } /* 3. For each das node, lncate matching DDS node(s) and attach attributes to the DDS node(s). Match means: 1. DAS->fullname :: DDS->fullname 2. DAS->name :: DDS->fullname (support DAS names with embedded '.' 3. DAS->name :: DDS->name */ for(i=0;i<nclistlength(dasnodes);i++) { OCobject das = (OCobject)nclistget(dasnodes,i); char* ocfullname; char* ocbasename; if(das == OCNULL) continue; ocfullname = makeocpathstring3(conn,das,"."); OCHECK(oc_inq_name(conn,das,&ocbasename)); for(j=0;j<nclistlength(varnodes);j++) { CDFnode* dds = (CDFnode*)nclistget(varnodes,j); char* ddsfullname = makesimplepathstring3(dds); if(strcmp(ocfullname,ddsfullname)==0 || strcmp(ocbasename,ddsfullname)==0 || strcmp(ocbasename,dds->name)==0) { mergedas1(conn,dds,das); /* remove from dasnodes list*/ nclistset(dasnodes,i,(ncelem)NULL); } efree(ddsfullname); } efree(ocfullname); efree(ocbasename); } /* 4. Assign globals*/ for(i=0;i<nclistlength(dasglobals);i++) { OCobject das = (OCobject)nclistget(dasglobals,i); mergedas1(conn,ddsroot,das); } /* process DOD_EXTRA */ if(nclistlength(dodsextra) > 0) dodsextra3(drno,ddsroot,dodsextra); done: /* cleanup*/ efree(dasobjects); nclistfree(dasglobals); nclistfree(dasnodes); nclistfree(dodsextra); nclistfree(varnodes); if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat); return THROW(ncerr); }
/* Invoke oc_merge_das and then extract special attributes such as "strlen" and "dimname" and stuff from DODS_EXTRA. */ int dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot) { int i,j; NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; NClist* allnodes; OClink conn; char* ocname = NULL; char** values = NULL; conn = nccomm->oc.conn; if(ddsroot == NULL || dasroot == NULL) return NC_NOERR; /* Merge the das tree onto the dds tree */ ocstat = oc_merge_das(nccomm->oc.conn,dasroot,ddsroot); if(ocstat != OC_NOERR) goto done; /* Create attributes on CDFnodes */ allnodes = nccomm->cdf.ddsroot->tree->nodes; for(i=0;i<nclistlength(allnodes);i++) { CDFnode* node = (CDFnode*)nclistget(allnodes,i); OCddsnode ocnode = node->ocnode; size_t attrcount; OCtype ocetype; OCCHECK(oc_dds_attr_count(conn,ocnode,&attrcount)); for(j=0;j<attrcount;j++) { size_t nvalues; NCattribute* att = NULL; if(ocname != NULL) { free(ocname); ocname = NULL; } /* from last loop */ OCCHECK(oc_dds_attr(conn,ocnode,j,&ocname,&ocetype,&nvalues,NULL)); if(nvalues > 0) { values = (char**)malloc(sizeof(char*)*nvalues); if(values == NULL) {ncstat = NC_ENOMEM; goto done;} OCCHECK(oc_dds_attr(conn,ocnode,j,NULL,NULL,NULL,values)); } ncstat = buildattribute(ocname,octypetonc(ocetype),nvalues,values,&att); if(ncstat != NC_NOERR) goto done; if(node->attributes == NULL) node->attributes = nclistnew(); nclistpush(node->attributes,(void*)att); if(strncmp(ocname,"DODS",strlen("DODS"))==0) { att->invisible = 1; /* Define extra semantics associated with DODS and DODS_EXTRA attributes */ if(strcmp(ocname,"DODS.strlen")==0 || strcmp(ocname,"DODS_EXTRA.strlen")==0) { unsigned int maxstrlen = 0; if(values != NULL) { if(0==sscanf(values[0],"%u",&maxstrlen)) maxstrlen = 0; } node->dodsspecial.maxstrlen = maxstrlen; #ifdef DEBUG fprintf(stderr,"%s.maxstrlen=%d\n",node->ocname,(int)node->dodsspecial.maxstrlen); #endif } else if(strcmp(ocname,"DODS.dimName")==0 || strcmp(ocname,"DODS_EXTRA.dimName")==0) { if(values != NULL) { node->dodsspecial.dimname = nulldup(values[0]); #ifdef DEBUG fprintf(stderr,"%s.dimname=%s\n",node->ocname,node->dodsspecial.dimname); #endif } else node->dodsspecial.dimname = NULL; } else if(strcmp(ocname,"DODS.Unlimited_Dimension")==0 || strcmp(ocname,"DODS_EXTRA.Unlimited_Dimension")==0) { if(values != NULL) { if(nccomm->cdf.recorddimname != NULL) nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications"); else nccomm->cdf.recorddimname = nulldup(values[0]); #ifdef DEBUG fprintf(stderr,"%s.Unlimited_Dimension=%s\n",node->ocname,nccomm->cdf.recorddimname); #endif } } } /* clean up */ if(values) { oc_reclaim_strings(nvalues,values); free(values); values = NULL; } } } done: if(values != NULL) free(values); if(ocname != NULL) free(ocname); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
static int mergedas1(NCDAPCOMMON* nccomm, OCconnection conn, CDFnode* dds, OCobject das) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; unsigned int i,j,k; unsigned int nsubnodes; OCobject* subnodes = NULL; OCobject* dodsnodes = NULL; unsigned int ndodsnodes; if(dds == NULL || das == OCNULL) return NC_NOERR; /* nothing to do */ if(dds->attributes == NULL) dds->attributes = nclistnew(); /* assign the simple attributes in the das set to this dds node*/ OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes)); OCHECK(oc_inq_subnodes(conn,das,&subnodes)); for(i=0;i<nsubnodes;i++) { OCobject attnode = subnodes[i]; OCtype octype, ocetype; char* ocname = NULL; unsigned int ocnvalues; OCHECK(oc_inq_name(conn,attnode,&ocname)); OCHECK(oc_inq_class(conn,attnode,&octype)); if(octype == OC_Attribute) { NCattribute* att = NULL; NClist* stringvalues; OCHECK(oc_inq_primtype(conn,attnode,&ocetype)); OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues)); stringvalues = nclistnew(); for(j=0;j<ocnvalues;j++) { char* stringval; OCHECK(oc_inq_dasattr(conn,attnode,j,&ocetype,&stringval)); nclistpush(stringvalues,(ncelem)stringval); } ncstat = buildattribute(ocname, octypetonc(ocetype), stringvalues, &att); if(ncstat) goto done; nclistpush(dds->attributes,(ncelem)att); } else if(octype == OC_Attributeset && (strcmp(ocname,"DODS")==0 || strcmp(ocname,"DODS_EXTRA")==0)) { /* Turn the DODS special attributes into into special attributes for dds node */ OCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes)); OCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes)); for(j=0;j<ndodsnodes;j++) { char* dodsname = NULL; char newname[4096]; OCobject attnode = dodsnodes[j]; NCattribute* att = NULL; NClist* stringvalues; OCHECK(oc_inq_class(conn,attnode,&octype)); if(octype != OC_Attribute) continue; OCHECK(oc_inq_primtype(conn,attnode,&ocetype)); OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues)); stringvalues = nclistnew(); for(k=0;k<ocnvalues;k++) { char* stringval; OCHECK(oc_inq_dasattr(conn,attnode,k,&ocetype,&stringval)); nclistpush(stringvalues,(ncelem)stringval); } OCHECK(oc_inq_name(conn,attnode,&dodsname)); /* Compute new special name */ strcpy(newname,"_DODS_"); strcat(newname,dodsname); ncstat = buildattribute(newname, octypetonc(ocetype), stringvalues, &att); if(ncstat) goto done; att->invisible = 1; nclistpush(dds->attributes,(ncelem)att); /* Define extra semantics associated with DODS and DODS_EXTRA attribute */ if(strcmp(dodsname,"strlen")==0) { unsigned int maxstrlen = 0; if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0; } dds->dodsspecial.maxstrlen = maxstrlen; #ifdef DEBUG fprintf(stderr,"%s.maxstrlen=%d\n",dds->ocname,(int)dds->dodsspecial.maxstrlen); #endif } else if(strcmp(dodsname,"dimName")==0) { if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); dds->dodsspecial.dimname = nulldup(stringval); #ifdef DEBUG fprintf(stderr,"%s.dimname=%s\n",dds->ocname,dds->dodsspecial.dimname); #endif } else dds->dodsspecial.dimname = NULL; } else if(strcmp(dodsname,"Unlimited_Dimension")==0) { if(nccomm->cdf.recorddimname != NULL) { nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications"); } else if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); nccomm->cdf.recorddimname = nulldup(stringval); #ifdef DEBUG fprintf(stderr,"%s.Unlimited_Dimension=%s\n",dds->ocname,nccomm->cdf.recorddimname); #endif } } /* else ignore */ nullfree(dodsname); } nullfree(dodsnodes); } nullfree(ocname); } done: nullfree(subnodes); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
/* Provide a wrapper for oc_fetch so we can log what it does */ NCerror dap_fetch(NCDAPCOMMON* nccomm, OClink conn, const char* ce, OCdxd dxd, OCddsnode* rootp) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; char* ext = NULL; OCflags flags = 0; int httpcode = 0; if(dxd == OCDDS) ext = ".dds"; else if(dxd == OCDAS) ext = ".das"; else ext = ".dods"; if(ce != NULL && strlen(ce) == 0) ce = NULL; if(FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE)) { ce = NULL; } if(FLAGSET(nccomm->controls,NCF_ONDISK)) { flags |= OCONDISK; } if(SHOWFETCH) { /* Build uri string minus the constraint and #tag */ char* baseurl = ncuribuild(nccomm->oc.url,NULL,ext,NCURIBASE); if(ce == NULL) LOG1(NCLOGNOTE,"fetch: %s",baseurl); else LOG2(NCLOGNOTE,"fetch: %s?%s",baseurl,ce); nullfree(baseurl); #ifdef HAVE_GETTIMEOFDAY gettimeofday(&time0,NULL); #endif } ocstat = oc_fetch(conn,ce,dxd,flags,rootp); if(FLAGSET(nccomm->controls,NCF_SHOWFETCH)) { #ifdef HAVE_GETTIMEOFDAY double secs; gettimeofday(&time1,NULL); secs = deltatime(); nclog(NCLOGNOTE,"fetch complete: %0.3f secs",secs); #else nclog(NCLOGNOTE,"fetch complete."); #endif } #ifdef DEBUG2 fprintf(stderr,"fetch: dds:\n"); oc_dumpnode(conn,*rootp); #endif /* Look at the HTTP return code */ httpcode = oc_httpcode(conn); if(httpcode < 400) { ncstat = ocerrtoncerr(ocstat); } else if(httpcode >= 500) { ncstat = NC_EDAPSVC; } else if(httpcode == 401) { ncstat = NC_EAUTH; } else if(httpcode == 404) { ncstat = NC_ENOTFOUND; } else { ncstat = NC_EACCESS; } return ncstat; }
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; OClink conn = dapcomm->oc.conn; size_t recordcount; CDFnode* xroot; OCdatanode data = NULL; ASSERT((xseq->nctype == NC_Sequence)); /* collect the path to the sequence node */ collectnodepath3(xseq,path,WITHDATASET); /* Get tree root */ ASSERT(xseq->root == (CDFnode*)nclistget(path,0)); xroot = xseq->root; ocstat = oc_data_getroot(conn,xroot->tree->ocroot,&data); if(ocstat) goto done; /* Basically we use the path to walk the data instances to reach the sequence instance */ for(i=0;i<nclistlength(path);i++) { CDFnode* current = (CDFnode*)nclistget(path,i); OCdatanode nextdata = NULL; CDFnode* next = NULL; /* invariant: current = ith node in path; data = corresponding datanode */ /* get next node in next and next instance in nextdata */ if(current->nctype == NC_Structure || current->nctype == NC_Dataset) { if(nclistlength(current->array.dimset0) > 0) { /* Cannot handle this case */ ncstat = THROW(NC_EDDS); goto done; } /* get next node in path; structure/dataset => exists */ next = (CDFnode*)nclistget(path,i+1); index = fieldindex(current,next); /* Move to appropriate field */ ocstat = oc_data_ithfield(conn,data,index,&nextdata); if(ocstat) goto done; oc_data_free(conn,data); data = nextdata; /* set up for next loop iteration */ } else if(current->nctype == NC_Sequence) { /* Check for nested Sequences */ if(current != xseq) { /* Cannot handle this case */ ncstat = THROW(NC_EDDS); goto done; } /* Get the record count */ ocstat = oc_data_recordcount(conn,data,&recordcount); if(sizep) *sizep = recordcount; oc_data_free(conn,data); /* reclaim */ break; /* leave the loop */ } else { PANIC("unexpected mode"); return NC_EINVAL; } } done: nclistfree(path); if(ocstat) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
static NCerror getseqdimsize(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t* sizep) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; OClink conn = dapcomm->oc.conn; OCdatanode rootcontent = NULL; OCddsnode 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; }
NCerror nc3d_getvarx(int ncid, int varid, const size_t *startp, const size_t *countp, const ptrdiff_t* stridep, void *data, nc_type dsttype0) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; int i; NC* drno; NC* substrate; NCDAPCOMMON* dapcomm; CDFnode* cdfvar = NULL; /* cdf node mapping to var*/ NClist* varnodes; nc_type dsttype; Getvara* varainfo = NULL; CDFnode* xtarget = NULL; /* target in DATADDS */ CDFnode* target = NULL; /* target in constrained DDS */ DCEprojection* varaprojection = NULL; NCcachenode* cachenode = NULL; size_t localcount[NC_MAX_VAR_DIMS]; NClist* ncdimsall; size_t ncrank; NClist* vars = NULL; DCEconstraint* fetchconstraint = NULL; DCEprojection* fetchprojection = NULL; DCEprojection* walkprojection = NULL; int state; #define FETCHWHOLE 1 /* fetch whole data set */ #define FETCHVAR 2 /* fetch whole variable */ #define FETCHPART 4 /* fetch constrained variable */ #define CACHED 8 /* whole variable is already in the cache */ ncstat = NC_check_id(ncid, (NC**)&drno); if(ncstat != NC_NOERR) goto fail; dapcomm = (NCDAPCOMMON*)drno->dispatchdata; ncstat = NC_check_id(drno->substrate, (NC**)&substrate); if(ncstat != NC_NOERR) goto fail; /* Locate var node via varid */ varnodes = dapcomm->cdf.ddsroot->tree->varnodes; for(i=0;i<nclistlength(varnodes);i++) { CDFnode* node = (CDFnode*)nclistget(varnodes,i); if(node->array.basevar == NULL && node->nctype == NC_Atomic && node->ncid == varid) { cdfvar = node; break; } } ASSERT((cdfvar != NULL)); /* If the variable is prefetchable, then now is the time to do a lazy prefetch */ if(FLAGSET(dapcomm->controls,NCF_PREFETCH) && !FLAGSET(dapcomm->controls,NCF_PREFETCH_EAGER)) { if(dapcomm->cdf.cache != NULL && dapcomm->cdf.cache->prefetch == NULL) { ncstat = prefetchdata3(dapcomm); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } } /* Get the dimension info */ ncdimsall = cdfvar->array.dimsetall; ncrank = nclistlength(ncdimsall); #ifdef DEBUG { int i; fprintf(stderr,"getvarx: %s",cdfvar->ncfullname); for(i=0;i<ncrank;i++) fprintf(stderr,"(%ld:%ld:%ld)", (long)startp[i], (long)countp[i], (long)stridep[i] ); fprintf(stderr,"\n"); } #endif /* Fill in missing arguments */ if(startp == NULL) startp = nc_sizevector0; if(countp == NULL) { /* Accumulate the dimension sizes */ for(i=0;i<ncrank;i++) { CDFnode* dim = (CDFnode*)nclistget(ncdimsall,i); localcount[i] = dim->dim.declsize; } countp = localcount; } if(stridep == NULL) stridep = nc_ptrdiffvector1; /* Validate the dimension sizes */ for(i=0;i<ncrank;i++) { CDFnode* dim = (CDFnode*)nclistget(ncdimsall,i); if(startp[i] > dim->dim.declsize || startp[i]+countp[i] > dim->dim.declsize) { ncstat = NC_EINVALCOORDS; goto fail; } } #ifdef DEBUG { NClist* dims = cdfvar->array.dimsetall; fprintf(stderr,"getvarx: %s",cdfvar->ncfullname); if(nclistlength(dims) > 0) {int i; for(i=0;i<nclistlength(dims);i++) fprintf(stderr,"(%lu:%lu:%lu)",(unsigned long)startp[i],(unsigned long)countp[i],(unsigned long)stridep[i]); fprintf(stderr," -> "); for(i=0;i<nclistlength(dims);i++) if(stridep[i]==1) fprintf(stderr,"[%lu:%lu]",(unsigned long)startp[i],(unsigned long)((startp[i]+countp[i])-1)); else { unsigned long iend = (stridep[i] * countp[i]); iend = (iend + startp[i]); iend = (iend - 1); fprintf(stderr,"[%lu:%lu:%lu]", (unsigned long)startp[i],(unsigned long)stridep[i],iend); } } fprintf(stderr,"\n"); } #endif dsttype = (dsttype0); /* Default to using the inquiry type for this var*/ if(dsttype == NC_NAT) dsttype = cdfvar->externaltype; /* Validate any implied type conversion*/ if(cdfvar->etype != dsttype && dsttype == NC_CHAR) { /* The only disallowed conversion is to/from char and non-byte numeric types*/ switch (cdfvar->etype) { case NC_STRING: case NC_URL: case NC_CHAR: case NC_BYTE: case NC_UBYTE: break; default: return THROW(NC_ECHAR); } } ncstat = makegetvar34(dapcomm,cdfvar,data,dsttype,&varainfo); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} /* Compile the start/stop/stride info into a projection */ ncstat = buildvaraprojection3(varainfo->target, startp,countp,stridep, &varaprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} fetchprojection = NULL; walkprojection = NULL; /* Create walkprojection as the merge of the url projections and the vara projection; may change in FETCHPART case below*/ ncstat = daprestrictprojection(dapcomm->oc.dapconstraint->projections, varaprojection,&walkprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} #ifdef DEBUG fprintf(stderr,"getvarx: walkprojection: |%s|\n",dumpprojection(walkprojection)); #endif /* define the var list of interest */ vars = nclistnew(); nclistpush(vars,(void*)varainfo->target); state = 0; if(iscached(dapcomm,cdfvar,&cachenode)) { /* ignores non-whole variable cache entries */ state = CACHED; ASSERT((cachenode != NULL)); #ifdef DEBUG fprintf(stderr,"var is in cache\n"); #endif /* If it is cached, then it is a whole variable but may still need to apply constraints during the walk */ ASSERT(cachenode->wholevariable); /* by construction */ } else if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) { state = FETCHWHOLE; } else {/* load using constraints */ if(FLAGSET(dapcomm->controls,NCF_WHOLEVAR)) state = FETCHVAR; else state = FETCHPART; } ASSERT(state != 0); switch (state) { case FETCHWHOLE: { /* buildcachenode3 will create a new cachenode and will also fetch the whole corresponding datadds. */ /* Build the complete constraint to use in the fetch */ fetchconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); /* Use no projections or selections */ fetchconstraint->projections = nclistnew(); fetchconstraint->selections = nclistnew(); #ifdef DEBUG fprintf(stderr,"getvarx: FETCHWHOLE: fetchconstraint: %s\n",dumpconstraint(fetchconstraint)); #endif ncstat = buildcachenode34(dapcomm,fetchconstraint,vars,&cachenode,0); fetchconstraint = NULL; /*buildcachenode34 takes control of fetchconstraint.*/ if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } break; case CACHED: { } break; case FETCHVAR: { /* Fetch a complete single variable */ /* Create fetch projection as the merge of the url projections and the vara projection */ ncstat = daprestrictprojection(dapcomm->oc.dapconstraint->projections, varaprojection,&fetchprojection); /* elide any sequence and string dimensions (dap servers do not allow such). */ ncstat = removepseudodims(fetchprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} /* Convert to a whole variable projection */ dcemakewholeprojection(fetchprojection); #ifdef DEBUG fprintf(stderr,"getvarx: FETCHVAR: fetchprojection: |%s|\n",dumpprojection(fetchprojection)); #endif /* Build the complete constraint to use in the fetch */ fetchconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); /* merged constraint just uses the url constraint selection */ fetchconstraint->selections = dceclonelist(dapcomm->oc.dapconstraint->selections); /* and the created fetch projection */ fetchconstraint->projections = nclistnew(); nclistpush(fetchconstraint->projections,(void*)fetchprojection); #ifdef DEBUG fprintf(stderr,"getvarx: FETCHVAR: fetchconstraint: %s\n",dumpconstraint(fetchconstraint)); #endif /* buildcachenode3 will create a new cachenode and will also fetch the corresponding datadds. */ ncstat = buildcachenode34(dapcomm,fetchconstraint,vars,&cachenode,0); fetchconstraint = NULL; /*buildcachenode34 takes control of fetchconstraint.*/ if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } break; case FETCHPART: { /* Create fetch projection as the merge of the url projections and the vara projection */ ncstat = daprestrictprojection(dapcomm->oc.dapconstraint->projections, varaprojection,&fetchprojection); /* elide any sequence and string dimensions (dap servers do not allow such). */ ncstat = removepseudodims(fetchprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} /* Shift the varaprojection for simple walk */ dcefree((DCEnode*)walkprojection) ; /* reclaim any existing walkprojection */ walkprojection = (DCEprojection*)dceclone((DCEnode*)varaprojection); dapshiftprojection(walkprojection); #ifdef DEBUG fprintf(stderr,"getvarx: FETCHPART: fetchprojection: |%s|\n",dumpprojection(fetchprojection)); #endif /* Build the complete constraint to use in the fetch */ fetchconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); /* merged constraint just uses the url constraint selection */ fetchconstraint->selections = dceclonelist(dapcomm->oc.dapconstraint->selections); /* and the created fetch projection */ fetchconstraint->projections = nclistnew(); nclistpush(fetchconstraint->projections,(void*)fetchprojection); #ifdef DEBUG fprintf(stderr,"getvarx: FETCHPART: fetchconstraint: %s\n",dumpconstraint(fetchconstraint)); #endif /* buildcachenode3 will create a new cachenode and will also fetch the corresponding datadds. */ ncstat = buildcachenode34(dapcomm,fetchconstraint,vars,&cachenode,0); fetchconstraint = NULL; /*buildcachenode34 takes control of fetchconstraint.*/ if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} } break; default: PANIC1("unknown fetch state: %d\n",state); } ASSERT(cachenode != NULL); #ifdef DEBUG fprintf(stderr,"cache.datadds=%s\n",dumptree(cachenode->datadds)); #endif /* attach DATADDS to (constrained) DDS */ unattach34(dapcomm->cdf.ddsroot); ncstat = attachsubset34(cachenode->datadds,dapcomm->cdf.ddsroot); if(ncstat) goto fail; /* Fix up varainfo to use the cache */ varainfo->cache = cachenode; cachenode = NULL; varainfo->varaprojection = walkprojection; walkprojection = NULL; /* Get the var correlate from the datadds */ target = varainfo->target; xtarget = target->attachment; if(xtarget == NULL) {THROWCHK(ncstat=NC_ENODATA); goto fail;} /* Switch to datadds tree space*/ varainfo->target = xtarget; save = (DCEnode*)varaprojection; ncstat = moveto(dapcomm,varainfo,varainfo->cache->datadds,data); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto fail;} nclistfree(vars); dcefree((DCEnode*)varaprojection); dcefree((DCEnode*)fetchconstraint); freegetvara(varainfo); fail: if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
NCerror buildcachenode34(NCDAPCOMMON* nccomm, DCEconstraint* constraint, NClist* varlist, NCcachenode** cachep, NCFLAGS flags) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; OClink conn = nccomm->oc.conn; OCddsnode ocroot = NULL; CDFnode* dxdroot = NULL; NCcachenode* cachenode = NULL; char* ce = NULL; int isprefetch = 0; if((flags & NCF_PREFETCH) != 0) isprefetch = 1; if((flags & NCF_PREFETCH_ALL) == 0) ce = buildconstraintstring3(constraint); ocstat = dap_fetch(nccomm,conn,ce,OCDATADDS,&ocroot); nullfree(ce); if(ocstat) {THROWCHK(ocerrtoncerr(ocstat)); goto done;} ncstat = buildcdftree34(nccomm,ocroot,OCDATA,&dxdroot); if(ncstat) {THROWCHK(ncstat); goto done;} /* re-struct*/ if(!FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE)) { ncstat = restruct3(dxdroot,nccomm->cdf.ddsroot,constraint->projections); if(ncstat) {THROWCHK(ncstat); goto done;} } /* create the cache node */ cachenode = createnccachenode(); cachenode->isprefetch = isprefetch; cachenode->vars = nclistclone(varlist); cachenode->datadds = dxdroot; /* Give the constraint over to the cachenode */ cachenode->constraint = constraint; constraint = NULL; cachenode->wholevariable = iscacheableconstraint(cachenode->constraint); /* save the root content*/ cachenode->ocroot = ocroot; ocstat = oc_data_getroot(conn,ocroot,&cachenode->content); if(ocstat) {THROWCHK(ocerrtoncerr(ocstat)); goto done;} /* capture the packet size */ ocstat = oc_raw_xdrsize(conn,ocroot,&cachenode->xdrsize); if(ocstat) {THROWCHK(ocerrtoncerr(ocstat)); goto done;} #ifdef DEBUG fprintf(stderr,"buildcachenode: new cache node: %s\n", dumpcachenode(cachenode)); #endif /* Insert into the cache. If not caching, then remove any previous cache node */ if(!isprefetch) { NCcache* cache = nccomm->cdf.cache; if(cache->nodes == NULL) cache->nodes = nclistnew(); /* remove cache nodes to get below the max cache size */ while(cache->cachesize + cachenode->xdrsize > cache->cachelimit && nclistlength(cache->nodes) > 0) { NCcachenode* node = (NCcachenode*)nclistremove(cache->nodes,0); #ifdef DEBUG fprintf(stderr,"buildcachenode: purge cache node: %s\n", dumpcachenode(cachenode)); #endif cache->cachesize -= node->xdrsize; freenccachenode(nccomm,node); } /* Remove cache nodes to get below the max cache count */ /* If not caching, then cachecount should be 0 */ while(nclistlength(cache->nodes) > cache->cachecount) { NCcachenode* node = (NCcachenode*)nclistremove(cache->nodes,0); #ifdef DEBUG fprintf(stderr,"buildcachenode: count purge cache node: %s\n", dumpcachenode(node)); #endif cache->cachesize -= node->xdrsize; freenccachenode(nccomm,node); } nclistpush(nccomm->cdf.cache->nodes,(void*)cachenode); cache->cachesize += cachenode->xdrsize; } #ifdef DEBUG fprintf(stderr,"buildcachenode: %s\n",dumpcachenode(cachenode)); #endif done: if(constraint != NULL) dcefree((DCEnode*)constraint); if(cachep) *cachep = cachenode; if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); if(ncstat) { freecdfroot34(dxdroot); freenccachenode(nccomm,cachenode); } return THROW(ncstat); }
/* See ncd3dispatch.c for other version */ int NCD3_open(const char * path, int mode, int basepe, size_t *chunksizehintp, int useparallel, void* mpidata, NC_Dispatch* dispatch, NC** ncpp) { NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; NC* drno = NULL; NCDAPCOMMON* dapcomm = NULL; const char* value; char* tmpname = NULL; if(!nc3dinitialized) nc3dinitialize(); if(path == NULL) return NC_EDAPURL; if(dispatch == NULL) PANIC("NC3D_open: no dispatch table"); /* Setup our NC and NCDAPCOMMON state*/ drno = (NC*)calloc(1,sizeof(NC)); if(drno == NULL) {ncstat = NC_ENOMEM; goto done;} /* compute an ncid */ ncstat = add_to_NCList(drno); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} dapcomm = (NCDAPCOMMON*)calloc(1,sizeof(NCDAPCOMMON)); if(dapcomm == NULL) {ncstat = NC_ENOMEM; goto done;} drno->dispatch = dispatch; drno->dispatchdata = dapcomm; dapcomm->controller = (NC*)drno; dapcomm->cdf.separator = "."; dapcomm->cdf.smallsizelimit = DFALTSMALLLIMIT; dapcomm->cdf.cache = createnccache(); #ifdef HAVE_GETRLIMIT { struct rlimit rl; if(getrlimit(RLIMIT_NOFILE, &rl) >= 0) { dapcomm->cdf.cache->cachecount = (size_t)(rl.rlim_cur / 2); } } #endif #ifdef OCCOMPILEBYDEFAULT /* set the compile flag by default */ dapcomm->oc.rawurltext = (char*)emalloc(strlen(path)+strlen("[compile]")+1); strcpy(dapcomm->oc.rawurltext,"[compile]"); strcat(dapcomm->oc.rawurltext, path); #else dapcomm->oc.rawurltext = strdup(path); #endif nc_uriparse(dapcomm->oc.rawurltext,&dapcomm->oc.url); /* parse the client parameters */ nc_uridecodeparams(dapcomm->oc.url); if(!constrainable34(dapcomm->oc.url)) SETFLAG(dapcomm->controls,NCF_UNCONSTRAINABLE); /* Use libsrc code for storing metadata */ tmpname = nulldup(PSEUDOFILE); /* Now, use the file to create the netcdf file */ if(sizeof(size_t) == sizeof(unsigned int)) ncstat = nc_create(tmpname,NC_CLOBBER,&drno->substrate); else ncstat = nc_create(tmpname,NC_CLOBBER|NC_64BIT_OFFSET,&drno->substrate); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* free the filename so it will automatically go away*/ unlink(tmpname); nullfree(tmpname); /* Avoid fill */ nc_set_fill(drno->substrate,NC_NOFILL,NULL); dapcomm->oc.dapconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); dapcomm->oc.dapconstraint->projections = nclistnew(); dapcomm->oc.dapconstraint->selections = nclistnew(); /* Parse constraints to make sure they are syntactically correct */ ncstat = parsedapconstraints(dapcomm,dapcomm->oc.url->constraint,dapcomm->oc.dapconstraint); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* Complain if we are unconstrainable but have constraints */ if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) { if(dapcomm->oc.url->constraint != NULL && strlen(dapcomm->oc.url->constraint) > 0) { nclog(NCLOGWARN,"Attempt to constrain an unconstrainable data source: %s", dapcomm->oc.url->constraint); } } /* Construct a url for oc minus any parameters */ dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL, (NC_URIALL ^ NC_URICONSTRAINTS)); /* Pass to OC */ ocstat = oc_open(dapcomm->oc.urltext,&dapcomm->oc.conn); if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;} nullfree(dapcomm->oc.urltext); /* clean up */ dapcomm->oc.urltext = NULL; /* process control client parameters */ applyclientparamcontrols3(dapcomm); /* Turn on logging; only do this after oc_open*/ if((value = paramvalue34(dapcomm,"log")) != NULL) { ncloginit(); ncsetlogging(1); nclogopen(value); oc_loginit(); oc_setlogging(1); oc_logopen(value); } /* fetch and build the (almost) unconstrained DDS for use as template */ ncstat = fetchtemplatemetadata3(dapcomm); if(ncstat != NC_NOERR) goto done; /* fetch and build the constrained DDS */ ncstat = fetchconstrainedmetadata3(dapcomm); if(ncstat != NC_NOERR) goto done; #ifdef DEBUG2 fprintf(stderr,"constrained dds: %s\n",dumptree(dapcomm->cdf.ddsroot)); #endif /* The following actions are (mostly) WRT to the constrained tree */ /* Accumulate useful nodes sets */ ncstat = computecdfnodesets3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Fix grids */ ncstat = fixgrids3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Locate and mark usable sequences */ ncstat = sequencecheck3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* suppress variables not in usable sequences */ ncstat = suppressunusablevars3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* apply client parameters */ ncstat = applyclientparams34(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Add (as needed) string dimensions*/ ncstat = addstringdims(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} if(nclistlength(dapcomm->cdf.seqnodes) > 0) { /* Build the sequence related dimensions */ ncstat = defseqdims(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} } /* Define the dimsetplus and dimsetall lists */ ncstat = definedimsets3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Re-compute the dimension names*/ ncstat = computecdfdimnames34(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Deal with zero size dimensions */ ncstat = fixzerodims3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} /* Attempt to use the DODS_EXTRA info to turn one of the dimensions into unlimited. Assume computecdfdimnames34 has already been called. */ ncstat = defrecorddim3(dapcomm); if(ncstat) {THROWCHK(ncstat); goto done;} if(dapcomm->cdf.recorddimname != NULL && nclistlength(dapcomm->cdf.seqnodes) > 0) { /*nclog(NCLOGWARN,"unlimited dimension specified, but sequences exist in DDS");*/ PANIC("unlimited dimension specified, but sequences exist in DDS"); } /* Re-compute the var names*/ ncstat = computecdfvarnames3(dapcomm,dapcomm->cdf.ddsroot,dapcomm->cdf.varnodes); if(ncstat) {THROWCHK(ncstat); goto done;} /* Transfer data from the unconstrained DDS data to the unconstrained DDS */ ncstat = dimimprint3(dapcomm); if(ncstat) goto done; /* Process the constraints to map to the constrained CDF tree */ /* (must follow fixgrids3 */ ncstat = mapconstraints3(dapcomm->oc.dapconstraint,dapcomm->cdf.ddsroot); if(ncstat != NC_NOERR) goto done; /* Canonicalize the constraint */ ncstat = fixprojections(dapcomm->oc.dapconstraint->projections); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* Fill in segment information */ ncstat = qualifyconstraints3(dapcomm->oc.dapconstraint); if(ncstat != NC_NOERR) goto done; /* using the modified constraint, rebuild the constraint string */ if(FLAGSET(dapcomm->controls,NCF_UNCONSTRAINABLE)) { /* ignore all constraints */ dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,0); } else { char* constraintstring = buildconstraintstring3(dapcomm->oc.dapconstraint); nc_urisetconstraints(dapcomm->oc.url,constraintstring); nullfree(constraintstring); dapcomm->oc.urltext = nc_uribuild(dapcomm->oc.url,NULL,NULL,NC_URICONSTRAINTS); } #ifdef DEBUG fprintf(stderr,"ncdap3: final constraint: %s\n",dapcomm->oc.url->constraint); #endif /* Estimate the variable sizes */ estimatevarsizes3(dapcomm); /* Build the meta data */ ncstat = buildncstructures3(dapcomm); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} /* Do any necessary data prefetch */ if(FLAGSET(dapcomm->controls,NCF_PREFETCH)) { ncstat = prefetchdata3(dapcomm); if(ncstat != NC_NOERR) { del_from_NCList((NC*)drno); /* undefine here */ {THROWCHK(ncstat); goto done;} } } { /* Mark as no longer writable and no longer indef; requires breaking abstraction */ NC* nc; ncstat = NC_check_id(drno->substrate, &nc); /* Mark as no longer writeable */ fClr(nc->nciop->ioflags, NC_WRITE); /* Mark as no longer indef; (do NOT use nc_enddef until diskless is working)*/ fSet(nc->flags, NC_INDEF); } if(ncpp) *ncpp = (NC*)drno; return ncstat; done: if(drno != NULL) NCD3_abort(drno->ext_ncid); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); }
int dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot) { unsigned int i,j; NCerror ncerr = NC_NOERR; OCerror ocstat = OC_NOERR; OClink conn = nccomm->oc.conn; size_t nsubnodes; NClist* dasglobals = nclistnew(); NClist* dasnodes = nclistnew(); NClist* dodsextra = nclistnew(); NClist* varnodes = nclistnew(); NClist* alldasnodes = nclistnew(); if(ddsroot == NULL || dasroot == NULL) return NC_NOERR; ocstat = collect_alldasnodes(conn,dasroot,alldasnodes); /* 1. collect all the relevant DAS nodes; namely those that contain at least one attribute value. Simultaneously look for potential ambiguities if found; complain but continue: result are indeterminate. also collect globals and DODS_EXTRA separately. */ for(i=0;i<nclistlength(alldasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(alldasnodes,i); OCtype octype; char* ocname = NULL; int isglobal = 0; int hasattributes = 0; OCCHECK(oc_dds_class(conn,das,&octype)); if(octype == OC_Attribute) continue; /* ignore these for now*/ OCCHECK(oc_dds_name(conn,das,&ocname)); OCCHECK(oc_dds_nsubnodes(conn,das,&nsubnodes)); isglobal = (ocname == NULL ? 0 : isglobalname3(ocname)); /* catch DODS_EXTRA */ if(isglobal && ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) { nclistpush(dodsextra,(void*)das); nullfree(ocname); continue; } if(ocname == NULL || isglobal) { nclistpush(dasglobals,(void*)das); nullfree(ocname); continue; } hasattributes = hasattribute3(conn,das); if(hasattributes) { /* Look for previously collected nodes with same name*/ for(j=0;j<nclistlength(dasnodes);j++) { OCddsnode das2 = (OCddsnode)nclistget(dasnodes,j); char* ocname2; OCCHECK(oc_dds_name(conn,das2,&ocname2)); if(ocname2 == NULL || ocname == NULL) goto loop; if(strcmp(ocname2,"DODS")==0) goto loop; if(strcmp(ocname,ocname2)==0) nclog(NCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2); loop: nullfree(ocname2); } nclistpush(dasnodes,(void*)das); } nullfree(ocname); } /* 2. collect all the leaf DDS nodes (of type NC_Atomic)*/ ocstat = collect_leaves(link,ddsroot,varnodes); /* 3. For each das node, locate matching DDS node(s) and attach attributes to the DDS node(s). Match means: 1. DAS->fullname :: DDS->fullname 2. DAS->name :: DDS->fullname (support DAS names with embedded '.' 3. DAS->name :: DDS->name 4. special case for DODS. Apply 1-3 on DODS parent. */ for(i=0;i<nclistlength(dasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(dasnodes,i); char* ocfullname = NULL; char* ocbasename = NULL; if(das == NULL) continue; OCCHECK(oc_dds_name(conn,das,&ocbasename)); if(strcmp(ocbasename,"DODS")==0) { OCddsnode container; OCCHECK(oc_dds_container(conn,das,&container)); ASSERT(container != NULL); ocfullname = makeocpathstring3(conn,container,"."); } else { ocfullname = makeocpathstring3(conn,das,"."); } for(j=0;j<nclistlength(varnodes);j++) { CDFnode* dds = (CDFnode*)nclistget(varnodes,j); char* ddsfullname = makecdfpathstring3(dds,"."); if(strcmp(ocfullname,ddsfullname)==0 || strcmp(ocbasename,ddsfullname)==0 || strcmp(ocbasename,dds->ocname)==0) { mergedas1(nccomm,conn,dds,das); /* remove from dasnodes list*/ nclistset(dasnodes,i,(void*)NULL); } nullfree(ddsfullname); } nullfree(ocfullname); nullfree(ocbasename); } /* 4. Assign globals */ for(i=0;i<nclistlength(dasglobals);i++) { OCddsnode das = (OCddsnode)nclistget(dasglobals,i); mergedas1(nccomm,conn,ddsroot,das); } /* 5. Assign DOD_EXTRA */ for(i=0;i<nclistlength(dodsextra);i++) { OCddsnode das = (OCddsnode)nclistget(dodsextra,i); mergedas1(nccomm,conn,ddsroot,das); } done: /* cleanup*/ nclistfree(dasglobals); nclistfree(dasnodes); nclistfree(alldasnodes); nclistfree(dodsextra); nclistfree(varnodes); if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat); return THROW(ncerr); }