Esempio n. 1
0
/* Utility to copy contents of the dfalt into an NCPROPINFO object */
static int
propinfo_default(struct NCPROPINFO* dst, const struct NCPROPINFO* dfalt)
{
    int i;
    if(dst->properties == NULL) {
        dst->properties = nclistnew();
        if(dst->properties == NULL) return NC_ENOMEM;
    }
    dst->version = dfalt->version;
    for(i=0;i<nclistlength(dfalt->properties);i++) {
        char* s = nclistget(dfalt->properties,i);
        s = strdup(s);
        if(s == NULL) return NC_ENOMEM;
        nclistpush(dst->properties,s);
    }
    return NC_NOERR;
}
Esempio n. 2
0
/**
 * @internal
 *
 * Construct the provenance information for a newly created file
 * using dfalt as the default.
 * Note that creation of the _NCProperties attribute is deferred
 * to the sync_netcdf4_file function.
 *
 * @param file Pointer to file object.
 * @param dfalt
 *
 * @return ::NC_NOERR No error.
 * [Note: other errors are reported via LOG()]
 * @author Dennis Heimbigner
 */
int
NC4_set_provenance(NC_FILE_INFO_T* file, const struct NCPROPINFO* dfalt)
{
    int ncstat = NC_NOERR;
    struct NCPROVENANCE* provenance = NULL;
    int superblock = -1;

    LOG((3, "%s: ncid 0x%x", __func__, file->root_grp->hdr.id));

    assert(file->provenance == NULL);

    provenance = calloc(1,sizeof(struct NCPROVENANCE));
    if(provenance == NULL) {ncstat = NC_ENOMEM; goto done;}

    /* Initialize from the default */
    provenance->propattr.version = globalpropinfo.version;
    /* Get the superblock number */
    if((ncstat = NC4_hdf5get_superblock(file,&superblock)))
        goto done;
    provenance->superblockversion = superblock;

    /* Capture properties */
    provenance->propattr.properties = nclistnew();
    if(provenance->propattr.properties == NULL)
    {ncstat = NC_ENOMEM; goto done;}
    /* add in the dfalt values */
    if(dfalt != NULL) {
        int i;
        for(i=0;i<nclistlength(dfalt->properties);i++) {
            char* prop = nclistget(dfalt->properties,i);
            if(prop != NULL) {
                prop = strdup(prop);
                if(prop == NULL) {ncstat = NC_ENOMEM; goto done;}
                nclistpush(provenance->propattr.properties,prop);
            }
        }
    }

done:
    if(ncstat) {
        LOG((0,"Could not create _NCProperties attribute"));
        (void)NC4_free_provenance(provenance);
    } else
        file->provenance = provenance;
    return NC_NOERR;
}
Esempio n. 3
0
/* In order to construct the projection,
we need to make sure to match the relevant dimensions
against the relevant nodes in which the ultimate target
is contained.
*/
NCerror
buildvaraprojection4(NCDRNO* drno, Getvara* getvar,
		     const size_t* startp, const size_t* countp, const ptrdiff_t* stridep,
		     NCprojection** projectionp)
{
    int i;
    NCerror ncstat = NC_NOERR;
    NClist* dimset;
    CDFnode* var = getvar->target;
    NCprojection* projection = NULL;
    NClist* segments = NULL;
    NCsegment* segment;

    segment = createncsegment();
    segment->node = var;
    ASSERT((segment->node != NULL));
    segment->segment = nulldup(segment->node->name);
    segment->slicesdefined = 0; /* temporary */
    segments = nclistnew();
    nclistpush(segments,(ncelem)segment);

    projection = createncprojection();
    projection->leaf = var;
    projection->segments = segments;

    /* All slices are assigned to the first (and only segment) */
    dimset = var->array.dimensions;
    segment->slicerank = nclistlength(var->array.dimensions);
    for(i=0;i<segment->slicerank;i++) {
        NCslice* slice = &segment->slices[i];
	CDFnode* dim = (CDFnode*)nclistget(dimset,i);
        slice->first = startp[i];
	slice->stride = stridep[i];
	slice->count = countp[i];
        slice->length = slice->count * slice->stride;
	slice->stop = (slice->first + slice->length);
	ASSERT(dim->dim.declsize > 0);
    	slice->declsize = dim->dim.declsize;
    }
    segment->slicesdefined = 1;

    if(projectionp) *projectionp = projection;
    if(ncstat) freencprojection1(projection);
    return ncstat;
}
Esempio n. 4
0
int
nc_http_open(const char* objecturl, void** curlp, long long* filelenp)
{
    int stat = NC_NOERR;
    CURL* curl = NULL;
    int i;
    NClist* list = NULL; 

    Trace("open");

    /* initialize curl*/
    curl = curl_easy_init();
    if (curl == NULL) stat = NC_ECURL;
    if(curlp && curl) *curlp = (void*)curl;
    if(filelenp) {
	*filelenp = -1;
        /* Attempt to get the file length using HEAD */
	list = nclistnew();
	if((stat = setupconn(curl,objecturl,NULL))) goto done;
	if((stat = headerson(curl,list))) goto done;
	if((stat = execute(curl,HEADCMD,NULL))) goto done;
	headersoff(curl);
	for(i=0;i<nclistlength(list);i+=2) {
	    char* s = nclistget(list,i);
	    if(strcasecmp(s,"content-length")==0) {
	        s = nclistget(list,i+1);
		sscanf(s,"%lld",filelenp);
		break;
	    }
	    /* Also check for the Accept-Ranges header */ 
	    if(strcasecmp(s,"accept-ranges")==0) {
	        s = nclistget(list,i+1);
		if(strcasecmp(s,"bytes")!=0) /* oops! */
		    {stat = NC_EACCESS; goto done;}
	    }
	}
    }  
done:
    nclistfreeall(list);
dbgflush();
    return stat;
}
Esempio n. 5
0
/* Overwrite if already there*/
int
nchashreplace(NChashmap* hm, nchashid hash, void* value)
{
    int i,offset,len;
    NClist* seq;
    void** list;

    offset = (hash % hm->alloc);    
    seq = hm->table[offset];
    if(seq == NULL) {seq = nclistnew(); hm->table[offset] = seq;}
    len = nclistlength(seq);
    list = nclistcontents(seq);
    for(i=0;i<len;i+=2,list+=2) {
	if(hash==(nchashid)(*list)) {list[1] = value; return TRUE;}
    }    
    nclistpush(seq,(void*)hash);
    nclistpush(seq,value);
    hm->size++;
    return TRUE;
}
Esempio n. 6
0
char*
dumppath(CDFnode* leaf)
{
    NClist* path = nclistnew();
    NCbytes* buf = ncbytesnew();
    char* result;
    int i;

    if(leaf == NULL) return nulldup("");
    collectnodepath3(leaf,path,!WITHDATASET);
    for(i=0;i<nclistlength(path);i++) {
	CDFnode* node = (CDFnode*)nclistget(path,i);
	if(i > 0) ncbytescat(buf,".");
	ncbytescat(buf,node->name);
    }
    result = ncbytesdup(buf);
    ncbytesfree(buf);
    nclistfree(path);
    return result;
}
Esempio n. 7
0
/* Replace the query */
int
ncurisetquery(NCURI* duri,const char* query)
{
    int ret = NCU_OK;
    freestringvec(duri->querylist);    
    nullfree(duri->query);
    duri->query = NULL;
    duri->querylist = NULL;
    if(query != NULL && strlen(query) > 0) {
	NClist* params = nclistnew();
	duri->query = strdup(query);
	ret = parselist(duri->query,params);
	if(ret != NCU_OK)
	    {THROW(NC_EURL);}
	nclistpush(params,NULL);
	duri->querylist = nclistextract(params);
	nclistfree(params);
    }
done:
    return ret;
}
Esempio n. 8
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. 9
0
char*
makeocpathstring(OClink conn, OCddsnode node, const char* sep)
{
    int i,len,first;
    char* result;
    char* name;
    OCtype octype;
    NClist* ocpath = NULL;
    NCbytes* pathname = NULL;

    /* If we are asking for the dataset path only,
       then include it, otherwise elide it
    */
    oc_dds_type(conn,node,&octype);
    if(octype == OC_Dataset) {
        oc_dds_name(conn,node,&name);
	return nulldup(name);
    }

    ocpath = nclistnew();
    collectocpath(conn,node,ocpath);
    len = nclistlength(ocpath);
    assert(len > 0); /* dataset at least */

    pathname = ncbytesnew();
    for(first=1,i=1;i<len;i++) { /* start at 1 to skip dataset name */
	OCddsnode node = (OCddsnode)nclistget(ocpath,i);
	char* name;
        oc_dds_type(conn,node,&octype);
        oc_dds_name(conn,node,&name);
	if(!first) ncbytescat(pathname,sep);
	ncbytescat(pathname,name);
	nullfree(name);
	first = 0;
    }
    result = ncbytesextract(pathname);
    ncbytesfree(pathname);
    nclistfree(ocpath);
    return result;
}
Esempio n. 10
0
/* Given an OCnode tree, mimic it as a CDFnode tree;
   Add DAS attributes if DAS is available. Accumulate set
   of all nodes in preorder.
*/
NCerror
buildcdftree(NCDAPCOMMON* nccomm, OCddsnode ocroot, OCdxd occlass, CDFnode** cdfrootp)
{
    CDFnode* root = NULL;
    CDFtree* tree = (CDFtree*)calloc(1,sizeof(CDFtree));
    NCerror err = NC_NOERR;
    if(!tree)
      return OC_ENOMEM;

    tree->ocroot = ocroot;
    tree->nodes = nclistnew();
    tree->occlass = occlass;
    tree->owner = nccomm;

    err = buildcdftreer(nccomm,ocroot,NULL,tree,&root);
    if(!err) {
	if(occlass != OCDAS)
	    fixnodes(nccomm,tree->nodes);
	if(cdfrootp) *cdfrootp = root;
    }
    return err;
}
Esempio n. 11
0
/*
Given a das attribute walk it to see if it
has at least 1 actual attribute (no recursion)
*/
static int
hasattribute3(OClink conn, OCdasnode dasnode)
{
    int i;
    OCerror ocstat = OC_NOERR;
    int tf = 0; /* assume false */
    OCtype ocsubtype;
    NClist* subnodes = nclistnew();

    OCCHECK(oc_dds_octype(conn,dasnode,&ocsubtype));
    if(ocsubtype == OC_Attribute) return 1; /* this is an attribute */
    ASSERT((ocsubtype == OC_Attributeset));

    OCCHECK(collect_subnodes(conn,dasnode,subnodes));
    for(i=0;i<nclistlength(subnodes);i++) {
        OCdasnode subnode = (OCdasnode)nclistget(subnodes,i);
        OCCHECK(oc_dds_class(conn,subnode,&ocsubtype));
	if(ocsubtype == OC_Attribute) {tf=1; break;}
    }
done:
    nclistfree(subnodes);
    return tf;
}
Esempio n. 12
0
/* Build an NCattribute */
static NCerror
buildattribute(char* name, nc_type ptype,
               size_t nvalues, char** values, NCattribute** attp)
{
    int i;
    NCerror ncstat = NC_NOERR;
    NCattribute* att = NULL;

    att = (NCattribute*)calloc(1,sizeof(NCattribute));
    MEMCHECK(att,NC_ENOMEM);
    att->name = nulldup(name);
    att->etype = ptype;

    att->values = nclistnew();
    for(i=0;i<nvalues;i++)
	nclistpush(att->values,(void*)nulldup(values[i]));

    if(attp) *attp = att;
    else
      free(att);

    return THROW(ncstat);
}
Esempio n. 13
0
static NCerror
fillselectionpath(DCEselection* s, NClist* nodes)
{
    int i;
    NCerror ncstat = NC_NOERR;
    NClist* path = nclistnew();
    DCEvar* var;

    ASSERT(s->lhs->discrim == CES_VAR);
    var = s->lhs->var;
    ncstat = matchpartialname3(nodes,var->segments,&var->cdfleaf);
    if(ncstat) goto done;
    /* Now find the value paths */
    for(i=0;i<nclistlength(s->rhs);i++) {
        DCEvalue* v = (DCEvalue*)nclistget(s->rhs,i);
	if(v->discrim != CES_VAR) continue;
        ncstat = matchpartialname3(nodes,v->var->segments,&v->var->cdfnode);
        if(ncstat) goto done;
    }
    
done:
    nclistfree(path);
    return ncstat;
}
Esempio n. 14
0
File: cdf.c Progetto: qingu/netcdf-c
NCerror
restruct(NCDAPCOMMON* ncc, CDFnode* ddsroot, CDFnode* templateroot, NClist* projections)
{
    NCerror ncstat = NC_NOERR;
    NClist* repairs = nclistnew();

    /* The current restruct assumes that the ddsroot tree
       has missing grids compared to the template.
       It is also assumed that order of the nodes
       in the ddsroot is the same as in the template.
    */
    if(ddsroot->tree->restructed) {
        nclistfree(repairs);
        return NC_NOERR;
    }

#ifdef DEBUG
    fprintf(stderr,"restruct: ddsroot=%s\n",dumptree(ddsroot));
    fprintf(stderr,"restruct: templateroot=%s\n",dumptree(templateroot));
#endif

    /* Match roots */
    if(!simplenodematch(ddsroot,templateroot))
        ncstat = NC_EDATADDS;
    else if(!restructr(ncc,ddsroot,templateroot,repairs))
        ncstat = NC_EDATADDS;
    else if(nclistlength(repairs) > 0) {
        /* Do the repairs */
        ncstat = repairgrids(ncc, repairs);
    }

    if(repairs)
        nclistfree(repairs);

    return THROW(ncstat);
}
Esempio n. 15
0
NCerror
dapmerge3(NCDRNO* drno, CDFnode* node)
{
    unsigned int i;
    char* aname;
    unsigned int nvalues,nattrs;
    void* values;
    OCtype atype;
    OCerror ocstat = OC_NOERR;
    NCerror ncstat = NC_NOERR;
    NCattribute* att;

    if(node->dds == OCNULL) goto done;
    OCHECK(oc_inq_nattr(drno->dap.conn,node->dds,&nattrs));
    if(nattrs == 0) goto done;
    if(node->attributes == NULL) node->attributes = nclistnew();
    for(i=0;i<nattrs;i++) {
	ocstat = oc_inq_attr(drno->dap.conn,node->dds,i,
			           &aname,
			           &atype,
                                   &nvalues,
                                   &values);
	if(ocstat != OC_NOERR) continue; /* ignore */
        if(aname == NULL || nvalues == 0 || values == NULL)
	    continue; /* nothing to do */
	ncstat = buildattribute(aname,octypetonc(atype),
				      nvalues,values,&att);
	if(ncstat == NC_NOERR)
            nclistpush(node->attributes,(ncelem)att);
	efree(aname);
	oc_attr_reclaim(atype,nvalues,values);
    }
done:
    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
    return THROW(ncstat);
}
Esempio n. 16
0
/* convert all names in projections in paths to be fully qualified
   by adding prefix segment objects.
*/
static NCerror
qualifyprojectionnames3(DCEprojection* proj)
{
    NCerror ncstat = NC_NOERR;
    NClist* fullpath = nclistnew();

    ASSERT((proj->discrim == CES_VAR
            && proj->var->annotation != NULL
            && ((CDFnode*)proj->var->annotation)->ocnode != OCNULL));
    collectnodepath3((CDFnode*)proj->var->annotation,fullpath,!WITHDATASET);
#ifdef DEBUG
fprintf(stderr,"qualify: %s -> ",
	dumpprojection(proj));
#endif
    /* Now add path nodes to create full path */
    completesegments3(fullpath,proj->var->segments);

#ifdef DEBUG
fprintf(stderr,"%s\n",
	dumpprojection(proj));
#endif
    nclistfree(fullpath);
    return ncstat;
}
Esempio n. 17
0
/**
 * @internal Initialize default provenance info
 * This will only be used for newly created files
 * or for opened files that do not contain an _NCProperties
 * attribute.
 *
 * @return ::NC_NOERR No error.
 * @author Dennis Heimbigner
 */
