Esempio n. 1
0
/* Convert a CDFnode var to a projection; include
   pseudodimensions; always whole variable.
*/
int
dapvar2projection(CDFnode* var, DCEprojection** projectionp)
{
    int i,j;
    int ncstat = NC_NOERR;
    NClist* path = nclistnew();
    NClist* segments;
    DCEprojection* projection = NULL;
    int dimindex;

    /* Collect the nodes needed to construct the projection segment */    
    collectnodepath3(var,path,!WITHDATASET);

    segments = nclistnew();
    dimindex = 0; /* point to next subset of slices */
    nclistsetalloc(segments,nclistlength(path));
    for(i=0;i<nclistlength(path);i++) {
	DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT);
	CDFnode* n = (CDFnode*)nclistget(path,i);
	int localrank;
        NClist* dimset;

	segment->annotation = (void*)n;
        segment->name = nulldup(n->ocname);
        /* We need to assign whole slices to each segment */
	localrank = nclistlength(n->array.dimsetplus);
        segment->rank = localrank;
	dimset = n->array.dimsetplus;
        for(j=0;j<localrank;j++) {
	    DCEslice* slice;
	    CDFnode* dim;
	    slice = &segment->slices[j];
	    dim = (CDFnode*)nclistget(dimset,j);
	    ASSERT(dim->dim.declsize0 > 0);
	    dcemakewholeslice(slice,dim->dim.declsize0);
	}
	segment->slicesdefined = 1;
	segment->slicesdeclized = 1;
	dimindex += localrank;
	nclistpush(segments,(ncelem)segment);
    }
    
    projection = (DCEprojection*)dcecreate(CES_PROJECT);
    projection->discrim = CES_VAR;
    projection->var = (DCEvar*)dcecreate(CES_VAR);
    projection->var->annotation = (void*)var;
    projection->var->segments = segments;

#ifdef DEBUG1
fprintf(stderr,"dapvar2projection: projection=%s\n",
        dumpprojection(projection));
