/* Delete the entry. return value = 1 => found and deleted; 0 => param not found */ static int nc_urlparamdelete(NClist* params, const char* clientparam) { int i,found = 0; if(params == NULL || clientparam == NULL) return 0; for(i=0;i<nclistlength(params);i+=2) { char* name = (char*)nclistget(params,i); if(strcmp(clientparam,name)==0) {found=1; break;} } if(found) { nclistremove(params,i+1); /* remove value */ nclistremove(params,i); /* remove name */ } return found; }
/* 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; }
/* Suppress variables not in usable sequences*/ NCerror suppressunusablevars3(NCDAPCOMMON* dapcomm) { int i,j; int found = 1; NClist* path = nclistnew(); while(found) { found = 0; /* Walk backwards to aid removal semantics */ for(i=nclistlength(dapcomm->cdf.ddsroot->tree->varnodes)-1;i>=0;i--) { CDFnode* var = (CDFnode*)nclistget(dapcomm->cdf.ddsroot->tree->varnodes,i); /* See if this var is under an unusable sequence */ nclistclear(path); collectnodepath3(var,path,WITHOUTDATASET); for(j=0;j<nclistlength(path);j++) { CDFnode* node = (CDFnode*)nclistget(path,j); if(node->nctype == NC_Sequence && !node->usesequence) { #ifdef DEBUG fprintf(stderr,"suppressing var in unusable sequence: %s.%s\n",node->ncfullname,var->ncbasename); #endif found = 1; break; } } if(found) break; } if(found) nclistremove(dapcomm->cdf.ddsroot->tree->varnodes,i); } nclistfree(path); return NC_NOERR; }
/* Given two projection lists, merge src into dst taking overlapping projections into acct. Assume that name qualification has occured. Dst will be modified. */ NCerror mergeprojections3(NClist* dst, NClist* src) { int i; NClist* cat = nclistnew(); NCerror ncstat = NC_NOERR; #ifdef DEBUG fprintf(stderr,"mergeprojection: dst = %s\n",dumpprojections(dst)); fprintf(stderr,"mergeprojection: src = %s\n",dumpprojections(src)); #endif ASSERT(dst != NULL); /* get dst concat clone(src) */ nclistsetalloc(cat,nclistlength(dst)+nclistlength(src)); for(i=0;i<nclistlength(dst);i++) { DCEprojection* p = (DCEprojection*)nclistget(dst,i); nclistpush(cat,(ncelem)p); } if(src != NULL) for(i=0;i<nclistlength(src);i++) { DCEprojection* p = (DCEprojection*)nclistget(src,i); nclistpush(cat,(ncelem)dceclone((DCEnode*)p)); } nclistclear(dst); /* Repeatedly pull elements from the concat, merge with all duplicates, and stick into the dst */ while(nclistlength(cat) > 0) { DCEprojection* target = (DCEprojection*)nclistremove(cat,0); if(target == NULL) continue; if(target->discrim != CES_VAR) continue; for(i=0;i<nclistlength(cat);i++) { DCEprojection* p2 = (DCEprojection*)nclistget(cat,i); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; if(target->var->cdfleaf != p2->var->cdfleaf) continue; /* This entry matches our current target; merge */ ncstat = mergeprojection31(target,p2); /* null out this merged entry and release it */ nclistset(cat,i,(ncelem)NULL); dcefree((DCEnode*)p2); } /* Capture the clone */ nclistpush(dst,(ncelem)target); } nclistfree(cat); return ncstat; }
int dcemergeprojectionlists(NClist* dst, NClist* src) { int i; NClist* cat = nclistnew(); int ncstat = NC_NOERR; #ifdef DEBUG fprintf(stderr,"dapmergeprojection: dst = %s\n",dcetostring((DCEnode*)dst)); fprintf(stderr,"dapmergeprojection: src = %s\n",dcetostring((DCEnode*)src)); #endif /* get dst concat clone(src) */ nclistsetalloc(cat,nclistlength(dst)+nclistlength(src)); for(i=0;i<nclistlength(dst);i++) { DCEprojection* p = (DCEprojection*)nclistget(dst,i); nclistpush(cat,(void*)p); } for(i=0;i<nclistlength(src);i++) { DCEprojection* p = (DCEprojection*)nclistget(src,i); nclistpush(cat,(void*)dceclone((DCEnode*)p)); } nclistclear(dst); /* Repeatedly pull elements from the concat, merge with all duplicates, and stick into the dst */ while(nclistlength(cat) > 0) { DCEprojection* target = (DCEprojection*)nclistremove(cat,0); if(target == NULL) continue; if(target->discrim != CES_VAR) continue; for(i=0;i<nclistlength(cat);i++) { DCEprojection* p2 = (DCEprojection*)nclistget(cat,i); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; if(dcesamepath(target->var->segments, p2->var->segments)!=0) continue; /* This entry matches our current target; merge */ ncstat = dcemergeprojections(target,p2); /* null out this merged entry and release it */ nclistset(cat,i,(void*)NULL); dcefree((DCEnode*)p2); } /* Capture the clone */ nclistpush(dst,(void*)target); } nclistfree(cat); return ncstat; }
/* return TRUE if found, false otherwise*/ int nchashremove(NChashmap* hm, nchashid hash) { int i,offset,len; NClist* seq; void** list; offset = (hash % hm->alloc); seq = hm->table[offset]; if(seq == NULL) return TRUE; len = nclistlength(seq); list = nclistcontents(seq); for(i=0;i<len;i+=2,list+=2) { if(hash==(nchashid)(*list)) { nclistremove(seq,i+1); nclistremove(seq,i); hm->size--; if(nclistlength(seq) == 0) {nclistfree(seq); hm->table[offset] = NULL;} return TRUE; } } return FALSE; }
int nclistdeleteall(NClist* l, void* elem) { int i; /* do not make unsigned */ unsigned int len,found; found = 0; len = nclistlength(l); for(i=len-1;i>=0;i--) { void* test = nclistget(l,i); if(test==elem) { nclistremove(l,i); found=1; } } return found; }
/** * @internal * * Construct the provenance information for a newly opened file * Using the specified _NCProperties value. If NULL, then * initialize using dfalt. * * @param file Pointer to file object. * @param propstring The contents of _NCProperties * @param dfalt * * @return ::NC_NOERR No error. * @return ::NC_ENOMEM * @return ::NC_EINVAL * @author Dennis Heimbigner */ int NC4_get_provenance(NC_FILE_INFO_T* file, const char* propstring, const struct NCPROPINFO* dfalt) { int ncstat = NC_NOERR; struct NCPROVENANCE* provenance; char *name = NULL; char *value = NULL; int v = 0; int superblock = -1; LOG((3, "%s: ncid 0x%x propstring %s", __func__, file->root_grp->hdr.id, propstring)); assert(file->provenance == NULL); if((file->provenance = calloc(1,sizeof(struct NCPROVENANCE))) == NULL) {ncstat = NC_ENOMEM; goto done;} provenance = file->provenance; if((provenance->propattr.properties = nclistnew()) == NULL) {ncstat = NC_ENOMEM; goto done;} /* Set the superblock */ if((ncstat = NC4_hdf5get_superblock(file,&superblock))) goto done; provenance->superblockversion = superblock; if(propstring == NULL) { /* Use dfalt */ if((ncstat=propinfo_default(&provenance->propattr,dfalt))) goto done; } else { NClist* list = provenance->propattr.properties; if((ncstat=properties_parse(propstring,list))) goto done; /* Check the version and remove from properties list*/ if(nclistlength(list) < 2) {ncstat = NC_EINVAL; goto done;} /* bad _NCProperties attribute */ /* Extract the purported version=... */ name = nclistremove(list,0); value = nclistremove(list,0); if(strcmp(name,NCPVERSION) == 0) { if(sscanf(value,"%d",&v) != 1) {ncstat = NC_EINVAL; goto done;} /* illegal version */ if(v <= 0 || v > NCPROPS_VERSION) {ncstat = NC_EINVAL; goto done;} /* unknown version */ provenance->propattr.version = v; } else {ncstat = NC_EINVAL; goto done;} /* bad _NCProperties attribute */ /* Now, rebuild from version 1 to version 2 if necessary */ if(provenance->propattr.version == 1) { int i; for(i=0;i<nclistlength(list);i+=2) { char* newname = NULL; name = nclistget(list,i); if(name == NULL) continue; /* ignore */ if(strcmp(name,NCPNCLIB1) == 0) newname = NCPNCLIB2; /* change name */ else if(strcmp(name,NCPHDF5LIB1) == 0) newname = NCPHDF5LIB2; else continue; /* ignore */ /* Do any rename */ nclistset(list,i,strdup(newname)); if(name) {free(name); name = NULL;} } } } done: if(name != NULL) free(name); if(value != NULL) free(value); return ncstat; }
NCerror fixprojections(NClist* list) { int i,j,k; NCerror ncstat = NC_NOERR; NClist* tmp = nclistnew(); /* misc. uses */ #ifdef DEBUG fprintf(stderr,"fixprojection: list = %s\n",dumpprojections(list)); #endif if(nclistlength(list) == 0) goto done; /* Step 1: remove duplicates and complain about slice mismatches */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p1 == p2) continue; if(p2->discrim != CES_VAR) continue; if(p1->var->annotation != p2->var->annotation) continue; /* check for slice mismatches */ if(!slicematch(p1->var->segments,p2->var->segments)) { /* complain */ nclog(NCLOGWARN,"Malformed projection: same variable with different slicing"); } /* remove p32 */ nclistset(list,j,(ncelem)NULL); dcefree((DCEnode*)p2); } } /* Step 2: remove containers when a field is also present */ for(i=0;i<nclistlength(list);i++) { DCEprojection* p1 = (DCEprojection*)nclistget(list,i); if(p1 == NULL) continue; if(p1->discrim != CES_VAR) continue; /* dont try to unify functions */ if(!iscontainer((CDFnode*)p1->var->annotation)) continue; for(j=i;j<nclistlength(list);j++) { DCEprojection* p2 = (DCEprojection*)nclistget(list,j); if(p2 == NULL) continue; if(p2->discrim != CES_VAR) continue; nclistclear(tmp); collectnodepath3((CDFnode*)p2->var->annotation,tmp,WITHDATASET); for(k=0;k<nclistlength(tmp);k++) { void* candidate = (void*)nclistget(tmp,k); if(candidate == p1->var->annotation) { nclistset(list,i,(ncelem)NULL); dcefree((DCEnode*)p1); goto next; } } } next: continue; } /* Step 3: expand all containers recursively down to the leaf nodes */ for(;;) { nclistclear(tmp); for(i=0;i<nclistlength(list);i++) { DCEprojection* target = (DCEprojection*)nclistget(list,i); CDFnode* leaf; if(target == NULL) continue; if(target->discrim != CES_VAR) continue; /* dont try to unify functions */ leaf = (CDFnode*)target->var->annotation; ASSERT(leaf != NULL); if(iscontainer(leaf)) {/* capture container */ if(!nclistcontains(tmp,(ncelem)target)) nclistpush(tmp,(ncelem)target); nclistset(list,i,(ncelem)NULL); } } if(nclistlength(tmp) == 0) break; /*done*/ /* Now explode the containers */ for(i=0;i<nclistlength(tmp);i++) { DCEprojection* container = (DCEprojection*)nclistget(tmp,i); CDFnode* leaf = (CDFnode*)container->var->annotation; for(j=0;i<nclistlength(leaf->subnodes);j++) { CDFnode* field = (CDFnode*)nclistget(leaf->subnodes,j); /* Convert field node to a proper constraint */ DCEprojection* proj = projectify(field,container); nclistpush(list,(ncelem)proj); } /* reclaim the container */ dcefree((DCEnode*)container); } } /*for(;;)*/ /* remove all NULL elements */ for(i=nclistlength(list)-1;i>=0;i--) { DCEprojection* target = (DCEprojection*)nclistget(list,i); if(target == NULL) nclistremove(list,i); } done: #ifdef DEBUG fprintf(stderr,"fixprojection: exploded = %s\n",dumpprojections(list)); #endif nclistfree(tmp); return 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 if we can unify sets of nodes to be projected into larger units. */ static NClist* unifyprojectionnodes3(NClist* varlist) { int i; NClist* nodeset = nclistnew(); NClist* containerset = nclistnew(); NClist* containernodes = nclistnew(); nclistsetalloc(nodeset,nclistlength(varlist)); nclistsetalloc(containerset,nclistlength(varlist)); /* Duplicate the varlist so we can modify it; simultaneously collect unique container set. */ for(i=0;i<nclistlength(varlist);i++) { CDFnode* var = (CDFnode*)nclistget(varlist,i); CDFnode* container = var->container; nclistpush(nodeset,(ncelem)var); switch (container->nctype) { case NC_Sequence: case NC_Structure: case NC_Grid: case NC_Dataset: /* add (uniquely) to container set */ if(!nclistcontains(containerset,(ncelem)container)) nclistpush(containerset,(ncelem)container); break; default: break; } } /* Now, try to find containers whose subnodes are all in the varlist; repeat until no more changes */ for(;;) { int changed = 0; for(i=0;i<nclistlength(containerset);i++) { int j, allfound; CDFnode* container = (CDFnode*)nclistget(containerset,i); if(container == NULL) continue; nclistclear(containernodes); for(allfound=1,j=0;j<nclistlength(container->subnodes);j++) { CDFnode* subnode = (CDFnode*)nclistget(container->subnodes,j); if(!nclistcontains(varlist,(ncelem)subnode)) {allfound=0;break;} nclistpush(containernodes,(ncelem)subnode); } if(allfound) { nclistpush(nodeset,(ncelem)container); nclistset(containerset,i,(ncelem)NULL); /* remove */ for(j=nclistlength(nodeset)-1;j>=0;j--) { /* walk backwards */ CDFnode* testnode = (CDFnode*)nclistget(nodeset,j); if(nclistcontains(containernodes,(ncelem)testnode)) nclistremove(nodeset,j);/* remove */ } changed = 1; } } if(!changed) break; /* apparently we have reached a stable situation */ } /* If there is only the dataset left as a projection, then remove it */ if(nclistlength(nodeset) == 1) { CDFnode* thenode = (CDFnode*)nclistget(nodeset,0); if(thenode->nctype == NC_Dataset) nclistclear(nodeset); } nclistfree(containerset); nclistfree(containernodes); return nodeset; }
void restrictprojection34(NClist* varlist, NClist* projections) { int i,j,len; #ifdef DEBUG fprintf(stderr,"restriction.before=|%s|\n", dumpprojections(projections)); #endif if(nclistlength(varlist) == 0) goto done; /* nothing to add or remove */ /* If the projection list is empty, then add a projection for every variable in varlist */ if(nclistlength(projections) == 0) { NClist* path = nclistnew(); NClist* nodeset = NULL; /* Attempt to unify the vars into larger units (like a complete grid) */ nodeset = unifyprojectionnodes3(varlist); for(i=0;i<nclistlength(nodeset);i++) { CDFnode* var = (CDFnode*)nclistget(nodeset,i); #ifdef DEBUG fprintf(stderr,"restriction.candidate=|%s|\n",var->ncfullname); #endif DCEprojection* newp = (DCEprojection*)dcecreate(CES_PROJECT); newp->discrim = CES_VAR; newp->var = (DCEvar*)dcecreate(CES_VAR); newp->var->cdfleaf = var; nclistclear(path); collectnodepath3(var,path,!WITHDATASET); newp->var->segments = nclistnew(); for(j=0;j<nclistlength(path);j++) { CDFnode* node = (CDFnode*)nclistget(path,j); DCEsegment* newseg = (DCEsegment*)dcecreate(CES_SEGMENT); newseg->name = nulldup(node->name); makewholesegment3(newseg,node);/*treat as simple projections*/ newseg->cdfnode = node; nclistpush(newp->var->segments,(ncelem)newseg); } nclistpush(projections,(ncelem)newp); } nclistfree(path); nclistfree(nodeset); } else { /* Otherwise, walk all the projections and see if they intersect any of the variables. If not, then remove from the projection list. */ len = nclistlength(projections); for(i=len-1;i>=0;i--) {/* Walk backward to facilitate removal*/ int intersect = 0; DCEprojection* proj = (DCEprojection*)nclistget(projections,i); if(proj->discrim != CES_VAR) continue; for(j=0;j<nclistlength(varlist);j++) { CDFnode* var = (CDFnode*)nclistget(varlist,j); /* Note that intersection could go either way */ if(treecontains3(var,proj->var->cdfleaf) || treecontains3(proj->var->cdfleaf,var)) {intersect = 1; break;} } if(!intersect) { /* suppress this projection */ DCEprojection* p = (DCEprojection*)nclistremove(projections,i); dcefree((DCEnode*)p); } } /* Now looks for containment between projections and only keep the more restrictive. Is this algorithm stable against reordering?. */ for(;;) { int removed = 0; for(i=0;i<nclistlength(projections);i++) { DCEprojection* pi = (DCEprojection*)nclistget(projections,i); if(pi->discrim != CES_VAR) continue; for(j=0;j<i;j++) { DCEprojection* pj = (DCEprojection*)nclistget(projections,j); if(pj->discrim != CES_VAR) continue; if(treecontains3(pi->var->cdfleaf,pj->var->cdfleaf)) { DCEprojection* p = (DCEprojection*)nclistremove(projections,j); dcefree((DCEnode*)p); removed = 1; break; } else if(treecontains3(pj->var->cdfleaf,pi->var->cdfleaf)) { DCEprojection* p = (DCEprojection*)nclistremove(projections,i); dcefree((DCEnode*)p); removed = 1; break; } } } if(!removed) break; } } done: #ifdef DEBUG fprintf(stderr,"restriction.after=|%s|\n", dumpprojections(projections)); #endif return; }