int
NC4_provenance_init(void)
{
    int stat = NC_NOERR;
    int i;
    NClist* other = NULL;
    char* name = NULL;
    char* value = NULL;
    unsigned major,minor,release;

    if(globalpropinitialized)
        return stat;

    /* Build _NCProperties info */

    /* Initialize globalpropinfo */
    memset((void*)&globalpropinfo,0,sizeof(globalpropinfo));
    globalpropinfo.version = NCPROPS_VERSION;
    globalpropinfo.properties = nclistnew();
    if(globalpropinfo.properties == NULL)
    {stat = NC_ENOMEM; goto done;}

    /* Insert primary library version as first entry */
    if((name = strdup(NCPNCLIB2)) == NULL)
    {stat = NC_ENOMEM; goto done;}
    nclistpush(globalpropinfo.properties,name);
    name = NULL; /* Avoid multiple free() */

    if((value = strdup(PACKAGE_VERSION)) == NULL)
    {stat = NC_ENOMEM; goto done;}
    nclistpush(globalpropinfo.properties,value);
    value = NULL;

    /* Insert the HDF5 as underlying storage format library */
    if((name = strdup(NCPHDF5LIB2)) == NULL)
    {stat = NC_ENOMEM; goto done;}
    nclistpush(globalpropinfo.properties,name);
    name = NULL;

    stat = NC4_hdf5get_libversion(&major,&minor,&release);
    if(stat) goto done;
    {
        char sversion[64];
        snprintf(sversion,sizeof(sversion),"%1u.%1u.%1u",major,minor,release);
        if((value = strdup(sversion)) == NULL)
        {stat = NC_ENOMEM; goto done;}
    }
    nclistpush(globalpropinfo.properties,value);
    value = NULL;

    /* Add any extra fields */
    /*Parse them into an NClist */
    other = nclistnew();
    if(other == NULL) {stat = NC_ENOMEM; goto done;}
#ifdef NCPROPERTIES
    stat = properties_parse(NCPROPERTIES_EXTRA,other);
    if(stat) goto done;
#endif
    /* merge into the properties list */
    for(i=0;i<nclistlength(other);i++)
        nclistpush(globalpropinfo.properties,strdup(nclistget(other,i)));
    nclistfreeall(other);
    other = NULL;

done:
    if(name != NULL) free(name);
    if(value != NULL) free(value);
    if(other != NULL)
        nclistfreeall(other);
    if(stat && globalpropinfo.properties != NULL) {
        nclistfreeall(globalpropinfo.properties);
        globalpropinfo.properties = NULL;
    }
    if(stat == NC_NOERR)
        globalpropinitialized = 1; /* avoid repeating it */
    return stat;
}
Esempio n. 18
0
/**
 * @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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/* Given the arguments to vara
   construct a corresponding projection
   with any pseudo dimensions removed
*/
NCerror
buildvaraprojection(CDFnode* var,
		     const size_t* startp, const size_t* countp, const ptrdiff_t* stridep,
		     DCEprojection** projectionp)
{
    int i,j;
    NCerror ncstat = NC_NOERR;
    DCEprojection* projection = NULL;
    NClist* path = nclistnew();
    NClist* segments = NULL;
    int dimindex;

    /* Build a skeleton projection that has 1 segment for
       every cdfnode from root to the variable of interest.
       Each segment has the slices from its corresponding node
       in the path, including pseudo-dims
    */
    ncstat = dapvar2projection(var,&projection);


#ifdef DEBUG
fprintf(stderr,"buildvaraprojection: skeleton: %s\n",dumpprojection(projection));
#endif

    /* Now, modify the projection to reflect the corresponding
       start/count/stride from the nc_get_vara arguments.
    */
    segments = projection->var->segments;
    dimindex = 0;
    for(i=0;i<nclistlength(segments);i++) {
	DCEsegment* segment = (DCEsegment*)nclistget(segments,i);
        for(j=0;j<segment->rank;j++) {
	    size_t count = 0;
	    DCEslice* slice = &segment->slices[j];
	    /* make each slice represent the corresponding
               start/count/stride */
	    slice->first = startp[dimindex+j];
	    slice->stride = stridep[dimindex+j];
	    count = countp[dimindex+j];
	    slice->count = count;
	    slice->length = count * slice->stride;
	    slice->last = (slice->first + slice->length) - 1;
	    if(slice->last >= slice->declsize) {
		slice->last = slice->declsize - 1;
		/* reverse compute the new length */
		slice->length = (slice->last - slice->first) + 1;
	    }
	}
	dimindex += segment->rank;
    }
#ifdef DEBUG
fprintf(stderr,"buildvaraprojection.final: %s\n",dumpprojection(projection));
#endif

#ifdef DEBUG
fprintf(stderr,"buildvaraprojection3: final: projection=%s\n",
        dumpprojection(projection));
#endif

    if(projectionp) *projectionp = projection;

    nclistfree(path);
    if(ncstat) dcefree((DCEnode*)projection);
    return ncstat;
}
Esempio n. 21
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. 22
0
static int
mergedas1(OCconnection conn, CDFnode* dds, OCobject das)
{
    NCerror ncstat = NC_NOERR;
    OCerror ocstat = OC_NOERR;
    unsigned int i,j;
    unsigned int nsubnodes;
    OCobject* subnodes = NULL;
    OCobject* dodsnodes = NULL;
    unsigned int ndodsnodes;


    if(dds == NULL || das == OCNULL) return NC_NOERR; /* nothing to do */
    if(dds->attributes == NULL) dds->attributes = nclistnew();
    /* assign the simple attributes in the das set to this dds node*/
    OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes));
    OCHECK(oc_inq_subnodes(conn,das,&subnodes));
    for(i=0;i<nsubnodes;i++) {
	OCobject attnode = subnodes[i];
	OCtype octype, ocetype;
	char* ocname = NULL;
	unsigned int ocnvalues;
        OCHECK(oc_inq_name(conn,attnode,&ocname));	
        OCHECK(oc_inq_class(conn,attnode,&octype));
	if(octype == OC_Attribute) {
	    NCattribute* att = NULL;
	    NClist* stringvalues;
            OCHECK(oc_inq_primtype(conn,attnode,&ocetype));	
	    OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues));
	    stringvalues = nclistnew();
	    for(j=0;j<ocnvalues;j++) {
		char* stringval;
	        OCHECK(oc_inq_dasattr(conn,attnode,j,&ocetype,&stringval));
	        nclistpush(stringvalues,(ncelem)stringval);
	    }
	    ncstat = buildattribute(ocname,
				    octypetonc(ocetype),
				    stringvalues,
				    &att);				
	    if(ncstat) goto done;
            nclistpush(dds->attributes,(ncelem)att);
	} else if(octype == OC_Attributeset && strcmp(ocname,"DODS")==0) {
	    /* This is a DODS special attribute set */
	    OCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes));
	    OCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes));
	    for(j=0;j<ndodsnodes;j++) {
		char* dodsname = NULL;
		char* stringval;
	        OCobject dodsnode = dodsnodes[j];
	        OCHECK(oc_inq_class(conn,dodsnode,&octype));
		if(octype != OC_Attribute) continue;
	        OCHECK(oc_inq_name(conn,dodsnode,&dodsname));
	        OCHECK(oc_inq_dasattr_nvalues(conn,dodsnode,&ocnvalues));
		if(strcmp(dodsname,"strlen")==0) {
		    unsigned int maxstrlen = 0;
		    if(ocnvalues > 0) {
		        OCHECK(oc_inq_dasattr(conn,dodsnode,0,NULL,&stringval));
			if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0;
			efree(stringval);
		    }
		    dds->dodsspecial.maxstrlen = maxstrlen;
#ifdef DEBUG
fprintf(stderr,"%s.maxstrlen=%d\n",dds->name,(int)dds->dodsspecial.maxstrlen);
#endif
		} else if(strcmp(dodsname,"dimName")==0) {
		    if(ocnvalues > 0) {
		        OCHECK(oc_inq_dasattr(conn,dodsnode,0,NULL,
				&dds->dodsspecial.dimname));
#ifdef DEBUG
fprintf(stderr,"%s.dimname=%s\n",dds->name,dds->dodsspecial.dimname);
#endif
		    } else dds->dodsspecial.dimname = NULL;
		} /* else ignore */
	        efree(dodsname);
	    }
	    efree(dodsnodes);
	} /* else ignore */
        efree(ocname);
    }