#endif

    nclistfree(path);
    if(ncstat) dcefree((DCEnode*)projection);
    else if(projectionp) *projectionp = projection;
    return ncstat;
}    
Esempio n. 2
0
static DCEprojection*
projectify(CDFnode* field, DCEprojection* container)
{
    DCEprojection* proj  = (DCEprojection*)dcecreate(CES_PROJECT);
    DCEvar* var  = (DCEvar*)dcecreate(CES_VAR);
    DCEsegment* seg  = (DCEsegment*)dcecreate(CES_SEGMENT);
    proj->discrim = CES_VAR;
    proj->var = var;
    var->annotation = (void*)field;
    /* Dup the segment list */
    var->segments = dceclonelist(container->var->segments);
    seg->rank = 0;
    nclistpush(var->segments,(ncelem)seg);
    return proj;
}
Esempio n. 3
0
Object
range(DCEparsestate* state, Object sfirst, Object sstride, Object slast)
{
    DCEslice* slice = (DCEslice*)dcecreate(CES_SLICE);
    unsigned long first=0,stride=0,last=0;

    /* Note: that incoming arguments are strings; we must convert to size_t;
       but we do know they are legal integers or NULL */
    sscanf((char*)sfirst,"%lu",&first); /* always defined */
    if(slast != NULL)
        sscanf((char*)slast,"%lu",&last);
    else
	last = first;
    if(sstride != NULL)
        sscanf((char*)sstride,"%lu",&stride);
    else
	stride = 1; /* default */

    if(stride == 0)
    	dceerror(state,"Illegal index for range stride");
    if(last < first)
	dceerror(state,"Illegal index for range last index");
    slice->first  = first;
    slice->stride = (stride == 0 ? 1 : stride);
    slice->last   = last;
    slice->length  = (slice->last - slice->first) + 1;
    slice->count  = slice->length / slice->stride;
#ifdef DEBUG
fprintf(stderr,"	ce.slice: %s\n",
	dumpslice(slice));
#endif
    return slice;
}
Esempio n. 4
0
Object
var(DCEparsestate* state, Object indexpath)
{
    DCEvar* v = (DCEvar*)dcecreate(CES_VAR);
    v->segments = (NClist*)indexpath;
    return v;
}
Esempio n. 5
0
static void
completesegments3(NClist* fullpath, NClist* segments)
{
    int i,delta;
    /* add path nodes to segments to create full path */
    delta = (nclistlength(fullpath) - nclistlength(segments));
    ASSERT((delta >= 0));
    for(i=0;i<delta;i++) {
        DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
        seg->name = nulldup(node->ocname);
        seg->annotation = (void*)node;
	seg->rank = nclistlength(node->array.dimset0);
#ifdef IGNORE
	for(j=0;j<seg->rank;j++) {
            CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j);
            dcemakewholeslice(seg->slices+j,dim->dim.declsize);
        }
#endif
        nclistinsert(segments,i,(ncelem)seg);
    }
    /* Now modify the segments to point to the appropriate node
       and fill in the slices.
    */
    for(i=delta;i<nclistlength(segments);i++) {
        DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
	seg->annotation = (void*)node;
#ifdef IGNORE
        if(!seg->slicesdefined) {
	    makewholesegment3(seg,node);
	}
#endif
    }
}
Esempio n. 6
0
Object
constant(DCEparsestate* state, Object val, int tag)
{
    DCEconstant* con = (DCEconstant*)dcecreate(CES_CONST);
    char* text = (char*)val;
    char* endpoint = NULL;
    switch (tag) {
    case SCAN_STRINGCONST:
	con->discrim = CES_STR;
	con->text = nulldup(text);
	break;
    case SCAN_NUMBERCONST:
	con->intvalue = strtoll(text,&endpoint,10);
	if(*text != '\0' && *endpoint == '\0') {
	    con->discrim = CES_INT;
	} else {
	    con->floatvalue = strtod(text,&endpoint);
	    if(*text != '\0' && *endpoint == '\0')
	        con->discrim = CES_FLOAT;
	    else abort();
	}
	break;
    default: abort(); break;
    }
    return con;
}
Esempio n. 7
0
Object
function(DCEparsestate* state, Object fcnname, Object args)
{
    DCEfcn* fcn = (DCEfcn*)dcecreate(CES_FCN);
    fcn->name = nulldup((char*)fcnname);
    fcn->args = args;
    return fcn;
}
Esempio n. 8
0
Object
segmentlist(DCEparsestate* state, Object var0, Object decl)
{
    /* watch out: this is non-standard */
    NClist* list;
    DCEvar* v = (DCEvar*)var0;
    if(v==NULL) v = (DCEvar*)dcecreate(CES_VAR);
    list = v->segments;
    if(list == NULL) list = nclistnew();
    nclistpush(list,(void*)decl);
    v->segments = list;
    return v;
}
Esempio n. 9
0
Object
value(DCEparsestate* state, Object val)
{
    DCEvalue* ncvalue = (DCEvalue*)dcecreate(CES_VALUE);
    CEsort tag = *(CEsort*)val;
    switch (tag) {
    case CES_VAR: ncvalue->var = (DCEvar*)val; break;
    case CES_FCN: ncvalue->fcn = (DCEfcn*)val; break;
    case CES_CONST: ncvalue->constant = (DCEconstant*)val; break;
    default: abort(); break;
    }
    ncvalue->discrim = tag;
    return ncvalue;
}
Esempio n. 10
0
Object
sel_clause(DCEparsestate* state, int selcase,
	   Object lhs, Object relop0, Object values)
{
    DCEselection* sel = (DCEselection*)dcecreate(CES_SELECT);
    sel->operator = (CEsort)relop0;
    sel->lhs = (DCEvalue*)lhs;
    if(selcase == 2) {/*singleton value*/
	sel->rhs = nclistnew();
	nclistpush(sel->rhs,(void*)values);
    } else
        sel->rhs = (NClist*)values;
    return sel;
}
Esempio n. 11
0
Object
indexer(DCEparsestate* state, Object name, Object indices)
{
    int i;
    NClist* list = (NClist*)indices;
    DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
    seg->name = strdup((char*)name);
    for(i=0;i<nclistlength(list);i++) {
	DCEslice* slice = (DCEslice*)nclistget(list,i);
        seg->slices[i] = *slice;
	free(slice);
    }
    nclistfree(indices);
    return seg;
}
Esempio n. 12
0
Object
projection(DCEparsestate* state, Object varorfcn)
{
    DCEprojection* p = (DCEprojection*)dcecreate(CES_PROJECT);
    CEsort tag = *(CEsort*)varorfcn;
    if(tag == CES_FCN)
	p->fcn = varorfcn;
    else
	p->var = varorfcn;
    p->discrim = tag;
#ifdef DEBUG
fprintf(stderr,"	ce.projection: %s\n",
	dcetostring((DCEnode*)p));
#endif
    return p;
}
Esempio n. 13
0
Object
array_indices(DCEparsestate* state, Object list0, Object indexno)
{
    DCEslice* slice;
    long long start = -1;
    NClist* list = (NClist*)list0;
    if(list == NULL) list = nclistnew();
    sscanf((char*)indexno,"%lld",&start);
    if(start < 0) {
    	dceerror(state,"Illegal array index");
	start = 1;
    }
    slice = (DCEslice*)dcecreate(CES_SLICE);
    slice->first = start;
    slice->stride = 1;
    slice->length = 1;
    slice->last = start;
    slice->count = 1;
    nclistpush(list,(void*)slice);
    return list;
}
Esempio n. 14
0
Object
segment(DCEparsestate* state, Object name, Object slices0)
{
    int i;
    DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT);
    NClist* slices = (NClist*)slices0;
    segment->name = strdup((char*)name);
    if(slices != NULL && nclistlength(slices) > 0) {
        segment->slicesdefined = 1; /* but not declsizes */
	for(i=0;i<nclistlength(slices);i++) {
	    DCEslice* slice = (DCEslice*)nclistget(slices,i);
	    segment->slices[i] = *slice;
	    free(slice);
	}
	nclistfree(slices);
    } else
        segment->slicesdefined = 0;
