Exemple #1
0
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;
}
Exemple #3
0
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);
}