done:
    efree(subnodes);
    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
    return THROW(ncstat);
}
Esempio n. 23
0
/* 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);
}
Esempio n. 24
0
/* Do a simple uri parse: return NCU_OK if success, NCU_XXX if failed */
int
ncuriparse(const char* uri0, NCURI** durip)
{
    int ret = NCU_OK;
    NCURI tmp;
    char* p;
    char* q;
    int isfile;
    int hashost;
    char* uri = NULL;
    NCURI* duri = NULL;
    char* prefix = NULL;
    char* next = NULL;
    NClist* params = nclistnew();
    NClist* querylist = nclistnew();
    size_t len0;
    int pathchar;

    if(uri0 == NULL)
	{THROW(NCU_EBADURL);}

    len0 = strlen(uri0);
    if(len0 == 0)
	{THROW(NCU_EBADURL);}

    /* Create a local NCURI instance to hold
       pointers into the parsed string
    */
    memset(&tmp,0,sizeof(tmp));

    /* make mutable copy. Add some extra space
       because we will need to null terminate the host section
       without losing the first character of the path section.
    */
    uri = (char*)malloc(len0+1+1); /* +2 for nul term and for host section terminator */
    if(uri == NULL)
	{THROW(NCU_ENOMEM);}
    strncpy(uri,uri0,len0+1);

    /* Walk the uri and do the following:
	1. remove leading and trailing whitespace
	2. convert all '\\' -> '\' (Temp hack to remove escape characters
                                    inserted by Windows or MinGW)
    */
    for(q=uri,p=uri;*p;p++) {if((*p == '\\' && p[1] == '\\') || *p < ' ') {continue;} else {*q++ = *p;}}
    *q = '\0';

    p = uri;

    /* break up the url into coarse pieces */
    if(*p == LBRACKET) {
        prefix = p;
        ret = collectprefixparams(p,&next); /* collect the prefix */
        if(ret != NCU_OK)
            {THROW(NCU_EBADURL);}
         p = next;
    } else {
	prefix = NULL;
    }
    tmp.uri = p; /* will be the core */
    /* Skip past the core of the url */
    next = nclocate(p,"?#");
    if(next != NULL) {
	int c = *next;
	terminate(next);
	next++;
	if(c == '?') {
	    tmp.query = next;
	    next = nclocate(next,"#");
	    if(next == NULL)
		tmp.fragment = NULL;
	    else {
		terminate(next);
		next++;
	        tmp.fragment = next;
	    }
	} else { /*c == '#'*/
	    tmp.fragment = next;
	}	    
    }

    /* Parse the prefix parameters */
    if(prefix != NULL) {
        if(parselist(prefix,params) != NCU_OK)
            {THROW(NCU_EBADURL);}
    }
    /* Parse the fragment parameters */
    if(tmp.fragment != NULL) {
        if(parselist(tmp.fragment,params) != NCU_OK)
            {THROW(NCU_EBADURL);}
    }
    if(nclistlength(params) > 0) {
	nclistpush(params,NULL);
        tmp.fraglist = nclistextract(params);
    } else
	tmp.fraglist = NULL;
    /* Parse the query */
    if(tmp.query != NULL) {
        if(parselist(tmp.query,querylist) != NCU_OK)
            {THROW(NCU_EBADURL);}
        if(nclistlength(querylist) > 0) {
	    nclistpush(querylist,NULL);
            tmp.querylist = nclistextract(querylist);
	}
    }    

    /* Now parse the core of the url */
    p = tmp.uri;

    /* Mark the protocol */
    tmp.protocol = p;
    p = strchr(p,':');
    if(!p)
	{THROW(NCU_EBADURL);}
    terminate(p); /*overwrite colon*/
    p++; /* skip the colon */
    if(strlen(tmp.protocol)==0)
	{THROW(NCU_EBADURL);}
    /*
       The legal formats for file: urls are a problem since
       many variants are often accepted.
       By RFC, the proper general format is: file://host/path,
       where the 'host' can be omitted and defaults to 'localhost'.
       and the path includes the leading '/'.
       So, assuming no host, the format is: "file:///path".
       Some implementations, however, ignore the host, and allow
       the format: file:/path.
       We also simplify things by assuming the host part is always empty.
       which means we can have file:///path, but not file://..../path.
       Note in all cases, the leading '/' is considered part of the path,
       which is then assumed to be an absolute path. But also note that
       the windows drive letter has to be taken into account. Our rule is that
       if the path looks like D:..., 
       where D is a single alphabetic letter (a-z or A-Z),
       then it is a windows path and can be use in place of a /path.
       The rules implemented here (for file:) are then as follows
       1. file:D:... : assume D: is a windows drive letter and treat D:... as the path
       2. file:/X, where X does not start with a slash: treat /X as the path.
       3. file://D:... : assume D: is a windows drive letter and treat as the path
       4. file:///X, where X does not start with a slash: treat /X as the path.
       All other cases are disallowed: specifically including file://X.
    */

    isfile = (strcmp(tmp.protocol,"file")==0);
    if(isfile) {
	int l = strlen(p); /* to test if we have enough characters */
	hashost = 0; /* always */
	if(l >= 2 && p[1] == ':' && strchr(DRIVELETTERS,p[0]) != NULL) { /* case 1 */
	    p = p; /* p points to the start of the path */
        } else if(l >= 2 && p[0] == '/' && p[1] != '/') { /* case 2 */
	    p = p; /* p points to the start of the path */
	} else if(l >= 4 && p[0] == '/' && p[1] == '/'
		&& p[3] == ':' && strchr(DRIVELETTERS,p[2]) != NULL) { /* case 3 */
	    p = p+2; /* points to the start of the windows path */
        } else if(l >= 4 && p[0] == '/' && p[1] == '/' && p[2] == '/' && p[3] != '/') { /* case 4 */
	    p += 2; /* points to the start of the path */
        } else /* everything else is illegal */
	    {THROW(NCU_EPATH);}
    } else {
        if(p[0] != '/' || p[1] != '/') /* must be proto:// */
	    {THROW(NCU_EPATH);}
	p += 2;
        hashost = 1; /* Assume we have a hostname */
    }
    if(!hashost) {
        tmp.path = p;
	pathchar = EOFCHAR;
    } else { /* assume there should be a host section */
	/* We already extracted the query and/or fragment sections above,
           splocate the end of the host section and therefore the start
           of the path.
        */
	tmp.host = p;
        p  = nclocate(p,"/");
	if(p == NULL) { /* no path */
	    tmp.path = NULL; /* default */
	    pathchar = EOFCHAR;
	} else {
	    tmp.path = p; /* save ptr to rest of the path */
	    pathchar = *p; /* save leading char of the path */
	    terminate(p); /* overwrite the leading char of the path; restored below */
	}
    }
    /* Nullify tmp.host for consistency */
    if(tmp.host != NULL && strlen(tmp.host)==0) {tmp.host = NULL;}

    if(tmp.host != NULL) {/* Parse the host section */
        char* pp;
	/* Check for leading user:pwd@ */
        char* newhost = strchr(tmp.host,'@');
        if(newhost != NULL) {
	    size_t rem;
	    if(newhost == tmp.host)
		{THROW(NCU_EUSRPWD);} /* we have proto://@ */
	    terminate(newhost); /* overwrite '@' */
	    newhost++; /* should point past usr+pwd */
	    tmp.user = tmp.host;
	    /* Break user+pwd into two pieces */
	    pp = strchr(tmp.user,':');
	    if(pp == NULL)
		{THROW(NCU_EUSRPWD);} /* we have user only */
	    terminate(pp); /* overwrite ':' */
	    pp++;
	    if(strlen(tmp.user)==0)
		{THROW(NCU_EUSRPWD);} /* we have empty user */
	    if(strlen(pp)==0)
		{THROW(NCU_EUSRPWD);} /* we have empty password */
	    tmp.password = pp;	    
	    tmp.host = newhost;
	}
	/* Breakup host into host + port */
	pp = tmp.host;
        pp = strchr(pp,':');
        if(pp != NULL) { /* there is a port */
	    terminate(pp); /* overwrite ':' */
	    pp++; /* skip colon */
	    if(strlen(tmp.host) == 0)
		{THROW(NCU_EBADURL);} /* empty host */
	    if(strlen(pp)==0)
		{THROW(NCU_EBADURL);} /* empty port */
	    tmp.port = pp;
	    /* The port must look something like a number */
	    for(pp=tmp.port;*pp;pp++) {
	        if(strchr("0123456789-",*pp) == NULL)
		    {THROW(NCU_EPORT);}  /* probably not a real port, fail */
	    }
	} /* else no port */
    }

    /* Fill in duri from tmp */
    duri = (NCURI*)calloc(1,sizeof(NCURI));
    if(duri == NULL)
      {THROW(NCU_ENOMEM);}
    /* save original uri */
    duri->uri = strdup(uri0);
    duri->protocol = nulldup(tmp.protocol);
    /* before saving, we need to decode the user+pwd */
    duri->user = NULL;
    duri->password = NULL;
    if(tmp.user != NULL) 
        duri->user = ncuridecode(tmp.user);
    if(tmp.password != NULL)
        duri->password = ncuridecode(tmp.password);
    duri->host = nulldup(tmp.host);
    duri->port = nulldup(tmp.port);
    if(tmp.path != NULL) {
	/* We need to add back the previously overwritten path lead char (if necessary);
           this must be done after all host section related pieces have been captured */
	if(pathchar != EOFCHAR)
	    *tmp.path = pathchar;
        duri->path = nulldup(tmp.path);
    }
    duri->query = nulldup(tmp.query);
    duri->fragment = nulldup(tmp.fragment);
    duri->fraglist = tmp.fraglist; tmp.fraglist = NULL;
    duri->querylist = tmp.querylist; tmp.querylist = NULL;
    if(durip) *durip = duri;

#ifdef NCXDEBUG
	{
        fprintf(stderr,"duri:");
	fprintf(stderr," protocol=|%s|",FIX(duri->protocol));
	fprintf(stderr," user=|%s|",FIX(duri->user));
	fprintf(stderr," password=|%s|",FIX(duri->password));
	fprintf(stderr," host=|%s|",FIX(duri->host));
	fprintf(stderr," port=|%s|",FIX(duri->port));
	fprintf(stderr," path=|%s|",FIX(duri->path));
	fprintf(stderr," query=|%s|",FIX(duri->query));
	fprintf(stderr," fragment=|%s|",FIX(duri->fragment));
        fprintf(stderr,"\n");
    }
#endif

done:
    if(uri != NULL)
	free(uri);
    freestringlist(params);
    freestringlist(querylist);
    freestringvec(tmp.fraglist);
    freestringvec(tmp.querylist);
    return ret;
}
Esempio n. 25
0
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);
}
Esempio n. 26
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. 27
0
int
NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void* params, NCmodel* model, char** newpathp)
{
    int stat = NC_NOERR;
    char* newpath = NULL;
    NCURI* uri = NULL;
    int omode = *omodep;
    int isuri = 0;
    NClist* modeargs = nclistnew();

    if((stat = processuri(path, &uri, &newpath, modeargs))) goto done;
    isuri = (uri != NULL);

    /* Phase 1: compute the IOSP */
    if((stat = extractiosp(modeargs,omode,model))) goto done;
    assert(model->iosp != 0);

    /* Phase 2: Process the non-iosp mode arguments */
    if(!modelcomplete(model) && isuri) {
	    int i;
	    for(i=0;i<nclistlength(modeargs);i++) {
		const char* arg = nclistget(modeargs,i);
		if((stat=processmodearg(arg,model))) goto done;
	    }
    }

    /* Phase 3: See if we can infer DAP */
    if(!modelcomplete(model) && isuri) {
            if((stat = NC_dapinfer(modeargs,model))) goto done;
    }

    /* Phase 4: mode inference */
    if(!modelcomplete(model)) {
        if((stat = NC_omodeinfer(omode,model))) goto done;
    }

    /* Phase 5: Infer from file content, if possible;
       this has highest precedence, so it may override
       previous decisions.
    */
    if(!iscreate && isreadable(model->iosp)) {
	/* Ok, we need to try to read the file */
	if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done;
    }

    /* Phase 6: Infer impl from format */
    if(!modelcomplete(model)) {
        if((stat = NC_implinfer(useparallel, model))) goto done;
    }

    assert(modelcomplete(model));

    /* Force flag consistency */
    switch (model->impl) {
    case NC_FORMATX_NC4:
    case NC_FORMATX_NC_HDF4:
    case NC_FORMATX_DAP4:
    case NC_FORMATX_UDF0:
    case NC_FORMATX_UDF1:
	omode |= NC_NETCDF4;
	if(model->format == NC_FORMAT_NETCDF4_CLASSIC)
	    omode |= NC_CLASSIC_MODEL;
	break;
    case NC_FORMATX_DAP2:
	omode &= ~(NC_NETCDF4|NC_64BIT_OFFSET|NC_64BIT_DATA);
	break;
    case NC_FORMATX_NC3:
	omode &= ~NC_NETCDF4; /* must be netcdf-3 (CDF-1, CDF-2, CDF-5) */
	if(model->format == NC_FORMAT_64BIT_OFFSET) omode |= NC_64BIT_OFFSET;
	else if(model->format == NC_FORMAT_64BIT_DATA) omode |= NC_64BIT_DATA;
	break;
    case NC_FORMATX_PNETCDF:
	omode &= ~NC_NETCDF4; /* must be netcdf-3 (CDF-1, CDF-2, CDF-5) */
	if(model->format == NC_FORMAT_64BIT_OFFSET) omode |= NC_64BIT_OFFSET;
	else if(model->format == NC_FORMAT_64BIT_DATA) omode |= NC_64BIT_DATA;
	break;
    default:
	{stat = NC_ENOTNC; goto done;}
    }

done:
    if(uri) ncurifree(uri);
    nclistfreeall(modeargs);
    if(stat == NC_NOERR && newpathp) {*newpathp = newpath; newpath = NULL;}
    nullfree(newpath);
    *omodep = omode; /* in/out */
    return check(stat);
}
Esempio n. 28
0
static NCerror
matchpartialname3(NClist* nodes, NClist* segments, CDFnode** nodep)
{
    int i,nsegs;
    NCerror ncstat = NC_NOERR;
    DCEsegment* lastseg = NULL;
    NClist* namematches = nclistnew();
    NClist* matches = nclistnew();
    NClist* matchpath = nclistnew();

    /* Locate all nodes with the same name
       as the last element in the segment path
    */
    nsegs = nclistlength(segments);
    lastseg = (DCEsegment*)nclistget(segments,nsegs-1);
    for(i=0;i<nclistlength(nodes);i++) {
        CDFnode* node = (CDFnode*)nclistget(nodes,i);
	if(node->ocname == null)
	    continue;
	/* Path names come from oc space */
        if(strcmp(node->ocname,lastseg->name) != 0)
	    continue;
	/* Only look at selected kinds of nodes */
	if(node->nctype != NC_Sequence
               && node->nctype != NC_Structure
               && node->nctype != NC_Grid
               && node->nctype != NC_Primitive
          )
	    continue;
	nclistpush(namematches,(ncelem)node);
    }    
    if(nclistlength(namematches)==0) {
        nclog(NCLOGERR,"No match for projection name: %s",lastseg->name);
        ncstat = NC_EDDS;
	goto done;
    }

    /* Now, collect and compare paths of the matching nodes */
    for(i=0;i<nclistlength(namematches);i++) {
        CDFnode* matchnode = (CDFnode*)nclistget(namematches,i);
	nclistclear(matchpath);
	collectnodepath3(matchnode,matchpath,0);
	/* Do a suffix match */
        if(matchsuffix3(matchpath,segments)) {
	    nclistpush(matches,(ncelem)matchnode);
#ifdef DEBUG
fprintf(stderr,"matchpartialname: pathmatch: %s :: %s\n",
matchnode->ncfullname,dumpsegments(segments));
#endif
	}
    }
    /* |matches|==0 => no match; |matches|>1 => ambiguity */
    switch (nclistlength(matches)) {
    case 0:
        nclog(NCLOGERR,"No match for projection name: %s",lastseg->name);
        ncstat = NC_EDDS;
	break;
    case 1:
        if(nodep)
	    *nodep = (CDFnode*)nclistget(matches,0);
	break;
    default: {
	CDFnode* minnode = NULL;
	int minpath = 0;
	int nmin = 0; /* to catch multiple ones with same short path */
	/* ok, see if one of the matches has a path that is shorter
           then all the others */
	for(i=0;i<nclistlength(matches);i++) {
	    CDFnode* candidate = (CDFnode*)nclistget(matches,i);
	    nclistclear(matchpath);
	    collectnodepath3(candidate,matchpath,0);
	    if(minpath == 0) {
		minpath = nclistlength(matchpath);
		minnode = candidate;
	    } else if(nclistlength(matchpath) == minpath) {
	        nmin++;		
	    } else if(nclistlength(matchpath) < minpath) {
		minpath = nclistlength(matchpath);
		minnode = candidate;
		nmin = 1;
	    }
	} /*for*/
	if(minnode == NULL || nmin > 1) {	
	    nclog(NCLOGERR,"Ambiguous match for projection name: %s",
			lastseg->name);
            ncstat = NC_EDDS;
	} else if(nodep)
	    *nodep = minnode;
	} break;
    }
#ifdef DEBUG
fprintf(stderr,"matchpartialname: choice: %s %s for %s\n",
(nclistlength(matches) > 1?"":"forced"),
(*nodep)->ncfullname,dumpsegments(segments));
#endif

done:
    return THROW(ncstat);
}
Esempio n. 29
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);
}
Esempio n. 30
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);
}