#ifdef DEBUG
fprintf(stderr,"	ce.segment: %s\n",
	dumpsegment(segment));
#endif
    return segment;
}
Esempio n. 15
0
static void
completesegments(NClist* fullpath, NClist* segments)
{
    int i,delta;
    /* add path nodes to segments to create full path */
    delta = (nclistlength(fullpath) - nclistlength(segments));
    ASSERT((delta >= 0));
    for(i=0;i<delta;i++) {
        DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
        seg->name = nulldup(node->ocname);
        seg->annotation = (void*)node;
	seg->rank = nclistlength(node->array.dimset0);
        nclistinsert(segments,i,(void*)seg);
    }
    /* Now modify the segments to point to the appropriate node
       and fill in the slices.
    */
    for(i=delta;i<nclistlength(segments);i++) {
        DCEsegment* seg = (DCEsegment*)nclistget(segments,i);
        CDFnode* node = (CDFnode*)nclistget(fullpath,i);
	seg->annotation = (void*)node;
    }
}
Esempio n. 16
0
/* 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);
}
Esempio n. 17
0
/* Compute the set of prefetched data.
   Notes:
   1. Even if caching is off, we will
       still prefetch the small variables.
   2. All prefetches are whole variable fetches.
   3. If the data set is unconstrainable, we
      will prefetch the whole thing
*/
NCerror
prefetchdata3(NCDAPCOMMON* nccomm)
{
    int i,j;
    NCerror ncstat = NC_NOERR;
    NClist* allvars = nccomm->cdf.varnodes;
    DCEconstraint* urlconstraint = nccomm->oc.dapconstraint;
    NClist* vars = nclistnew();
    NCcachenode* cache = NULL;
    DCEconstraint* newconstraint = NULL;
    int isnc4 = FLAGSET(nccomm->controls,NCF_NC4);


    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 { /* 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(!isnc4) {
	        /* If netcdf 3 and 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.dimset0);j++) {
                CDFnode* dim = (CDFnode*)nclistget(var->array.dimset0,j);
                nelems *= dim->dim.declsize;
	    }
if(SHOWFETCH) {
nclog(NCLOGDBG,"prefetch: %s=%lu",var->ncfullname,(unsigned long)nelems);
}
	    if(nelems <= nccomm->cdf.smallsizelimit) {
	        nclistpush(vars,(ncelem)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.
    */

    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,(ncelem)varprojection);
    }
