[409] | 1 | /********************************************************************* |
---|
| 2 | * Copyright 1993, UCAR/Unidata |
---|
| 3 | * See netcdf/COPYRIGHT file for copying and redistribution conditions. |
---|
| 4 | * $Header: /upc/share/CVS/netcdf-3/libncdap3/common34.c,v 1.29 2010/05/25 13:53:02 ed Exp $ |
---|
| 5 | *********************************************************************/ |
---|
| 6 | |
---|
| 7 | #include "ncdap3.h" |
---|
| 8 | |
---|
| 9 | #ifdef HAVE_GETRLIMIT |
---|
| 10 | # ifdef HAVE_SYS_RESOURCE_H |
---|
| 11 | # include <sys/time.h> |
---|
| 12 | # endif |
---|
| 13 | # ifdef HAVE_SYS_RESOURCE_H |
---|
| 14 | # include <sys/resource.h> |
---|
| 15 | # endif |
---|
| 16 | #endif |
---|
| 17 | #include "dapdump.h" |
---|
| 18 | |
---|
| 19 | extern CDFnode* v4node; |
---|
| 20 | |
---|
| 21 | /* Define the set of protocols known to be constrainable */ |
---|
| 22 | static char* constrainableprotocols[] = {"http", "https",NULL}; |
---|
| 23 | static NCerror buildcdftree34r(NCDAPCOMMON*,OCobject,CDFnode*,CDFtree*,CDFnode**); |
---|
| 24 | static void defdimensions(OCobject, CDFnode*, NCDAPCOMMON*, CDFtree*); |
---|
| 25 | static NCerror attachsubset34r(CDFnode*, CDFnode*); |
---|
| 26 | static void free1cdfnode34(CDFnode* node); |
---|
| 27 | |
---|
| 28 | /* Define Procedures that are common to both |
---|
| 29 | libncdap3 and libncdap4 |
---|
| 30 | */ |
---|
| 31 | |
---|
| 32 | /* Ensure every node has an initial base name defined and fullname */ |
---|
| 33 | /* Exceptions: anonymous dimensions. */ |
---|
| 34 | static NCerror |
---|
| 35 | fix1node34(NCDAPCOMMON* nccomm, CDFnode* node) |
---|
| 36 | { |
---|
| 37 | if(node->nctype == NC_Dimension && node->ocname == NULL) return NC_NOERR; |
---|
| 38 | ASSERT((node->ocname != NULL)); |
---|
| 39 | nullfree(node->ncbasename); |
---|
| 40 | node->ncbasename = cdflegalname3(node->ocname); |
---|
| 41 | if(node->ncbasename == NULL) return NC_ENOMEM; |
---|
| 42 | nullfree(node->ncfullname); |
---|
| 43 | node->ncfullname = makecdfpathstring3(node,nccomm->cdf.separator); |
---|
| 44 | if(node->ncfullname == NULL) return NC_ENOMEM; |
---|
| 45 | if(node->nctype == NC_Primitive) |
---|
| 46 | node->externaltype = nctypeconvert(nccomm,node->etype); |
---|
| 47 | return NC_NOERR; |
---|
| 48 | } |
---|
| 49 | |
---|
| 50 | NCerror |
---|
| 51 | fixnodes34(NCDAPCOMMON* nccomm, NClist* cdfnodes) |
---|
| 52 | { |
---|
| 53 | int i; |
---|
| 54 | for(i=0;i<nclistlength(cdfnodes);i++) { |
---|
| 55 | CDFnode* node = (CDFnode*)nclistget(cdfnodes,i); |
---|
| 56 | NCerror err = fix1node34(nccomm,node); |
---|
| 57 | if(err) return err; |
---|
| 58 | } |
---|
| 59 | return NC_NOERR; |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | |
---|
| 63 | NCerror |
---|
| 64 | fixgrid34(NCDAPCOMMON* nccomm, CDFnode* grid) |
---|
| 65 | { |
---|
| 66 | unsigned int i,glen; |
---|
| 67 | CDFnode* array; |
---|
| 68 | |
---|
| 69 | glen = nclistlength(grid->subnodes); |
---|
| 70 | array = (CDFnode*)nclistget(grid->subnodes,0); |
---|
| 71 | if(nccomm->controls.flags & (NCF_NC3)) { |
---|
| 72 | /* Rename grid Array: variable, but leave its oc base name alone */ |
---|
| 73 | nullfree(array->ncbasename); |
---|
| 74 | array->ncbasename = nulldup(grid->ncbasename); |
---|
| 75 | if(!array->ncbasename) return NC_ENOMEM; |
---|
| 76 | } |
---|
| 77 | /* validate and modify the grid structure */ |
---|
| 78 | if((glen-1) != nclistlength(array->array.dimset0)) goto invalid; |
---|
| 79 | for(i=1;i<glen;i++) { |
---|
| 80 | CDFnode* arraydim = (CDFnode*)nclistget(array->array.dimset0,i-1); |
---|
| 81 | CDFnode* map = (CDFnode*)nclistget(grid->subnodes,i); |
---|
| 82 | CDFnode* mapdim; |
---|
| 83 | /* map must have 1 dimension */ |
---|
| 84 | if(nclistlength(map->array.dimset0) != 1) goto invalid; |
---|
| 85 | /* and the map name must match the ith array dimension */ |
---|
| 86 | if(arraydim->ocname != NULL && map->ocname != NULL |
---|
| 87 | && strcmp(arraydim->ocname,map->ocname) != 0) |
---|
| 88 | goto invalid; |
---|
| 89 | /* and the map name must match its dim name (if any) */ |
---|
| 90 | mapdim = (CDFnode*)nclistget(map->array.dimset0,0); |
---|
| 91 | if(mapdim->ocname != NULL && map->ocname != NULL |
---|
| 92 | && strcmp(mapdim->ocname,map->ocname) != 0) |
---|
| 93 | goto invalid; |
---|
| 94 | /* Add appropriate names for the anonymous dimensions */ |
---|
| 95 | /* Do the map name first, so the array dim may inherit */ |
---|
| 96 | if(mapdim->ocname == NULL) { |
---|
| 97 | nullfree(mapdim->ncbasename); |
---|
| 98 | mapdim->ocname = nulldup(map->ocname); |
---|
| 99 | if(!mapdim->ocname) return NC_ENOMEM; |
---|
| 100 | mapdim->ncbasename = cdflegalname3(mapdim->ocname); |
---|
| 101 | if(!mapdim->ncbasename) return NC_ENOMEM; |
---|
| 102 | } |
---|
| 103 | if(arraydim->ocname == NULL) { |
---|
| 104 | nullfree(arraydim->ncbasename); |
---|
| 105 | arraydim->ocname = nulldup(map->ocname); |
---|
| 106 | if(!arraydim->ocname) return NC_ENOMEM; |
---|
| 107 | arraydim->ncbasename = cdflegalname3(arraydim->ocname); |
---|
| 108 | if(!arraydim->ncbasename) return NC_ENOMEM; |
---|
| 109 | } |
---|
| 110 | if(FLAGSET(nccomm->controls,(NCF_NCDAP|NCF_NC3))) { |
---|
| 111 | char tmp[3*NC_MAX_NAME]; |
---|
| 112 | /* Add the grid name to the basename of the map */ |
---|
| 113 | snprintf(tmp,sizeof(tmp),"%s%s%s",map->container->ncbasename, |
---|
| 114 | nccomm->cdf.separator, |
---|
| 115 | map->ncbasename); |
---|
| 116 | nullfree(map->ncbasename); |
---|
| 117 | map->ncbasename = nulldup(tmp); |
---|
| 118 | if(!map->ncbasename) return NC_ENOMEM; |
---|
| 119 | } |
---|
| 120 | } |
---|
| 121 | return NC_NOERR; |
---|
| 122 | invalid: |
---|
| 123 | return NC_EINVAL; /* mal-formed grid */ |
---|
| 124 | } |
---|
| 125 | |
---|
| 126 | /** |
---|
| 127 | * Given an anonymous dimension, compute the |
---|
| 128 | * effective 0-based index wrt to the specified var. |
---|
| 129 | * The result should mimic the libnc-dap indices. |
---|
| 130 | */ |
---|
| 131 | |
---|
| 132 | static void |
---|
| 133 | computedimindexanon3(CDFnode* dim, CDFnode* var) |
---|
| 134 | { |
---|
| 135 | int i; |
---|
| 136 | NClist* dimset = var->array.dimsetall; |
---|
| 137 | for(i=0;i<nclistlength(dimset);i++) { |
---|
| 138 | CDFnode* candidate = (CDFnode*)nclistget(dimset,i); |
---|
| 139 | if(dim == candidate) { |
---|
| 140 | dim->dim.index1=i+1; |
---|
| 141 | return; |
---|
| 142 | } |
---|
| 143 | } |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | /* Replace dims in a list with their corresponding basedim */ |
---|
| 147 | static void |
---|
| 148 | replacedims(NClist* dims) |
---|
| 149 | { |
---|
| 150 | int i; |
---|
| 151 | for(i=0;i<nclistlength(dims);i++) { |
---|
| 152 | CDFnode* dim = (CDFnode*)nclistget(dims,i); |
---|
| 153 | CDFnode* basedim = dim->dim.basedim; |
---|
| 154 | if(basedim == NULL) continue; |
---|
| 155 | nclistset(dims,i,(ncelem)basedim); |
---|
| 156 | } |
---|
| 157 | } |
---|
| 158 | |
---|
| 159 | /** |
---|
| 160 | Two dimensions are equivalent if |
---|
| 161 | 1. they have the same size |
---|
| 162 | 2. neither are anonymous |
---|
| 163 | 3. they ave the same names. |
---|
| 164 | */ |
---|
| 165 | static int |
---|
| 166 | equivalentdim(CDFnode* basedim, CDFnode* dupdim) |
---|
| 167 | { |
---|
| 168 | if(dupdim->dim.declsize != basedim->dim.declsize) return 0; |
---|
| 169 | if(basedim->ocname == NULL && dupdim->ocname == NULL) return 0; |
---|
| 170 | if(basedim->ocname == NULL || dupdim->ocname == NULL) return 0; |
---|
| 171 | if(strcmp(dupdim->ocname,basedim->ocname) != 0) return 0; |
---|
| 172 | return 1; |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | /* |
---|
| 176 | Provide short and/or unified names for dimensions. |
---|
| 177 | This must mimic lib-ncdap, which is difficult. |
---|
| 178 | */ |
---|
| 179 | NCerror |
---|
| 180 | computecdfdimnames34(NCDAPCOMMON* nccomm) |
---|
| 181 | { |
---|
| 182 | int i,j; |
---|
| 183 | char tmp[NC_MAX_NAME*2]; |
---|
| 184 | NClist* conflicts = nclistnew(); |
---|
| 185 | NClist* varnodes = nccomm->cdf.varnodes; |
---|
| 186 | NClist* alldims; |
---|
| 187 | NClist* basedims; |
---|
| 188 | |
---|
| 189 | /* Collect all dimension nodes from dimsetall lists */ |
---|
| 190 | |
---|
| 191 | alldims = getalldims34(nccomm,0); |
---|
| 192 | |
---|
| 193 | /* Assign an index to all anonymous dimensions |
---|
| 194 | vis-a-vis its containing variable |
---|
| 195 | */ |
---|
| 196 | for(i=0;i<nclistlength(varnodes);i++) { |
---|
| 197 | CDFnode* var = (CDFnode*)nclistget(varnodes,i); |
---|
| 198 | for(j=0;j<nclistlength(var->array.dimsetall);j++) { |
---|
| 199 | CDFnode* dim = (CDFnode*)nclistget(var->array.dimsetall,j); |
---|
| 200 | if(dim->ocname != NULL) continue; /* not anonymous */ |
---|
| 201 | computedimindexanon3(dim,var); |
---|
| 202 | } |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | /* Unify dimensions by defining one dimension as the "base" |
---|
| 206 | dimension, and make all "equivalent" dimensions point to the |
---|
| 207 | base dimension. |
---|
| 208 | 1. Equivalent means: same size and both have identical non-null names. |
---|
| 209 | 2. Dims with same name but different sizes will be handled separately |
---|
| 210 | */ |
---|
| 211 | for(i=0;i<nclistlength(alldims);i++) { |
---|
| 212 | CDFnode* dupdim = NULL; |
---|
| 213 | CDFnode* basedim = (CDFnode*)nclistget(alldims,i); |
---|
| 214 | if(basedim == NULL) continue; |
---|
| 215 | if(basedim->dim.basedim != NULL) continue; /* already processed*/ |
---|
| 216 | for(j=i+1;j<nclistlength(alldims);j++) { /* Sigh, n**2 */ |
---|
| 217 | dupdim = (CDFnode*)nclistget(alldims,j); |
---|
| 218 | if(basedim == dupdim) continue; |
---|
| 219 | if(dupdim == NULL) continue; |
---|
| 220 | if(dupdim->dim.basedim != NULL) continue; /* already processed */ |
---|
| 221 | if(!equivalentdim(basedim,dupdim)) |
---|
| 222 | continue; |
---|
| 223 | dupdim->dim.basedim = basedim; /* equate */ |
---|
| 224 | #ifdef DEBUG1 |
---|
| 225 | fprintf(stderr,"assign: %s/%s -> %s/%s\n", |
---|
| 226 | basedim->dim.array->ocname,basedim->ocname, |
---|
| 227 | dupdim->dim.array->ocname,dupdim->ocname |
---|
| 228 | ); |
---|
| 229 | #endif |
---|
| 230 | } |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | /* Next case: same name and different sizes*/ |
---|
| 234 | /* => rename second dim */ |
---|
| 235 | |
---|
| 236 | for(i=0;i<nclistlength(alldims);i++) { |
---|
| 237 | CDFnode* basedim = (CDFnode*)nclistget(alldims,i); |
---|
| 238 | if(basedim->dim.basedim != NULL) continue; |
---|
| 239 | /* Collect all conflicting dimensions */ |
---|
| 240 | nclistclear(conflicts); |
---|
| 241 | for(j=i+1;j<nclistlength(alldims);j++) { |
---|
| 242 | CDFnode* dim = (CDFnode*)nclistget(alldims,j); |
---|
| 243 | if(dim->dim.basedim != NULL) continue; |
---|
| 244 | if(dim->ocname == NULL && basedim->ocname == NULL) continue; |
---|
| 245 | if(dim->ocname == NULL || basedim->ocname == NULL) continue; |
---|
| 246 | if(strcmp(dim->ocname,basedim->ocname)!=0) continue; |
---|
| 247 | if(dim->dim.declsize == basedim->dim.declsize) continue; |
---|
| 248 | #ifdef DEBUG2 |
---|
| 249 | fprintf(stderr,"conflict: %s[%lu] %s[%lu]\n", |
---|
| 250 | basedim->ncfullname,(unsigned long)basedim->dim.declsize, |
---|
| 251 | dim->ncfullname,(unsigned long)dim->dim.declsize); |
---|
| 252 | #endif |
---|
| 253 | nclistpush(conflicts,(ncelem)dim); |
---|
| 254 | } |
---|
| 255 | /* Give all the conflicting dimensions an index */ |
---|
| 256 | for(j=0;j<nclistlength(conflicts);j++) { |
---|
| 257 | CDFnode* dim = (CDFnode*)nclistget(conflicts,j); |
---|
| 258 | dim->dim.index1 = j+1; |
---|
| 259 | } |
---|
| 260 | } |
---|
| 261 | nclistfree(conflicts); |
---|
| 262 | |
---|
| 263 | /* Replace all non-base dimensions with their base dimension */ |
---|
| 264 | for(i=0;i<nclistlength(varnodes);i++) { |
---|
| 265 | CDFnode* node = (CDFnode*)nclistget(varnodes,i); |
---|
| 266 | replacedims(node->array.dimsetall); |
---|
| 267 | replacedims(node->array.dimsetplus); |
---|
| 268 | replacedims(node->array.dimset0); |
---|
| 269 | } |
---|
| 270 | |
---|
| 271 | /* Collect list of all basedims */ |
---|
| 272 | basedims = nclistnew(); |
---|
| 273 | for(i=0;i<nclistlength(alldims);i++) { |
---|
| 274 | CDFnode* dim = (CDFnode*)nclistget(alldims,i); |
---|
| 275 | if(dim->dim.basedim == NULL) { |
---|
| 276 | if(!nclistcontains(basedims,(ncelem)dim)) { |
---|
| 277 | nclistpush(basedims,(ncelem)dim); |
---|
| 278 | } |
---|
| 279 | } |
---|
| 280 | } |
---|
| 281 | |
---|
| 282 | nccomm->cdf.dimnodes = basedims; |
---|
| 283 | |
---|
| 284 | /* cleanup */ |
---|
| 285 | nclistfree(alldims); |
---|
| 286 | |
---|
| 287 | /* Assign ncbasenames and ncfullnames to base dimensions */ |
---|
| 288 | for(i=0;i<nclistlength(basedims);i++) { |
---|
| 289 | CDFnode* dim = (CDFnode*)nclistget(basedims,i); |
---|
| 290 | CDFnode* var = dim->dim.array; |
---|
| 291 | if(dim->dim.basedim != NULL) PANIC1("nonbase basedim: %s\n",dim->ocname); |
---|
| 292 | /* stringdim names are already assigned */ |
---|
| 293 | if(dim->ocname == NULL) { /* anonymous: use the index to compute the name */ |
---|
| 294 | snprintf(tmp,sizeof(tmp),"%s_%d", |
---|
| 295 | var->ncfullname,dim->dim.index1-1); |
---|
| 296 | nullfree(dim->ncbasename); |
---|
| 297 | dim->ncbasename = cdflegalname3(tmp); |
---|
| 298 | nullfree(dim->ncfullname); |
---|
| 299 | dim->ncfullname = nulldup(dim->ncbasename); |
---|
| 300 | } else { /* !anonymous; use index1 if defined */ |
---|
| 301 | char* legalname = cdflegalname3(dim->ocname); |
---|
| 302 | nullfree(dim->ncbasename); |
---|
| 303 | if(dim->dim.index1 > 0) {/* need to fix conflicting names (see above) */ |
---|
| 304 | char sindex[64]; |
---|
| 305 | snprintf(sindex,sizeof(sindex),"_%d",dim->dim.index1); |
---|
| 306 | dim->ncbasename = (char*)malloc(strlen(sindex)+strlen(legalname)+1); |
---|
| 307 | if(dim->ncbasename == NULL) return NC_ENOMEM; |
---|
| 308 | strcpy(dim->ncbasename,legalname); |
---|
| 309 | strcat(dim->ncbasename,sindex); |
---|
| 310 | nullfree(legalname); |
---|
| 311 | } else {/* standard case */ |
---|
| 312 | dim->ncbasename = legalname; |
---|
| 313 | } |
---|
| 314 | nullfree(dim->ncfullname); |
---|
| 315 | dim->ncfullname = nulldup(dim->ncbasename); |
---|
| 316 | } |
---|
| 317 | } |
---|
| 318 | |
---|
| 319 | /* Verify unique and defined names for dimensions*/ |
---|
| 320 | for(i=0;i<nclistlength(basedims);i++) { |
---|
| 321 | CDFnode* dim1 = (CDFnode*)nclistget(basedims,i); |
---|
| 322 | if(dim1->dim.basedim != NULL) PANIC1("nonbase basedim: %s\n",dim1->ncbasename); |
---|
| 323 | if(dim1->ncbasename == NULL || dim1->ncfullname == NULL) |
---|
| 324 | PANIC1("missing dim names: %s",dim1->ocname); |
---|
| 325 | /* search backward so we can delete duplicates */ |
---|
| 326 | for(j=nclistlength(basedims)-1;j>i;j--) { |
---|
| 327 | CDFnode* dim2 = (CDFnode*)nclistget(basedims,j); |
---|
| 328 | if(strcmp(dim1->ncfullname,dim2->ncfullname)==0) { |
---|
| 329 | /* complain and suppress one of them */ |
---|
| 330 | fprintf(stderr,"duplicate dim names: %s[%lu] %s[%lu]\n", |
---|
| 331 | dim1->ncfullname,(unsigned long)dim1->dim.declsize, |
---|
| 332 | dim2->ncfullname,(unsigned long)dim2->dim.declsize); |
---|
| 333 | nclistremove(basedims,j); |
---|
| 334 | } |
---|
| 335 | } |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | #ifdef DEBUG |
---|
| 339 | for(i=0;i<nclistlength(basedims);i++) { |
---|
| 340 | CDFnode* dim = (CDFnode*)nclistget(basedims,i); |
---|
| 341 | fprintf(stderr,"basedim: %s=%ld\n",dim->ncfullname,(long)dim->dim.declsize); |
---|
| 342 | } |
---|
| 343 | #endif |
---|
| 344 | |
---|
| 345 | return NC_NOERR; |
---|
| 346 | } |
---|
| 347 | |
---|
| 348 | NCerror |
---|
| 349 | makegetvar34(NCDAPCOMMON* nccomm, CDFnode* var, void* data, nc_type dsttype, Getvara** getvarp) |
---|
| 350 | { |
---|
| 351 | Getvara* getvar; |
---|
| 352 | NCerror ncstat = NC_NOERR; |
---|
| 353 | |
---|
| 354 | getvar = (Getvara*)calloc(1,sizeof(Getvara)); |
---|
| 355 | MEMCHECK(getvar,NC_ENOMEM); |
---|
| 356 | if(getvarp) *getvarp = getvar; |
---|
| 357 | |
---|
| 358 | getvar->target = var; |
---|
| 359 | getvar->memory = data; |
---|
| 360 | getvar->dsttype = dsttype; |
---|
| 361 | getvar->target = var; |
---|
| 362 | if(ncstat) nullfree(getvar); |
---|
| 363 | return ncstat; |
---|
| 364 | } |
---|
| 365 | |
---|
| 366 | int |
---|
| 367 | constrainable34(NC_URI* durl) |
---|
| 368 | { |
---|
| 369 | char** protocol = constrainableprotocols; |
---|
| 370 | for(;*protocol;protocol++) { |
---|
| 371 | if(strcmp(durl->protocol,*protocol)==0) |
---|
| 372 | return 1; |
---|
| 373 | } |
---|
| 374 | return 0; |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | CDFnode* |
---|
| 378 | makecdfnode34(NCDAPCOMMON* nccomm, char* name, OCtype octype, |
---|
| 379 | /*optional*/ OCobject ocnode, CDFnode* container) |
---|
| 380 | { |
---|
| 381 | CDFnode* node; |
---|
| 382 | assert(nccomm != NULL); |
---|
| 383 | node = (CDFnode*)calloc(1,sizeof(CDFnode)); |
---|
| 384 | if(node == NULL) return (CDFnode*)NULL; |
---|
| 385 | |
---|
| 386 | node->ocname = NULL; |
---|
| 387 | if(name) { |
---|
| 388 | size_t len = strlen(name); |
---|
| 389 | if(len >= NC_MAX_NAME) len = NC_MAX_NAME-1; |
---|
| 390 | node->ocname = (char*)malloc(len+1); |
---|
| 391 | if(node->ocname == NULL) return NULL; |
---|
| 392 | memcpy(node->ocname,name,len); |
---|
| 393 | node->ocname[len] = '\0'; |
---|
| 394 | } |
---|
| 395 | node->nctype = octypetonc(octype); |
---|
| 396 | node->ocnode = ocnode; |
---|
| 397 | node->subnodes = nclistnew(); |
---|
| 398 | node->container = container; |
---|
| 399 | if(ocnode != OCNULL) { |
---|
| 400 | oc_inq_primtype(nccomm->oc.conn,ocnode,&octype); |
---|
| 401 | node->etype = octypetonc(octype); |
---|
| 402 | } |
---|
| 403 | return node; |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | /* Given an OCnode tree, mimic it as a CDFnode tree; |
---|
| 407 | Add DAS attributes if DAS is available. Accumulate set |
---|
| 408 | of all nodes in preorder. |
---|
| 409 | */ |
---|
| 410 | NCerror |
---|
| 411 | buildcdftree34(NCDAPCOMMON* nccomm, OCobject ocroot, OCdxd occlass, CDFnode** cdfrootp) |
---|
| 412 | { |
---|
| 413 | CDFnode* root = NULL; |
---|
| 414 | CDFtree* tree = (CDFtree*)calloc(1,sizeof(CDFtree)); |
---|
| 415 | NCerror err = NC_NOERR; |
---|
| 416 | tree->ocroot = ocroot; |
---|
| 417 | tree->nodes = nclistnew(); |
---|
| 418 | tree->occlass = occlass; |
---|
| 419 | tree->owner = nccomm; |
---|
| 420 | |
---|
| 421 | err = buildcdftree34r(nccomm,ocroot,NULL,tree,&root); |
---|
| 422 | if(!err) { |
---|
| 423 | if(occlass != OCDAS) |
---|
| 424 | fixnodes34(nccomm,tree->nodes); |
---|
| 425 | if(cdfrootp) *cdfrootp = root; |
---|
| 426 | } |
---|
| 427 | return err; |
---|
| 428 | } |
---|
| 429 | |
---|
| 430 | static NCerror |
---|
| 431 | buildcdftree34r(NCDAPCOMMON* nccomm, OCobject ocnode, CDFnode* container, |
---|
| 432 | CDFtree* tree, CDFnode** cdfnodep) |
---|
| 433 | { |
---|
| 434 | unsigned int i,ocrank,ocnsubnodes; |
---|
| 435 | OCtype octype; |
---|
| 436 | char* ocname = NULL; |
---|
| 437 | NCerror ncerr = NC_NOERR; |
---|
| 438 | CDFnode* cdfnode; |
---|
| 439 | |
---|
| 440 | oc_inq_class(nccomm->oc.conn,ocnode,&octype); |
---|
| 441 | oc_inq_name(nccomm->oc.conn,ocnode,&ocname); |
---|
| 442 | oc_inq_rank(nccomm->oc.conn,ocnode,&ocrank); |
---|
| 443 | oc_inq_nsubnodes(nccomm->oc.conn,ocnode,&ocnsubnodes); |
---|
| 444 | |
---|
| 445 | switch (octype) { |
---|
| 446 | case OC_Dataset: |
---|
| 447 | case OC_Grid: |
---|
| 448 | case OC_Structure: |
---|
| 449 | case OC_Sequence: |
---|
| 450 | case OC_Primitive: |
---|
| 451 | cdfnode = makecdfnode34(nccomm,ocname,octype,ocnode,container); |
---|
| 452 | nclistpush(tree->nodes,(ncelem)cdfnode); |
---|
| 453 | if(tree->root == NULL) { |
---|
| 454 | tree->root = cdfnode; |
---|
| 455 | cdfnode->tree = tree; |
---|
| 456 | } |
---|
| 457 | break; |
---|
| 458 | |
---|
| 459 | case OC_Dimension: |
---|
| 460 | default: PANIC1("buildcdftree: unexpect OC node type: %d",(int)octype); |
---|
| 461 | |
---|
| 462 | } |
---|
| 463 | /* cross link */ |
---|
| 464 | cdfnode->root = tree->root; |
---|
| 465 | |
---|
| 466 | if(ocrank > 0) defdimensions(ocnode,cdfnode,nccomm,tree); |
---|
| 467 | for(i=0;i<ocnsubnodes;i++) { |
---|
| 468 | OCobject ocsubnode; |
---|
| 469 | CDFnode* subnode; |
---|
| 470 | oc_inq_ith(nccomm->oc.conn,ocnode,i,&ocsubnode); |
---|
| 471 | ncerr = buildcdftree34r(nccomm,ocsubnode,cdfnode,tree,&subnode); |
---|
| 472 | if(ncerr) return ncerr; |
---|
| 473 | nclistpush(cdfnode->subnodes,(ncelem)subnode); |
---|
| 474 | } |
---|
| 475 | nullfree(ocname); |
---|
| 476 | if(cdfnodep) *cdfnodep = cdfnode; |
---|
| 477 | return ncerr; |
---|
| 478 | } |
---|
| 479 | |
---|
| 480 | static void |
---|
| 481 | defdimensions(OCobject ocnode, CDFnode* cdfnode, NCDAPCOMMON* nccomm, CDFtree* tree) |
---|
| 482 | { |
---|
| 483 | unsigned int i,ocrank; |
---|
| 484 | |
---|
| 485 | oc_inq_rank(nccomm->oc.conn,ocnode,&ocrank); |
---|
| 486 | assert(ocrank > 0); |
---|
| 487 | for(i=0;i<ocrank;i++) { |
---|
| 488 | CDFnode* cdfdim; |
---|
| 489 | OCobject ocdim; |
---|
| 490 | char* ocname; |
---|
| 491 | size_t declsize; |
---|
| 492 | |
---|
| 493 | oc_inq_ithdim(nccomm->oc.conn,ocnode,i,&ocdim); |
---|
| 494 | oc_inq_dim(nccomm->oc.conn,ocdim,&declsize,&ocname); |
---|
| 495 | |
---|
| 496 | cdfdim = makecdfnode34(nccomm,ocname,OC_Dimension, |
---|
| 497 | ocdim,cdfnode->container); |
---|
| 498 | nullfree(ocname); |
---|
| 499 | nclistpush(tree->nodes,(ncelem)cdfdim); |
---|
| 500 | /* Initially, constrained and unconstrained are same */ |
---|
| 501 | cdfdim->dim.declsize = declsize; |
---|
| 502 | cdfdim->dim.array = cdfnode; |
---|
| 503 | if(cdfnode->array.dimset0 == NULL) |
---|
| 504 | cdfnode->array.dimset0 = nclistnew(); |
---|
| 505 | nclistpush(cdfnode->array.dimset0,(ncelem)cdfdim); |
---|
| 506 | } |
---|
| 507 | } |
---|
| 508 | |
---|
| 509 | /* Note: this routine only applies some common |
---|
| 510 | client parameters, other routines may apply |
---|
| 511 | specific ones. |
---|
| 512 | */ |
---|
| 513 | |
---|
| 514 | NCerror |
---|
| 515 | applyclientparams34(NCDAPCOMMON* nccomm) |
---|
| 516 | { |
---|
| 517 | int i,len; |
---|
| 518 | int dfaltstrlen = DEFAULTSTRINGLENGTH; |
---|
| 519 | int dfaltseqlim = DEFAULTSEQLIMIT; |
---|
| 520 | const char* value; |
---|
| 521 | char tmpname[NC_MAX_NAME+32]; |
---|
| 522 | char* pathstr; |
---|
| 523 | OCconnection conn = nccomm->oc.conn; |
---|
| 524 | unsigned long limit; |
---|
| 525 | |
---|
| 526 | ASSERT(nccomm->oc.url != NULL); |
---|
| 527 | |
---|
| 528 | nccomm->cdf.cache->cachelimit = DFALTCACHELIMIT; |
---|
| 529 | value = oc_clientparam_get(conn,"cachelimit"); |
---|
| 530 | limit = getlimitnumber(value); |
---|
| 531 | if(limit > 0) nccomm->cdf.cache->cachelimit = limit; |
---|
| 532 | |
---|
| 533 | nccomm->cdf.fetchlimit = DFALTFETCHLIMIT; |
---|
| 534 | value = oc_clientparam_get(conn,"fetchlimit"); |
---|
| 535 | limit = getlimitnumber(value); |
---|
| 536 | if(limit > 0) nccomm->cdf.fetchlimit = limit; |
---|
| 537 | |
---|
| 538 | nccomm->cdf.smallsizelimit = DFALTSMALLLIMIT; |
---|
| 539 | value = oc_clientparam_get(conn,"smallsizelimit"); |
---|
| 540 | limit = getlimitnumber(value); |
---|
| 541 | if(limit > 0) nccomm->cdf.smallsizelimit = limit; |
---|
| 542 | |
---|
| 543 | nccomm->cdf.cache->cachecount = DFALTCACHECOUNT; |
---|
| 544 | #ifdef HAVE_GETRLIMIT |
---|
| 545 | { struct rlimit rl; |
---|
| 546 | if(getrlimit(RLIMIT_NOFILE, &rl) >= 0) { |
---|
| 547 | nccomm->cdf.cache->cachecount = (size_t)(rl.rlim_cur / 2); |
---|
| 548 | } |
---|
| 549 | } |
---|
| 550 | #endif |
---|
| 551 | value = oc_clientparam_get(conn,"cachecount"); |
---|
| 552 | limit = getlimitnumber(value); |
---|
| 553 | if(limit > 0) nccomm->cdf.cache->cachecount = limit; |
---|
| 554 | /* Ignore limit if not caching */ |
---|
| 555 | if(!FLAGSET(nccomm->controls,NCF_CACHE)) |
---|
| 556 | nccomm->cdf.cache->cachecount = 0; |
---|
| 557 | |
---|
| 558 | if(oc_clientparam_get(conn,"nolimit") != NULL) |
---|
| 559 | dfaltseqlim = 0; |
---|
| 560 | value = oc_clientparam_get(conn,"limit"); |
---|
| 561 | if(value != NULL && strlen(value) != 0) { |
---|
| 562 | if(sscanf(value,"%d",&len) && len > 0) dfaltseqlim = len; |
---|
| 563 | } |
---|
| 564 | nccomm->cdf.defaultsequencelimit = dfaltseqlim; |
---|
| 565 | |
---|
| 566 | /* allow embedded _ */ |
---|
| 567 | value = oc_clientparam_get(conn,"stringlength"); |
---|
| 568 | if(value != NULL && strlen(value) != 0) { |
---|
| 569 | if(sscanf(value,"%d",&len) && len > 0) dfaltstrlen = len; |
---|
| 570 | } |
---|
| 571 | nccomm->cdf.defaultstringlength = dfaltstrlen; |
---|
| 572 | |
---|
| 573 | /* String dimension limits apply to variables */ |
---|
| 574 | for(i=0;i<nclistlength(nccomm->cdf.varnodes);i++) { |
---|
| 575 | CDFnode* var = (CDFnode*)nclistget(nccomm->cdf.varnodes,i); |
---|
| 576 | /* Define the client param stringlength for this variable*/ |
---|
| 577 | var->maxstringlength = 0; /* => use global dfalt */ |
---|
| 578 | strcpy(tmpname,"stringlength_"); |
---|
| 579 | pathstr = makeocpathstring3(conn,var->ocnode,"."); |
---|
| 580 | strcat(tmpname,pathstr); |
---|
| 581 | nullfree(pathstr); |
---|
| 582 | value = oc_clientparam_get(conn,tmpname); |
---|
| 583 | if(value != NULL && strlen(value) != 0) { |
---|
| 584 | if(sscanf(value,"%d",&len) && len > 0) var->maxstringlength = len; |
---|
| 585 | } |
---|
| 586 | } |
---|
| 587 | /* Sequence limits apply to sequences */ |
---|
| 588 | for(i=0;i<nclistlength(nccomm->cdf.ddsroot->tree->nodes);i++) { |
---|
| 589 | CDFnode* var = (CDFnode*)nclistget(nccomm->cdf.ddsroot->tree->nodes,i); |
---|
| 590 | if(var->nctype != NC_Sequence) continue; |
---|
| 591 | var->sequencelimit = dfaltseqlim; |
---|
| 592 | strcpy(tmpname,"nolimit_"); |
---|
| 593 | pathstr = makeocpathstring3(conn,var->ocnode,"."); |
---|
| 594 | strcat(tmpname,pathstr); |
---|
| 595 | if(oc_clientparam_get(conn,tmpname) != NULL) |
---|
| 596 | var->sequencelimit = 0; |
---|
| 597 | strcpy(tmpname,"limit_"); |
---|
| 598 | strcat(tmpname,pathstr); |
---|
| 599 | value = oc_clientparam_get(conn,tmpname); |
---|
| 600 | if(value != NULL && strlen(value) != 0) { |
---|
| 601 | if(sscanf(value,"%d",&len) && len > 0) |
---|
| 602 | var->sequencelimit = len; |
---|
| 603 | } |
---|
| 604 | nullfree(pathstr); |
---|
| 605 | } |
---|
| 606 | |
---|
| 607 | /* test for the appropriate fetch flags */ |
---|
| 608 | value = oc_clientparam_get(conn,"fetch"); |
---|
| 609 | if(value != NULL && strlen(value) > 0) { |
---|
| 610 | if(value[0] == 'd' || value[0] == 'D') { |
---|
| 611 | SETFLAG(nccomm->controls,NCF_ONDISK); |
---|
| 612 | } |
---|
| 613 | } |
---|
| 614 | |
---|
| 615 | /* test for the force-whole-var flag */ |
---|
| 616 | value = oc_clientparam_get(conn,"wholevar"); |
---|
| 617 | if(value != NULL) { |
---|
| 618 | SETFLAG(nccomm->controls,NCF_WHOLEVAR); |
---|
| 619 | } |
---|
| 620 | |
---|
| 621 | return NC_NOERR; |
---|
| 622 | } |
---|
| 623 | |
---|
| 624 | void |
---|
| 625 | freecdfroot34(CDFnode* root) |
---|
| 626 | { |
---|
| 627 | int i; |
---|
| 628 | CDFtree* tree; |
---|
| 629 | NCDAPCOMMON* nccomm; |
---|
| 630 | if(root == NULL) return; |
---|
| 631 | tree = root->tree; |
---|
| 632 | ASSERT((tree != NULL)); |
---|
| 633 | /* Explicitly FREE the ocroot */ |
---|
| 634 | nccomm = tree->owner; |
---|
| 635 | oc_root_free(nccomm->oc.conn,tree->ocroot); |
---|
| 636 | tree->ocroot = OCNULL; |
---|
| 637 | for(i=0;i<nclistlength(tree->nodes);i++) { |
---|
| 638 | CDFnode* node = (CDFnode*)nclistget(tree->nodes,i); |
---|
| 639 | free1cdfnode34(node); |
---|
| 640 | } |
---|
| 641 | nclistfree(tree->nodes); |
---|
| 642 | nullfree(tree); |
---|
| 643 | } |
---|
| 644 | |
---|
| 645 | /* Free up a single node, but not any |
---|
| 646 | nodes it points to. |
---|
| 647 | */ |
---|
| 648 | static void |
---|
| 649 | free1cdfnode34(CDFnode* node) |
---|
| 650 | { |
---|
| 651 | unsigned int j,k; |
---|
| 652 | if(node == NULL) return; |
---|
| 653 | nullfree(node->ocname); |
---|
| 654 | nullfree(node->ncbasename); |
---|
| 655 | nullfree(node->ncfullname); |
---|
| 656 | if(node->attributes != NULL) { |
---|
| 657 | for(j=0;j<nclistlength(node->attributes);j++) { |
---|
| 658 | NCattribute* att = (NCattribute*)nclistget(node->attributes,j); |
---|
| 659 | nullfree(att->name); |
---|
| 660 | for(k=0;k<nclistlength(att->values);k++) |
---|
| 661 | nullfree((char*)nclistget(att->values,k)); |
---|
| 662 | nclistfree(att->values); |
---|
| 663 | nullfree(att); |
---|
| 664 | } |
---|
| 665 | } |
---|
| 666 | nullfree(node->dodsspecial.dimname); |
---|
| 667 | nclistfree(node->subnodes); |
---|
| 668 | nclistfree(node->attributes); |
---|
| 669 | nclistfree(node->array.dimsetplus); |
---|
| 670 | nclistfree(node->array.dimsetall); |
---|
| 671 | nclistfree(node->array.dimset0); |
---|
| 672 | |
---|
| 673 | /* Clean up the ncdap4 fields also */ |
---|
| 674 | nullfree(node->typename); |
---|
| 675 | nullfree(node->vlenname); |
---|
| 676 | nullfree(node); |
---|
| 677 | } |
---|
| 678 | |
---|
| 679 | /* Return true if node and node1 appear to refer to the same thing; |
---|
| 680 | takes grid->structure changes into account. |
---|
| 681 | */ |
---|
| 682 | int |
---|
| 683 | nodematch34(CDFnode* node1, CDFnode* node2) |
---|
| 684 | { |
---|
| 685 | return simplenodematch34(node1,node2); |
---|
| 686 | } |
---|
| 687 | |
---|
| 688 | int |
---|
| 689 | simplenodematch34(CDFnode* node1, CDFnode* node2) |
---|
| 690 | { |
---|
| 691 | if(node1 == NULL) return (node2==NULL); |
---|
| 692 | if(node2 == NULL) return 0; |
---|
| 693 | if(node1->nctype != node2->nctype) { |
---|
| 694 | /* Check for Grid->Structure match */ |
---|
| 695 | if((node1->nctype == NC_Structure && node2->nctype == NC_Grid) |
---|
| 696 | || (node2->nctype == NC_Structure && node1->nctype == NC_Grid)){ |
---|
| 697 | if(node1->ocname == NULL || node2->ocname == NULL |
---|
| 698 | || strcmp(node1->ocname,node2->ocname) !=0) return 0; |
---|
| 699 | } else return 0; |
---|
| 700 | } |
---|
| 701 | /* Add hack to address the screwed up Columbia server */ |
---|
| 702 | if(node1->nctype == NC_Dataset) return 1; |
---|
| 703 | if(node1->nctype == NC_Primitive |
---|
| 704 | && node1->etype != node2->etype) return 0; |
---|
| 705 | if(node1->ocname != NULL && node2->ocname != NULL |
---|
| 706 | && strcmp(node1->ocname,node2->ocname)!=0) return 0; |
---|
| 707 | if(nclistlength(node1->array.dimset0) |
---|
| 708 | != nclistlength(node2->array.dimset0)) return 0; |
---|
| 709 | return 1; |
---|
| 710 | } |
---|
| 711 | |
---|
| 712 | /* |
---|
| 713 | Given DDS node, locate the node |
---|
| 714 | in a DATADDS that matches the DDS node. |
---|
| 715 | Return NULL if no node found |
---|
| 716 | */ |
---|
| 717 | |
---|
| 718 | void |
---|
| 719 | unattach34(CDFnode* root) |
---|
| 720 | { |
---|
| 721 | unsigned int i; |
---|
| 722 | CDFtree* xtree = root->tree; |
---|
| 723 | for(i=0;i<nclistlength(xtree->nodes);i++) { |
---|
| 724 | CDFnode* xnode = (CDFnode*)nclistget(xtree->nodes,i); |
---|
| 725 | /* break bi-directional link */ |
---|
| 726 | xnode->attachment = NULL; |
---|
| 727 | } |
---|
| 728 | } |
---|
| 729 | |
---|
| 730 | static void |
---|
| 731 | setattach(CDFnode* target, CDFnode* template) |
---|
| 732 | { |
---|
| 733 | target->attachment = template; |
---|
| 734 | template->attachment = target; |
---|
| 735 | /* Transfer important information */ |
---|
| 736 | target->externaltype = template->externaltype; |
---|
| 737 | target->maxstringlength = template->maxstringlength; |
---|
| 738 | target->sequencelimit = template->sequencelimit; |
---|
| 739 | target->ncid = template->ncid; |
---|
| 740 | /* also transfer libncdap4 info */ |
---|
| 741 | target->typeid = template->typeid; |
---|
| 742 | target->typesize = template->typesize; |
---|
| 743 | } |
---|
| 744 | |
---|
| 745 | static NCerror |
---|
| 746 | attachdims34(CDFnode* xnode, CDFnode* template) |
---|
| 747 | { |
---|
| 748 | unsigned int i; |
---|
| 749 | for(i=0;i<nclistlength(xnode->array.dimsetall);i++) { |
---|
| 750 | CDFnode* xdim = (CDFnode*)nclistget(xnode->array.dimsetall,i); |
---|
| 751 | CDFnode* tdim = (CDFnode*)nclistget(template->array.dimsetall,i); |
---|
| 752 | setattach(xdim,tdim); |
---|
| 753 | #ifdef DEBUG2 |
---|
| 754 | fprintf(stderr,"attachdim: %s->%s\n",xdim->ocname,tdim->ocname); |
---|
| 755 | #endif |
---|
| 756 | } |
---|
| 757 | return NC_NOERR; |
---|
| 758 | } |
---|
| 759 | |
---|
| 760 | /* |
---|
| 761 | Match a DATADDS node to a DDS node. |
---|
| 762 | It is assumed that both trees have been regridded if necessary. |
---|
| 763 | */ |
---|
| 764 | |
---|
| 765 | static NCerror |
---|
| 766 | attach34r(CDFnode* xnode, NClist* templatepath, int depth) |
---|
| 767 | { |
---|
| 768 | unsigned int i,plen,lastnode,gridable; |
---|
| 769 | NCerror ncstat = NC_NOERR; |
---|
| 770 | CDFnode* templatepathnode; |
---|
| 771 | CDFnode* templatepathnext; |
---|
| 772 | |
---|
| 773 | plen = nclistlength(templatepath); |
---|
| 774 | if(depth >= plen) {THROWCHK(ncstat=NC_EINVAL); goto done;} |
---|
| 775 | |
---|
| 776 | lastnode = (depth == (plen-1)); |
---|
| 777 | templatepathnode = (CDFnode*)nclistget(templatepath,depth); |
---|
| 778 | ASSERT((simplenodematch34(xnode,templatepathnode))); |
---|
| 779 | setattach(xnode,templatepathnode); |
---|
| 780 | #ifdef DEBUG2 |
---|
| 781 | fprintf(stderr,"attachnode: %s->%s\n",xnode->ocname,templatepathnode->ocname); |
---|
| 782 | #endif |
---|
| 783 | |
---|
| 784 | if(lastnode) goto done; /* We have the match and are done */ |
---|
| 785 | |
---|
| 786 | if(nclistlength(xnode->array.dimsetall) > 0) { |
---|
| 787 | attachdims34(xnode,templatepathnode); |
---|
| 788 | } |
---|
| 789 | |
---|
| 790 | ASSERT((!lastnode)); |
---|
| 791 | templatepathnext = (CDFnode*)nclistget(templatepath,depth+1); |
---|
| 792 | |
---|
| 793 | gridable = (templatepathnext->nctype == NC_Grid && depth+2 < plen); |
---|
| 794 | |
---|
| 795 | /* Try to find an xnode subnode that matches templatepathnext */ |
---|
| 796 | for(i=0;i<nclistlength(xnode->subnodes);i++) { |
---|
| 797 | CDFnode* xsubnode = (CDFnode*)nclistget(xnode->subnodes,i); |
---|
| 798 | if(simplenodematch34(xsubnode,templatepathnext)) { |
---|
| 799 | ncstat = attach34r(xsubnode,templatepath,depth+1); |
---|
| 800 | if(ncstat) goto done; |
---|
| 801 | } else if(gridable && xsubnode->nctype == NC_Primitive) { |
---|
| 802 | /* grids may or may not appear in the datadds; |
---|
| 803 | try to match the xnode subnodes against the parts of the grid |
---|
| 804 | */ |
---|
| 805 | CDFnode* templatepathnext2 = (CDFnode*)nclistget(templatepath,depth+2); |
---|
| 806 | if(simplenodematch34(xsubnode,templatepathnext2)) { |
---|
| 807 | ncstat = attach34r(xsubnode,templatepath,depth+2); |
---|
| 808 | if(ncstat) goto done; |
---|
| 809 | } |
---|
| 810 | } |
---|
| 811 | } |
---|
| 812 | done: |
---|
| 813 | return THROW(ncstat); |
---|
| 814 | } |
---|
| 815 | |
---|
| 816 | NCerror |
---|
| 817 | attach34(CDFnode* xroot, CDFnode* template) |
---|
| 818 | { |
---|
| 819 | NCerror ncstat = NC_NOERR; |
---|
| 820 | NClist* templatepath = nclistnew(); |
---|
| 821 | CDFnode* ddsroot = template->root; |
---|
| 822 | |
---|
| 823 | if(xroot->attachment) unattach34(xroot); |
---|
| 824 | if(ddsroot != NULL && ddsroot->attachment) unattach34(ddsroot); |
---|
| 825 | if(!simplenodematch34(xroot,ddsroot)) |
---|
| 826 | {THROWCHK(ncstat=NC_EINVAL); goto done;} |
---|
| 827 | collectnodepath3(template,templatepath,WITHDATASET); |
---|
| 828 | ncstat = attach34r(xroot,templatepath,0); |
---|
| 829 | done: |
---|
| 830 | nclistfree(templatepath); |
---|
| 831 | return ncstat; |
---|
| 832 | } |
---|
| 833 | |
---|
| 834 | /* |
---|
| 835 | Match nodes in template tree to nodes in target tree; |
---|
| 836 | template tree is typically a structural superset of target tree. |
---|
| 837 | WARNING: Dimensions are not attached |
---|
| 838 | */ |
---|
| 839 | |
---|
| 840 | NCerror |
---|
| 841 | attachsubset34(CDFnode* target, CDFnode* template) |
---|
| 842 | { |
---|
| 843 | NCerror ncstat = NC_NOERR; |
---|
| 844 | |
---|
| 845 | if(template == NULL) {THROWCHK(ncstat=NC_NOERR); goto done;} |
---|
| 846 | if(!nodematch34(target,template)) {THROWCHK(ncstat=NC_EINVAL); goto done;} |
---|
| 847 | #ifdef DEBUG2 |
---|
| 848 | fprintf(stderr,"attachsubset: target=%s\n",dumptree(target)); |
---|
| 849 | fprintf(stderr,"attachsubset: template=%s\n",dumptree(template)); |
---|
| 850 | #endif |
---|
| 851 | ncstat = attachsubset34r(target,template); |
---|
| 852 | done: |
---|
| 853 | return ncstat; |
---|
| 854 | } |
---|
| 855 | |
---|
| 856 | static NCerror |
---|
| 857 | attachsubset34r(CDFnode* target, CDFnode* template) |
---|
| 858 | { |
---|
| 859 | unsigned int i; |
---|
| 860 | NCerror ncstat = NC_NOERR; |
---|
| 861 | int fieldindex; |
---|
| 862 | |
---|
| 863 | #ifdef DEBUG2 |
---|
| 864 | fprintf(stderr,"attachsubsetr: attach: target=%s template=%s\n", |
---|
| 865 | target->ocname,template->ocname); |
---|
| 866 | #endif |
---|
| 867 | |
---|
| 868 | ASSERT((nodematch34(target,template))); |
---|
| 869 | setattach(target,template); |
---|
| 870 | |
---|
| 871 | /* Try to match target subnodes against template subnodes */ |
---|
| 872 | |
---|
| 873 | fieldindex = 0; |
---|
| 874 | for(fieldindex=0,i=0;i<nclistlength(template->subnodes) && fieldindex<nclistlength(target->subnodes);i++) { |
---|
| 875 | CDFnode* templatesubnode = (CDFnode*)nclistget(template->subnodes,i); |
---|
| 876 | CDFnode* targetsubnode = (CDFnode*)nclistget(target->subnodes,fieldindex); |
---|
| 877 | if(nodematch34(targetsubnode,templatesubnode)) { |
---|
| 878 | #ifdef DEBUG2 |
---|
| 879 | fprintf(stderr,"attachsubsetr: match: %s :: %s\n",targetsubnode->ocname,templatesubnode->ocname); |
---|
| 880 | #endif |
---|
| 881 | ncstat = attachsubset34r(targetsubnode,templatesubnode); |
---|
| 882 | if(ncstat) goto done; |
---|
| 883 | fieldindex++; |
---|
| 884 | } |
---|
| 885 | } |
---|
| 886 | done: |
---|
| 887 | return THROW(ncstat); |
---|
| 888 | } |
---|
| 889 | |
---|
| 890 | static void |
---|
| 891 | getalldims34a(NClist* dimset, NClist* alldims) |
---|
| 892 | { |
---|
| 893 | int i; |
---|
| 894 | for(i=0;i<nclistlength(dimset);i++) { |
---|
| 895 | CDFnode* dim = (CDFnode*)nclistget(dimset,i); |
---|
| 896 | if(!nclistcontains(alldims,(ncelem)dim)) { |
---|
| 897 | #ifdef DEBUG3 |
---|
| 898 | fprintf(stderr,"getalldims: %s[%lu]\n", |
---|
| 899 | dim->ncfullname,(unsigned long)dim->dim.declsize); |
---|
| 900 | #endif |
---|
| 901 | nclistpush(alldims,(ncelem)dim); |
---|
| 902 | } |
---|
| 903 | } |
---|
| 904 | } |
---|
| 905 | |
---|
| 906 | /* Accumulate a set of all the known dimensions |
---|
| 907 | vis-a-vis defined variables |
---|
| 908 | */ |
---|
| 909 | NClist* |
---|
| 910 | getalldims34(NCDAPCOMMON* nccomm, int visibleonly) |
---|
| 911 | { |
---|
| 912 | int i; |
---|
| 913 | NClist* alldims = nclistnew(); |
---|
| 914 | NClist* varnodes = nccomm->cdf.varnodes; |
---|
| 915 | |
---|
| 916 | /* get bag of all dimensions */ |
---|
| 917 | for(i=0;i<nclistlength(varnodes);i++) { |
---|
| 918 | CDFnode* node = (CDFnode*)nclistget(varnodes,i); |
---|
| 919 | if(!visibleonly || node->visible) { |
---|
| 920 | getalldims34a(node->array.dimsetall,alldims); |
---|
| 921 | } |
---|
| 922 | } |
---|
| 923 | return alldims; |
---|
| 924 | } |
---|