static NCerror mapnodesr(CDFnode* connode, CDFnode* fullnode, int depth) { unsigned int i,j; NCerror ncstat = NC_NOERR; ASSERT((simplenodematch(connode,fullnode))); #ifdef DEBUG { char* path1 = makecdfpathstring(fullnode,"."); char* path2 = makecdfpathstring(connode,"."); fprintf(stderr,"mapnode: %s->%s\n",path1,path2); nullfree(path1); nullfree(path2); } #endif /* Map node */ mapfcn(connode,fullnode); #if 0 { int i; for(i=0;i<nclistlength(fullnode->subnodes);i++) { CDFnode* n = (CDFnode*)nclistget(fullnode->subnodes,i); fprintf(stderr,"fullnode.subnode[%d]: (%d) %s\n",i,n->nctype,n->ocname); } for(i=0;i<nclistlength(connode->subnodes);i++) { CDFnode* n = (CDFnode*)nclistget(connode->subnodes,i); fprintf(stderr,"connode.subnode[%d]: (%d) %s\n",i,n->nctype,n->ocname); } } #endif /* Try to match connode subnodes against fullnode subnodes */ ASSERT(nclistlength(connode->subnodes) <= nclistlength(fullnode->subnodes)); for(i=0;i<nclistlength(connode->subnodes);i++) { CDFnode* consubnode = (CDFnode*)nclistget(connode->subnodes,i); /* Search full subnodes for a matching subnode from con */ for(j=0;j<nclistlength(fullnode->subnodes);j++) { CDFnode* fullsubnode = (CDFnode*)nclistget(fullnode->subnodes,j); if(simplenodematch(fullsubnode,consubnode)) { ncstat = mapnodesr(consubnode,fullsubnode,depth+1); if(ncstat) goto done; } } } done: return THROW(ncstat); }
char* dumpcachenode(NCcachenode* node) { char* result = NULL; char tmp[8192]; int i; NCbytes* buf; if(node == NULL) return strdup("cachenode{null}"); buf = ncbytesnew(); result = buildconstraintstring(node->constraint); snprintf(tmp,sizeof(tmp),"cachenode%s(%lx){size=%lu; constraint=%s; vars=", node->isprefetch?"*":"", (unsigned long)node, (unsigned long)node->xdrsize, result); ncbytescat(buf,tmp); if(nclistlength(node->vars)==0) ncbytescat(buf,"null"); else for(i=0;i<nclistlength(node->vars);i++) { CDFnode* var = (CDFnode*)nclistget(node->vars,i); if(i > 0) ncbytescat(buf,","); ncbytescat(buf,makecdfpathstring(var,".")); } ncbytescat(buf,"}"); result = ncbytesdup(buf); ncbytesfree(buf); return result; }
NCerror dimimprint(NCDAPCOMMON* nccomm) { NCerror ncstat = NC_NOERR; NClist* allnodes; int i,j; CDFnode* basenode; allnodes = nccomm->cdf.ddsroot->tree->nodes; for(i=0;i<nclistlength(allnodes);i++) { CDFnode* node = (CDFnode*)nclistget(allnodes,i); int noderank, baserank; /* Do dimension imprinting */ basenode = node->basenode; if(basenode == NULL) continue; noderank = nclistlength(node->array.dimset0); baserank = nclistlength(basenode->array.dimset0); if(noderank == 0) continue; ASSERT(noderank == baserank); #ifdef DEBUG fprintf(stderr,"dimimprint %s/%d -> %s/%d\n", makecdfpathstring(basenode,"."), noderank, makecdfpathstring(node,"."), baserank); #endif for(j=0;j<noderank;j++) { CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j); CDFnode* basedim = (CDFnode*)nclistget(basenode->array.dimset0,j); dim->dim.declsize0 = basedim->dim.declsize; #ifdef DEBUG fprintf(stderr,"dimimprint: %d: %lu -> %lu\n",i,basedim->dim.declsize,dim->dim.declsize0); #endif } } return ncstat; }
/* Exceptions: anonymous dimensions. */ static NCerror fix1node(NCDAPCOMMON* nccomm, CDFnode* node) { if(node->nctype == NC_Dimension && node->ocname == NULL) return NC_NOERR; ASSERT((node->ocname != NULL)); nullfree(node->ncbasename); node->ncbasename = cdflegalname(node->ocname); if(node->ncbasename == NULL) return NC_ENOMEM; nullfree(node->ncfullname); node->ncfullname = makecdfpathstring(node,nccomm->cdf.separator); if(node->ncfullname == NULL) return NC_ENOMEM; if(node->nctype == NC_Atomic) node->externaltype = nctypeconvert(nccomm,node->etype); return NC_NOERR; }
/* Compute the set of prefetched data. Notes: 1. All prefetches are whole variable fetches. 2. If the data set is unconstrainable, we will prefetch the whole thing */ NCerror prefetchdata(NCDAPCOMMON* nccomm) { int i; NCFLAGS flags; NCerror ncstat = NC_NOERR; NClist* allvars = nccomm->cdf.ddsroot->tree->varnodes; DCEconstraint* urlconstraint = nccomm->oc.dapconstraint; NClist* vars = nclistnew(); NCcachenode* cache = NULL; DCEconstraint* newconstraint = NULL; if(FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE)) { /* If we cannot constrain and caching is enabled, then pull in everything */ if(FLAGSET(nccomm->controls,NCF_CACHE)) { for(i=0;i<nclistlength(allvars);i++) { nclistpush(vars,nclistget(allvars,i)); } } else { /* do no prefetching */ nccomm->cdf.cache->prefetch = NULL; goto done; } } else { /* pull in those variables previously marked as prefetchable */ for(i=0;i<nclistlength(allvars);i++) { CDFnode* var = (CDFnode*)nclistget(allvars,i); /* Most of the important testing was already done */ if(!var->basenode->prefetchable) continue; /* Do not attempt to prefetch any variables in the nc_open url's projection list */ if(nclistcontains(nccomm->cdf.projectedvars,(void*)var)) continue; /* Should be prefetchable */ nclistpush(vars,(void*)var); if(SHOWFETCH) { nclog(NCLOGDBG,"prefetch: %s",var->ncfullname); } } } /* If there are no vars, then do nothing */ if(nclistlength(vars) == 0) { nccomm->cdf.cache->prefetch = NULL; goto done; } /* Create a single constraint consisting of the projections for the variables; each projection is whole variable. The selections are passed on as is. Conditionally, The exception is if we are prefetching everything. */ newconstraint = (DCEconstraint*)dcecreate(CES_CONSTRAINT); newconstraint->projections = nclistnew(); newconstraint->selections = dceclonelist(urlconstraint->selections); for(i=0;i<nclistlength(vars);i++) { CDFnode* var = (CDFnode*)nclistget(vars,i); DCEprojection* varprojection; /* convert var to a projection */ ncstat = dapvar2projection(var,&varprojection); if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;} nclistpush(newconstraint->projections,(void*)varprojection); } if(SHOWFETCH) { char* s = dumpprojections(newconstraint->projections); LOG1(NCLOGNOTE,"prefetch.final: %s",s); nullfree(s); } flags = NCF_PREFETCH; #ifndef GRADS_PREFETCH if(nclistlength(allvars) == nclistlength(vars)) flags |= NCF_PREFETCH_ALL; #endif ncstat = buildcachenode(nccomm,newconstraint,vars,&cache,flags); newconstraint = NULL; /* buildcachenodetakes control of newconstraint */ if(ncstat != OC_NOERR) goto done; else if(cache == NULL) goto done; else cache->wholevariable = 1; /* All prefetches are whole variable */ /* Make cache node be the prefetch node */ nccomm->cdf.cache->prefetch = cache; if(SHOWFETCH) { LOG0(NCLOGNOTE,"prefetch.complete"); } if(SHOWFETCH) { char* s = NULL; /* Log the set of prefetch variables */ NCbytes* buf = ncbytesnew(); ncbytescat(buf,"prefetch.vars: "); for(i=0;i<nclistlength(vars);i++) { CDFnode* var = (CDFnode*)nclistget(vars,i); ncbytescat(buf," "); s = makecdfpathstring(var,"."); ncbytescat(buf,s); nullfree(s); } ncbytescat(buf,"\n"); nclog(NCLOGNOTE,"%s",ncbytescontents(buf)); ncbytesfree(buf); } done: nclistfree(vars); dcefree((DCEnode*)newconstraint); if(ncstat && cache != NULL) freenccachenode(nccomm,cache); return THROW(ncstat); }
/* Return 1 if we can reuse cached data to address the current get_vara request; return 0 otherwise. Target is in the constrained tree space. Currently, if the target matches a cache that is not a whole variable, then match is false. */ int iscached(NCDAPCOMMON* nccomm, CDFnode* target, NCcachenode** cachenodep) { int i,j,found,index; NCcache* cache; NCcachenode* cachenode; found = 0; if(target == NULL) goto done; /* Match the target variable against the prefetch, if any */ /* Note that prefetches are always whole variable */ cache = nccomm->cdf.cache; cachenode = cache->prefetch; if(cachenode!= NULL) { for(found=0,i=0;i<nclistlength(cachenode->vars);i++) { CDFnode* var = (CDFnode*)nclistget(cachenode->vars,i); if(var == target) { if(cachenodep) *cachenodep = cachenode; found=1; goto done; } } } /*search other cache nodes starting at latest first */ index = 0; for(i=nclistlength(cache->nodes)-1;i>=0;i--) { cachenode = (NCcachenode*)nclistget(cache->nodes,i); /* We currently do not try to match constraints; If the cachenode is constrained by more than simple wholevariable projections, then skip it. */ if(!cachenode->wholevariable) continue; for(found=0,j=0;j<nclistlength(cachenode->vars);j++) { CDFnode* var = (CDFnode*)nclistget(cachenode->vars,j); if(var == target) {found=1;index=i;break;} } if(found) break; } if(found) { ASSERT((cachenode != NULL)); if(nclistlength(cache->nodes) > 1) { /* Manage the cache nodes as LRU */ nclistremove(cache->nodes,index); nclistpush(cache->nodes,(void*)cachenode); } if(cachenodep) *cachenodep = cachenode; } done: #ifdef DEBUG fprintf(stderr,"iscached: search: %s\n",makecdfpathstring(target,".")); if(found) fprintf(stderr,"iscached: found: %s\n",dumpcachenode(cachenode)); else fprintf(stderr,"iscached: notfound\n"); #endif return found; }
NCerror computevarnodes(NCDAPCOMMON* nccomm, NClist* allnodes, NClist* varnodes) { unsigned int i,len; NClist* allvarnodes = nclistnew(); for(i=0; i<nclistlength(allnodes); i++) { CDFnode* node = (CDFnode*)nclistget(allnodes,i); #if 0 /* If this node has a bad name, repair it */ if(dap_badname(node->ocname)) { char* newname = dap_repairname(node->ocname); nullfree(node->ocname); node->ocname = newname; } #endif if(node->nctype == NC_Atomic) nclistpush(allvarnodes,(void*)node); } /* Further process the variable nodes to get the final set */ /* Use toplevel vars first */ len = nclistlength(allvarnodes); for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; if(daptoplevel(node)) { nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } } /*... then grid arrays and maps. but exclude the coordinate variables if we are trying to exactly mimic nc-dap */ for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; if(dapgridarray(node)) { nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } else if(dapgridmap(node)) { if(!FLAGSET(nccomm->controls,NCF_NCDAP)) nclistpush(varnodes,(void*)node); nclistset(allvarnodes,i,(void*)NULL); } } /*... then all others */ for(i=0; i<len; i++) { CDFnode* node = (CDFnode*)nclistget(allvarnodes,i); if(node == NULL) continue; nclistpush(varnodes,(void*)node); } nclistfree(allvarnodes); #ifdef DEBUG2 for(i=0; i<nclistlength(varnodes); i++) { CDFnode* node = (CDFnode*)nclistget(varnodes,i); if(node == NULL) continue; fprintf(stderr,"computevarnodes: var: %s\n",makecdfpathstring(node,".")); } #endif return NC_NOERR; }
/* Figure out the names for variables. */ NCerror computecdfvarnames(NCDAPCOMMON* nccomm, CDFnode* root, NClist* varnodes) { unsigned int i,j,d; /* clear all elided marks; except for dataset and grids */ for(i=0; i<nclistlength(root->tree->nodes); i++) { CDFnode* node = (CDFnode*)nclistget(root->tree->nodes,i); node->elided = 0; if(node->nctype == NC_Grid || node->nctype == NC_Dataset) node->elided = 1; } /* ensure all variables have an initial full name defined */ for(i=0; i<nclistlength(varnodes); i++) { CDFnode* var = (CDFnode*)nclistget(varnodes,i); nullfree(var->ncfullname); var->ncfullname = makecdfpathstring(var,nccomm->cdf.separator); #ifdef DEBUG2 fprintf(stderr,"var names: %s %s %s\n", var->ocname,var->ncbasename,var->ncfullname); #endif } /* unify all variables with same fullname and dimensions basevar fields says: "for duplicate grid variables"; when does this happen? */ if(FLAGSET(nccomm->controls,NCF_NC3)) { for(i=0; i<nclistlength(varnodes); i++) { int match; CDFnode* var = (CDFnode*)nclistget(varnodes,i); for(j=0; j<i; j++) { CDFnode* testnode = (CDFnode*)nclistget(varnodes,j); match = 1; if(testnode->array.basevar != NULL) continue; /* already processed */ if(strcmp(var->ncfullname,testnode->ncfullname) != 0) match = 0; else if(nclistlength(testnode->array.dimsetall) != nclistlength(var->array.dimsetall)) match = 0; else for(d=0; d<nclistlength(testnode->array.dimsetall); d++) { CDFnode* vdim = (CDFnode*)nclistget(var->array.dimsetall,d); CDFnode* tdim = (CDFnode*)nclistget(testnode->array.dimsetall,d); if(vdim->dim.declsize != tdim->dim.declsize) { match = 0; break; } } if(match) { testnode->array.basevar = var; fprintf(stderr,"basevar invoked: %s\n",var->ncfullname); } } } } /* Finally, verify unique names */ for(i=0; i<nclistlength(varnodes); i++) { CDFnode* var1 = (CDFnode*)nclistget(varnodes,i); if(var1->array.basevar != NULL) continue; for(j=0; j<i; j++) { CDFnode* var2 = (CDFnode*)nclistget(varnodes,j); if(var2->array.basevar != NULL) continue; if(strcmp(var1->ncfullname,var2->ncfullname)==0) { PANIC1("duplicate var names: %s",var1->ncfullname); } } } return NC_NOERR; }