if(SHOWFETCH) {
char* s = dumpprojections(newconstraint->projections);
LOG1(NCLOGNOTE,"prefetch.final: %s",s);
nullfree(s);
}
    ncstat = buildcachenode34(nccomm,newconstraint,vars,&cache,!isnc4);
    newconstraint = NULL; /* buildcachenode34 takes control of newconstraint */
    if(ncstat) goto done;
    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 = makecdfpathstring3(var,".");
ncbytescat(buf,s);
nullfree(s);
}
ncbytescat(buf,"\n");
nclog(NCLOGNOTE,"%s",ncbytescontents(buf));
ncbytesfree(buf);
}

done:
    nclistfree(vars);
    dcefree((DCEnode*)newconstraint);    
    if(ncstat) freenccachenode(nccomm,cache);
    return THROW(ncstat);
}
Esempio n. 18
0
/* 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
prefetchdata3(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.
       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;
    if(nclistlength(allvars) == nclistlength(vars)) flags |= NCF_PREFETCH_ALL;
    ncstat = buildcachenode34(nccomm,newconstraint,vars,&cache,flags);
    newconstraint = NULL; /* buildcachenode34 takes control of newconstraint */
    if(ncstat) goto done;
    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 = makecdfpathstring3(var,".");
ncbytescat(buf,s);
nullfree(s);
 }
ncbytescat(buf,"\n");
nclog(NCLOGNOTE,"%s",ncbytescontents(buf));
ncbytesfree(buf);
 }

