char* dumpcachenode(NCcachenode* node) { char* result = NULL; char tmp[8192]; int i; NCbytes* buf; if(node == NULL) return strdup("cachenode{null}"); buf = ncbytesnew(); snprintf(tmp,sizeof(tmp),"cachenode%s(%lx){size=%lu; constraint=%s; vars=", node->prefetch?"*":"", (unsigned long)node, (unsigned long)node->xdrsize, buildconstraintstring3(node->constraint)); 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,makesimplepathstring3(var)); } ncbytescat(buf,"}"); result = ncbytesdup(buf); ncbytesfree(buf); return result; }
/* 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, 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,(ncelem)cachenode); } if(cachenodep) *cachenodep = cachenode; } done: #ifdef DEBUG fprintf(stderr,"iscached: search: %s\n",makesimplepathstring3(target)); if(found) fprintf(stderr,"iscached: found: %s\n",dumpcachenode(cachenode)); else fprintf(stderr,"iscached: notfound\n"); #endif return found; }
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); }
/* Compute the set of prefetched data */ NCerror prefetchdata4(NCDRNO* drno) { int i,j; NCerror ncstat = NC_NOERR; NClist* allvars = drno->cdf.varnodes; NCconstraint* constraint = &drno->dap.constraint; NClist* vars = nclistnew(); NCcachenode* cache = NULL; NCconstraint newconstraint; /* If caching is off, and we can do constraints, then don't even do prefetch */ if(!FLAGSET(drno,NCF_CACHE) && !FLAGSET(drno,NCF_UNCONSTRAINABLE)) { drno->cdf.cache.prefetch = NULL; goto done; } for(i=0;i<nclistlength(allvars);i++) { CDFnode* var = (CDFnode*)nclistget(allvars,i); size_t nelems = 1; /* Compute the # of elements in the variable */ for(j=0;j<nclistlength(var->array.dimensions);j++) { CDFnode* dim = (CDFnode*)nclistget(var->array.dimensions,j); nelems *= dim->dim.declsize; } /* If we cannot constrain, then pull in everything */ if(FLAGSET(drno,NCF_UNCONSTRAINABLE) || nelems <= drno->cdf.smallsizelimit) nclistpush(vars,(ncelem)var); } /* If we cannot constrain, then pull in everything */ if(FLAGSET(drno,NCF_UNCONSTRAINABLE)) { newconstraint.projections = NULL; newconstraint.selections= NULL; } else { /* Construct the projections for this set of vars */ /* Construct the projections for this set of vars */ /* Initially, the constraints are same as the merged constraints */ newconstraint.projections = cloneprojections(constraint->projections); restrictprojection3(drno,vars,newconstraint.projections); /* similar for selections */ newconstraint.selections = cloneselections(constraint->selections); } ncstat = buildcachenode3(drno,&newconstraint,vars,&cache,0); if(ncstat) goto done; if(FLAGSET(drno,NCF_SHOWFETCH)) { /* 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," "); ncbytescat(buf,makesimplepathstring3(var)); } ncbytescat(buf,"\n"); oc_log(OCLOGNOTE,ncbytescontents(buf)); ncbytesfree(buf); } done: if(ncstat) { freenccachenode(drno,cache); } return THROW(ncstat); }
/* Compute the set of prefetched data; note that even if caching is off, we will still prefetch the small variables. */ NCerror prefetchdata3(NCDAPCOMMON* nccomm) { int i,j; NCerror ncstat = NC_NOERR; NClist* allvars = nccomm->cdf.varnodes; NCconstraint* constraint = nccomm->oc.dapconstraint; NClist* vars = nclistnew(); NCcachenode* cache = NULL; NCconstraint* newconstraint = NULL; /* Check if we can do constraints */ if(FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE)) { /*cannot constrain*/ /* If we cannot constrain, then pull in everything */ for(i=0;i<nclistlength(allvars);i++) { nclistpush(vars,nclistget(allvars,i)); } } else { /* can do constraints */ /* pull in those variables of sufficiently small size */ for(i=0;i<nclistlength(allvars);i++) { CDFnode* var = (CDFnode*)nclistget(allvars,i); size_t nelems = 1; /* If var is a sequence or under a sequence, then never prefetch */ if(var->nctype == NC_Sequence || dapinsequence(var)) continue; /* Compute the # of elements in the variable */ for(j=0;j<nclistlength(var->array.dimensions);j++) { CDFnode* dim = (CDFnode*)nclistget(var->array.dimensions,j); nelems *= dim->dim.declsize; } if(nelems <= nccomm->cdf.smallsizelimit) nclistpush(vars,(ncelem)var); } } /* If there are no vars, then do nothing */ if(nclistlength(vars) == 0) { nccomm->cdf.cache->prefetch = NULL; goto done; } newconstraint = createncconstraint(); /* Construct the projections for this set of vars */ /* Initially, the constraints are same as the merged constraints */ newconstraint->projections = clonencprojections(constraint->projections); restrictprojection34(vars,newconstraint->projections); /* similar for selections */ newconstraint->selections = clonencselections(constraint->selections); ncstat = buildcachenode34(nccomm,newconstraint,vars,&cache,1); if(ncstat) goto done; cache->wholevariable = 1; /* All prefetches are whole variable */ if(FLAGSET(nccomm->controls,NCF_SHOWFETCH)) { oc_log(OCLOGNOTE,"prefetch."); } #ifdef DEBUG /* 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," "); ncbytescat(buf,makesimplepathstring3(var)); } ncbytescat(buf,"\n"); oc_log(OCLOGNOTE,"%s",ncbytescontents(buf)); ncbytesfree(buf); #endif /* Make cache node be the prefetch node */ nccomm->cdf.cache->prefetch = cache; done: nclistfree(vars); freencconstraint(newconstraint); if(ncstat) freenccachenode(nccomm,cache); return THROW(ncstat); }