done:
    nclistfree(vars);
    dcefree((DCEnode*)newconstraint);    
    if(ncstat) freenccachenode(nccomm,cache);
    return THROW(ncstat);
}
Esempio n. 19
0
NCerror
buildvaraprojection3(Getvara* getvar,
		     const size_t* startp, const size_t* countp, const ptrdiff_t* stridep,
		     DCEprojection** projectionp)
{
    int i,j;
    int ncrank;
    NCerror ncstat = NC_NOERR;
    CDFnode* var = getvar->target;
    NClist* vardims = var->array.dimensions;
    DCEprojection* projection = NULL;
    NClist* path = nclistnew();
    NClist* segments = NULL;
    int dimindex;
    NClist* dimset = NULL;

    /* Collect the nodes needed to construct the projection segment */    
    collectnodepath3(var,path,!WITHDATASET);

    dimset = var->array.dimensions;
    ncrank = nclistlength(dimset);

    segments = nclistnew();
    nclistsetalloc(segments,nclistlength(path));
    for(i=0;i<nclistlength(path);i++) {
	DCEsegment* segment = (DCEsegment*)dcecreate(CES_SEGMENT);
	CDFnode* n = (CDFnode*)nclistget(path,i);
	segment->cdfnode = n;
	ASSERT((segment->cdfnode != NULL));
        segment->name = nulldup(n->name);
	segment->slicesdefined = 0; /* temporary */
	segment->slicesdeclized = 0; /* temporary */
	nclistpush(segments,(ncelem)segment);
    }
    
    projection = (DCEprojection*)dcecreate(CES_PROJECT);
    projection->discrim = CES_VAR;
    projection->var = (DCEvar*)dcecreate(CES_VAR);
    projection->var->cdfleaf = var;
    projection->var->segments = segments;

    /* We need to assign slices to each segment */
    dimindex = 0; /* point to next subset of slices */
    for(i=0;i<nclistlength(segments);i++) {
	DCEsegment* segment = (DCEsegment*)nclistget(segments,i);
	int localrank = nclistlength(segment->cdfnode->array.dimensions0);
        if(segment->cdfnode->array.stringdim != NULL) localrank++;
        if(segment->cdfnode->array.seqdim != NULL) localrank++;
        segment->rank = localrank;
        for(j=0;j<localrank;j++) {
	    DCEslice* slice = &segment->slices[j];
	    CDFnode* dim = (CDFnode*)nclistget(vardims,dimindex+j);
	    slice->first = startp[dimindex+j];
	    slice->stride = stridep[dimindex+j];
	    slice->count = countp[dimindex+j];
	    slice->length = slice->count * slice->stride;
	    if(slice->length > dim->dim.declsize)
		slice->length = dim->dim.declsize;
	    slice->stop = (slice->first + slice->length);
	    if(slice->stop > dim->dim.declsize)
		slice->stop = dim->dim.declsize;
	    slice->declsize = dim->dim.declsize;
	}
	segment->slicesdefined = 1;
	segment->slicesdeclized = 1;
	dimindex += localrank;
	ASSERT((dimindex <= ncrank));
    }

    ASSERT((dimindex == ncrank));

    if(projectionp) *projectionp = projection;

    nclistfree(path);
    if(ncstat) dcefree((DCEnode*)projection);
    return ncstat;
}
Esempio n. 20
0
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);
}
Esempio n. 21
0
DCEnode*
dceclone(DCEnode* node)
{
    DCEnode* result = NULL;

    result = (DCEnode*)dcecreate(node->sort);
    if(result == NULL) goto done;

    switch (node->sort) {

    case CES_SLICE: {
	DCEslice* clone = (DCEslice*)result;
	DCEslice* orig = (DCEslice*)node;
	*clone = *orig;
    } break;

    case CES_SEGMENT: {
	DCEsegment* clone = (DCEsegment*)result;
	DCEsegment* orig = (DCEsegment*)node;
	*clone = *orig;	
        clone->name = nulldup(orig->name);
	if(orig->rank > 0)
	    memcpy(clone->slices,orig->slices,orig->rank*sizeof(DCEslice));
    } break;

    case CES_VAR: {
	DCEvar* clone = (DCEvar*)result;
	DCEvar* orig = (DCEvar*)node;
	*clone = *orig;
	clone->segments = dceclonelist(clone->segments);
    } break;

    case CES_FCN: {
	DCEfcn* clone = (DCEfcn*)result;
	DCEfcn* orig = (DCEfcn*)node;
	*clone = *orig;
        clone->name = nulldup(orig->name);
	clone->args = dceclonelist(orig->args);
    } break;

    case CES_CONST: {
	DCEconstant* clone = (DCEconstant*)result;
	DCEconstant* orig = (DCEconstant*)node;
	*clone = *orig;
        if(clone->discrim ==  CES_STR)
	    clone->text = nulldup(clone->text);
    } break;

    case CES_VALUE: {
	DCEvalue* clone = (DCEvalue*)result;
	DCEvalue* orig = (DCEvalue*)node;
	*clone = *orig;
        switch (clone->discrim) {
        case CES_CONST:
	    clone->constant = (DCEconstant*)dceclone((DCEnode*)orig->constant); break;
        case CES_VAR:
	    clone->var = (DCEvar*)dceclone((DCEnode*)orig->var); break;
        case CES_FCN:
	    clone->fcn = (DCEfcn*)dceclone((DCEnode*)orig->fcn); break;
        default: assert(0);
        }
    } break;

    case CES_PROJECT: {
	DCEprojection* clone = (DCEprojection*)result;
	DCEprojection* orig = (DCEprojection*)node;
	*clone = *orig;	
	switch (orig->discrim) {
	case CES_VAR:
            clone->var = (DCEvar*)dceclone((DCEnode*)orig->var); break;
	case CES_FCN:
            clone->fcn = (DCEfcn*)dceclone((DCEnode*)orig->fcn); break;
	default: assert(0);
	}
    } break;

    case CES_SELECT: {
	DCEselection* clone = (DCEselection*)result;
	DCEselection* orig = (DCEselection*)node;
	*clone = *orig;	
	clone->lhs = (DCEvalue*)dceclone((DCEnode*)orig->lhs);
	clone->rhs = dceclonelist(orig->rhs);
    } break;

    case CES_CONSTRAINT: {
	DCEconstraint* clone = (DCEconstraint*)result;
	DCEconstraint* orig = (DCEconstraint*)node;
	*clone = *orig;	
	clone->projections = dceclonelist(orig->projections);	
	clone->selections = dceclonelist(orig->selections);
    } break;

    default:
	assert(0);
    }

done:
    return result;
}
Esempio n. 22
0
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;
}