From a7ecaeb327e540abf4d44595f4d5d991cdf00609 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 17 Aug 2013 12:53:29 -0500 Subject: [PATCH 01/21] Work in progress on NCF-177. --- libsrc4/nc4dim.c | 12 ++++++--- libsrc4/nc4file.c | 4 +++ libsrc4/nc4hdf.c | 62 +++++++++++++++++++++---------------------- libsrc4/nc4internal.c | 17 +++++++----- 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/libsrc4/nc4dim.c b/libsrc4/nc4dim.c index 0e8aa8562..f53fed4c2 100644 --- a/libsrc4/nc4dim.c +++ b/libsrc4/nc4dim.c @@ -333,14 +333,18 @@ NC4_rename_dim(int ncid, int dimid, const char *name) * data... */ if (!dim->old_name) { - if (!(dim->old_name = malloc((strlen(dim->name) + 1) * sizeof(char)))) - return NC_ENOMEM; - strcpy(dim->old_name, dim->name); + dim->old_name = dim->name; + dim->name = NULL; } + /* Check if this is a coordinate variable, and if so, mark it dirty */ + if (dim->coord_var) + dim->coord_var->dirty++; + /* Give the dimension its new name in metadata. UTF8 normalization * has been done. */ - free(dim->name); + if(dim->name) + free(dim->name); if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char)))) return NC_ENOMEM; strcpy(dim->name, norm_name); diff --git a/libsrc4/nc4file.c b/libsrc4/nc4file.c index e792b558f..8a4a60e2c 100644 --- a/libsrc4/nc4file.c +++ b/libsrc4/nc4file.c @@ -1488,6 +1488,10 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, { var->dimids[0] = grp->dim->dimid; var->dim[0] = grp->dim; + if(0 == strcmp(var->name, grp->dim->name)) { + grp->dim->coord_var = var; + grp->dim->coord_var_in_grp++; + } /* end if */ } } else diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index 439f3783f..996342625 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -1427,7 +1427,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) * has not specified chunksizes, use contiguous variable for * better performance. */ if (!unlimdim && !var->shuffle && !var->deflate && !var->options_mask && - !var->fletcher32 && !var->chunksizes[0]) + !var->fletcher32 && (var->chunksizes == NULL || !var->chunksizes[0])) var->contiguous = 1; if (!(dimsize = malloc(var->ndims * sizeof(hsize_t)))) @@ -1436,10 +1436,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) BAIL(NC_ENOMEM); if (!(chunksize = malloc(var->ndims * sizeof(hsize_t)))) BAIL(NC_ENOMEM); -/* for (d = 0; d < var->ndims; d++) - dimsize[d] = var->dim[d]->unlimited ? NC_HDF5_UNLIMITED_DIMSIZE : var->dim[d]->len; - maxdimsize[d] = var->dim[d]->unlimited ? H5S_UNLIMITED : (hsize_t)var->dim[d]->len; - chunksize[d] = var->chunksizes[d];*/ for (d = 0; d < var->ndims; d++) { @@ -1451,28 +1447,30 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) { dimsize[d] = dim->unlimited ? NC_HDF5_UNLIMITED_DIMSIZE : dim->len; maxdimsize[d] = dim->unlimited ? H5S_UNLIMITED : (hsize_t)dim->len; - if (var->chunksizes[d]) - chunksize[d] = var->chunksizes[d]; - else - { - size_t type_size; - if (var->type_info->nc_typeid == NC_STRING) - type_size = sizeof(char *); - else - type_size = var->type_info->size; - - /* Unlimited dim always gets chunksize of 1. */ - if (dim->unlimited) - chunksize[d] = 1; - else - chunksize[d] = pow((double)DEFAULT_CHUNK_SIZE/type_size, - 1/(double)(var->ndims - unlimdim)); - - /* If the chunksize is greater than the dim - * length, make it the dim length. */ - if (!dim->unlimited && chunksize[d] > dim->len) - chunksize[d] = dim->len; - set_chunksizes++; + if (!var->contiguous) { + if (var->chunksizes[d]) + chunksize[d] = var->chunksizes[d]; + else + { + size_t type_size; + if (var->type_info->nc_typeid == NC_STRING) + type_size = sizeof(char *); + else + type_size = var->type_info->size; + + /* Unlimited dim always gets chunksize of 1. */ + if (dim->unlimited) + chunksize[d] = 1; + else + chunksize[d] = pow((double)DEFAULT_CHUNK_SIZE/type_size, + 1/(double)(var->ndims - unlimdim)); + + /* If the chunksize is greater than the dim + * length, make it the dim length. */ + if (!dim->unlimited && chunksize[d] > dim->len) + chunksize[d] = dim->len; + set_chunksizes++; + } } if (!var->contiguous && !var->chunksizes[d]) @@ -2250,17 +2248,19 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) for (dim1 = g->dim; dim1; dim1 = dim1->next) if (var->dimids[d] == dim1->dimid) { + if(var->hdf_datasetid != dim1->hdf_dimscaleid) if (H5DSdetach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0) BAIL(NC_EHDFERR); + if(var->dimscale_attached) var->dimscale_attached[d] = 0; if (dims_detached++ == var->ndims) finished++; } - } - /* Free the HDF5 dataset id. */ - if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid)) - BAIL(NC_EHDFERR); + /* Free the HDF5 dataset id. */ + if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) + BAIL(NC_EHDFERR); + } /* Now delete the variable. */ if (H5Gunlink(grp->hdf_grpid, var->name) < 0) diff --git a/libsrc4/nc4internal.c b/libsrc4/nc4internal.c index c67ca64a5..f6befe2c3 100644 --- a/libsrc4/nc4internal.c +++ b/libsrc4/nc4internal.c @@ -858,9 +858,17 @@ nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size, LOG((4, "nc4_enum_member_add: size %d name %s", size, name)); /* Allocate storage for this field information. */ - if (!(member = calloc(1, sizeof(NC_ENUM_MEMBER_INFO_T))) || - !(member->value = calloc(1, size))) + if (!(member = calloc(1, sizeof(NC_ENUM_MEMBER_INFO_T)))) return NC_ENOMEM; + if (!(member->value = calloc(1, size))) { + free(member); + return NC_ENOMEM; + } + if (!(member->name = malloc((strlen(name) + 1) * sizeof(char)))) { + free(member->value); + free(member); + return NC_ENOMEM; + } /* Add this field to list. */ if (*list) @@ -877,11 +885,6 @@ nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size, } /* Store the information about this member. */ - if (!(member->name = malloc((strlen(name) + 1) * sizeof(char)))) { - if(member) free(member); - - return NC_ENOMEM; - } strcpy(member->name, name); memcpy(member->value, value, size); From 7a4479be6b9227902923d62d5e29a210fd24a529 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 14 Sep 2013 13:19:58 -0500 Subject: [PATCH 02/21] Minor cleanups to reduce warnings in headers, and switch from MPI_BYTE to MPI_INT for MPI_Allreduce() call. --- include/ncdispatch.h | 23 ----------------------- libsrc4/nc4hdf.c | 4 ++-- oc2/oc.h | 6 ------ oc2/ocinternal.h | 2 -- 4 files changed, 2 insertions(+), 33 deletions(-) diff --git a/include/ncdispatch.h b/include/ncdispatch.h index 6c41f1c81..426b22f95 100644 --- a/include/ncdispatch.h +++ b/include/ncdispatch.h @@ -23,29 +23,6 @@ #define longtype ((sizeof(long) == sizeof(int) ? NC_INT : NC_INT64)) -extern int nc_get_vara_ubyte(int ncid, int varid, - const size_t* start, const size_t* count, - unsigned char* value); -extern int nc_get_vara_ushort(int ncid, int varid, - const size_t* start, const size_t* count, - unsigned short* value); -extern int nc_get_vara_uint(int ncid, int varid, - const size_t* start, const size_t* count, - unsigned int* value); -extern int nc_get_vara_ulonglong(int ncid, int varid, - const size_t* start, const size_t* count, - unsigned long long* value); - -extern int nc_put_vara_ushort(int ncid, int varid, - const size_t* start, const size_t* count, - const unsigned short* value); -extern int nc_put_vara_uint(int ncid, int varid, - const size_t* start, const size_t* count, - const unsigned int* value); -extern int nc_put_vara_ulonglong(int ncid, int varid, - const size_t* start, const size_t* count, - const unsigned long long* value); - #define X_INT_MAX 2147483647 /* Given a filename, check its magic number */ diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index 1d59df1fb..35ca9aa5e 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -798,11 +798,11 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, BAIL(NC_ECANTEXTEND); /* Reach consensus about dimension sizes to extend to */ - /* (Note: Somewhat hackish, with the use of MPI_BYTE, but MPI_MAX is + /* (Note: Somewhat hackish, with the use of MPI_INTEGER, but MPI_MAX is * correct with this usage, as long as it's not executed on * heterogenous systems) */ - if(MPI_SUCCESS != MPI_Allreduce(MPI_IN_PLACE, &xtend_size, (var->ndims * sizeof(hsize_t)), MPI_BYTE, MPI_MAX, h5->comm)) + if(MPI_SUCCESS != MPI_Allreduce(MPI_IN_PLACE, &xtend_size, (var->ndims * (sizeof(hsize_t) / sizeof(int))), MPI_INT, MPI_MAX, h5->comm)) BAIL(NC_EMPI); } #endif /* USE_PARALLEL */ diff --git a/oc2/oc.h b/oc2/oc.h index 71f24b7f5..3a9bda5c5 100644 --- a/oc2/oc.h +++ b/oc2/oc.h @@ -439,12 +439,6 @@ extern OCerror oc_data_octype(OClink, OCdatanode data, OCtype*); */ extern int oc_data_indexed(OClink link, OCdatanode datanode); -/* Return 1 if the specified data has a valid index, 0 otherwise. - Valid index means it was created using - oc_data_ithelement or oc_data_ithrecord. -*/ -extern int oc_data_indexed(OClink, OCdatanode); - /* Return 1 if the specified data can be indexed Indexable means the data is pointing to an indexed structure or to a sequence. diff --git a/oc2/ocinternal.h b/oc2/ocinternal.h index 516fa7472..f77e350a1 100644 --- a/oc2/ocinternal.h +++ b/oc2/ocinternal.h @@ -208,8 +208,6 @@ extern int ocinternalinitialize(void); extern OCerror ocupdatelastmodifieddata(OCstate* state); -extern int ocinternalinitialize(void); - extern OCerror ocsetuseragent(OCstate* state, const char* agent); #endif /*COMMON_H*/ From d9069aaeaa086313f0d6018c58be855e2399cce8 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 28 Sep 2013 12:40:21 -0500 Subject: [PATCH 03/21] More progress toward fixing NCF-177. --- include/nc4internal.h | 2 +- libsrc4/nc4hdf.c | 43 ++++++++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/include/nc4internal.h b/include/nc4internal.h index 1de0f416a..c02932c17 100644 --- a/include/nc4internal.h +++ b/include/nc4internal.h @@ -145,7 +145,7 @@ typedef struct NC_VAR_INFO struct NC_VAR_INFO *next; struct NC_VAR_INFO *prev; int dirty; - int created; + int created; /* Variable has already been created (_not_ that it was just created) */ int written_to; int *dimscale_attached; struct NC_TYPE_INFO *type_info; diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index cdadb1c5c..c34494c4a 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -1343,7 +1343,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) int d; NC_DIM_INFO_T *dim = NULL; int dims_found = 0; - int set_chunksizes = 0; char *name_to_use; int retval = NC_NOERR; @@ -1454,8 +1453,9 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) BAIL(NC_ENOMEM); if (!(maxdimsize = malloc(var->ndims * sizeof(hsize_t)))) BAIL(NC_ENOMEM); - if (!(chunksize = malloc(var->ndims * sizeof(hsize_t)))) - BAIL(NC_ENOMEM); + if (!var->contiguous) + if (!(chunksize = malloc(var->ndims * sizeof(hsize_t)))) + BAIL(NC_ENOMEM); for (d = 0; d < var->ndims; d++) { @@ -1489,12 +1489,12 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) * length, make it the dim length. */ if (!dim->unlimited && chunksize[d] > dim->len) chunksize[d] = dim->len; - set_chunksizes++; + + /* Remember the computed chunksize */ + var->chunksizes[d] = chunksize[d]; } } - if (!var->contiguous && !var->chunksizes[d]) - var->chunksizes[d] = chunksize[d]; dims_found++; break; } @@ -1534,11 +1534,11 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) H5P_CRT_ORDER_INDEXED) < 0) BAIL(NC_EHDFERR); - /* Set per-var chunk cache. */ - if (var->chunk_cache_size) + /* Set per-var chunk cache, for chunked datasets. */ + if (!var->contiguous && var->chunk_cache_size) if (H5Pset_chunk_cache(access_plistid, var->chunk_cache_nelems, - var->chunk_cache_size, var->chunk_cache_preemption) < 0) - BAIL(NC_EHDFERR); + var->chunk_cache_size, var->chunk_cache_preemption) < 0) + BAIL(NC_EHDFERR); /* At long last, create the dataset. */ name_to_use = var->hdf5_name ? var->hdf5_name : var->name; @@ -2226,7 +2226,8 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) * this object exists in the HDF group. */ if (var->dimscale) for (d1 = grp->dim; d1; d1 = d1->next) - if (!strcmp(d1->name, var->name)) + if (!strcmp(d1->name, var->name) || + !strcmp(d1->old_name, var->name)) { if ((retval = var_exists(grp->hdf_grpid, var->name, &exists))) return retval; @@ -2240,6 +2241,11 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) if ((retval = rec_detach_scales(grp->nc4_info->root_grp, var->dimids[0], d1->hdf_dimscaleid))) return retval; + + /* Check if this variable should no longer be a dimscale */ + /* (Because its dim was renamed) */ + if (!strcmp(d1->old_name, var->name)) + var->dimscale = 0; break; } } @@ -2253,6 +2259,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) assert(d1 && d1->hdf_dimscaleid); if (H5Dclose(d1->hdf_dimscaleid) < 0) return NC_EDIMMETA; + d1->hdf_dimscaleid = 0; } else { @@ -2268,11 +2275,11 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) for (dim1 = g->dim; dim1; dim1 = dim1->next) if (var->dimids[d] == dim1->dimid) { - if(var->hdf_datasetid != dim1->hdf_dimscaleid) - if (H5DSdetach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0) - BAIL(NC_EHDFERR); - if(var->dimscale_attached) - var->dimscale_attached[d] = 0; + if(var->hdf_datasetid != dim1->hdf_dimscaleid) + if (H5DSdetach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0) + BAIL(NC_EHDFERR); + if(var->dimscale_attached) + var->dimscale_attached[d] = 0; if (dims_detached++ == var->ndims) finished++; } @@ -2280,6 +2287,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) /* Free the HDF5 dataset id. */ if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) BAIL(NC_EHDFERR); + var->hdf_datasetid = 0; } /* Now delete the variable. */ @@ -2293,7 +2301,8 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) /* Reattach this scale everywhere it is used. (Recall that * netCDF dimscales are always 1-D). */ - if (d1 && replace_existing_var) + /* (Only do this if the variable is still a dimscale) */ + if (d1 && replace_existing_var && var->dimscale) { d1->hdf_dimscaleid = var->hdf_datasetid; if ((retval = rec_reattach_scales(grp->nc4_info->root_grp, From 1d007eb101ea10a684d8ad60646c4fd6c41f0939 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 20 Nov 2013 13:37:21 -0700 Subject: [PATCH 04/21] Addressed a number of minor bugs reported by Clang. --- Doxyfile | 2 +- libdap2/cache.c | 7 ++++--- libdap2/ncdap3a.c | 6 +++--- oc2/ocinternal.c | 5 +++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Doxyfile b/Doxyfile index 01126d5d5..87793fd90 100755 --- a/Doxyfile +++ b/Doxyfile @@ -32,7 +32,7 @@ PROJECT_NAME = netCDF-C # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 4.3.1-RC3 +PROJECT_NUMBER = 4.3.1-RC5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/libdap2/cache.c b/libdap2/cache.c index 813079657..fd91e0512 100644 --- a/libdap2/cache.c +++ b/libdap2/cache.c @@ -162,8 +162,9 @@ nullfree(s); 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 */ + if(ncstat || cache == NULL) goto done; + else + cache->wholevariable = 1; /* All prefetches are whole variable */ /* Make cache node be the prefetch node */ nccomm->cdf.cache->prefetch = cache; if(SHOWFETCH) { @@ -190,7 +191,7 @@ ncbytesfree(buf); done: nclistfree(vars); dcefree((DCEnode*)newconstraint); - if(ncstat) freenccachenode(nccomm,cache); + if(ncstat && cache != NULL) freenccachenode(nccomm,cache); return THROW(ncstat); } diff --git a/libdap2/ncdap3a.c b/libdap2/ncdap3a.c index 0aa3bec0b..b96ff914a 100644 --- a/libdap2/ncdap3a.c +++ b/libdap2/ncdap3a.c @@ -151,7 +151,7 @@ defrecorddim3(NCDAPCOMMON* dapcomm) NCerror defseqdims(NCDAPCOMMON* dapcomm) { - unsigned int i; + unsigned int i = 0; NCerror ncstat = NC_NOERR; int seqdims = 1; /* default is to compute seq dims counts */ @@ -169,7 +169,7 @@ defseqdims(NCDAPCOMMON* dapcomm) for(i=0;icdf.ddsroot->tree->seqnodes);i++) { CDFnode* seq = (CDFnode*)nclistget(dapcomm->cdf.ddsroot->tree->seqnodes,i); - size_t seqsize; + size_t seqsize = 0; CDFnode* sqdim = NULL; CDFnode* container; /* Does this sequence match the requirements for use ? */ @@ -214,7 +214,7 @@ getseqdimsize(NCDAPCOMMON* dapcomm, CDFnode* seq, size_t* sizep) CDFnode* dxdroot; CDFnode* xseq; NCbytes* seqcountconstraints = ncbytesnew(); - size_t seqsize; + size_t seqsize = 0; /* Read the minimal amount of data in order to get the count */ /* If the url is unconstrainable, then get the whole thing */ diff --git a/oc2/ocinternal.c b/oc2/ocinternal.c index a087003fd..c2324284e 100644 --- a/oc2/ocinternal.c +++ b/oc2/ocinternal.c @@ -387,8 +387,9 @@ createtempfile(OCstate* state, OCtree* tree) return stat; fail: - if(name != NULL) free(name); - oclog(OCLOGERR,"oc_open: attempt to create tmp file failed: %s",name); + oclog(OCLOGERR,"oc_open: attempt to create tmp file failed: %s",name == NULL ? "[NULL]" : name); + + if(name != NULL) {free(name);name=NULL;} return stat; } From 74fce49fe157b44464d2b74a87ad1d2d6bd40736 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 20 Nov 2013 14:03:55 -0700 Subject: [PATCH 05/21] Corrected an issue reported by clang related to dereferencing a NULL value. --- libdap2/ncdap3a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libdap2/ncdap3a.c b/libdap2/ncdap3a.c index b96ff914a..fd41dbfac 100644 --- a/libdap2/ncdap3a.c +++ b/libdap2/ncdap3a.c @@ -524,7 +524,8 @@ computeseqcountconstraints3r(NCDAPCOMMON* dapcomm, CDFnode* node, CDFnode** cand candidate = NULL; compound = NULL; - + if(node == NULL) + return; for(i=0;isubnodes);i++) { CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,i); if(subnode->nctype == NC_Structure || subnode->nctype == NC_Grid) From 906f2a7513304efbf32359d2b02afb2d59d6ea4b Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 13:48:30 -0700 Subject: [PATCH 06/21] Corrected a garbage-value error reported by Clang. --- ncgen/nc_iter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ncgen/nc_iter.c b/ncgen/nc_iter.c index 95e6e5be2..c8978fa4e 100644 --- a/ncgen/nc_iter.c +++ b/ncgen/nc_iter.c @@ -49,7 +49,7 @@ nc_get_iter(Symbol* vsym, Symbol* vartype; size_t value_size; /* size in bytes of each variable element */ int ndims; /* number of dimensions for variable */ - size_t dimsizes[NC_MAX_VAR_DIMS]; /* variable dimension sizes */ + size_t dimsizes[NC_MAX_VAR_DIMS] = {0}; /* variable dimension sizes */ long long nvalues = 1; int dim; From 18afaa914549cb86fbca1f3f4a6edc13c042388a Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 13:49:21 -0700 Subject: [PATCH 07/21] Corrected several convoluted chains in cache.c by which either null pointers might be dereferenced, or by which a pointer might be referenced after being freed. These were reported by Clang static analysis. --- libdap2/cache.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libdap2/cache.c b/libdap2/cache.c index fd91e0512..c9e1348f7 100644 --- a/libdap2/cache.c +++ b/libdap2/cache.c @@ -162,7 +162,8 @@ nullfree(s); 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 || cache == NULL) goto done; + if(ncstat != OC_NOERR) goto done; + else if(cache == NULL) goto done; else cache->wholevariable = 1; /* All prefetches are whole variable */ /* Make cache node be the prefetch node */ @@ -293,9 +294,10 @@ done: if(constraint != NULL) dcefree((DCEnode*)constraint); if(cachep) *cachep = cachenode; if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); - if(ncstat) { + if(ncstat != OC_NOERR) { freecdfroot34(dxdroot); freenccachenode(nccomm,cachenode); + if(cachep) *cachep = NULL; } return THROW(ncstat); } @@ -320,6 +322,7 @@ fprintf(stderr,"freecachenode: %s\n", freecdfroot34(node->datadds); nclistfree(node->vars); nullfree(node); + } void From 842ca6b998dbbb8dbcd48e8e21c5a03add6d94ce Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 14:53:42 -0700 Subject: [PATCH 08/21] It appears that we will need to do another release candidate. Bumped the revision in the configuration tools. --- CMakeLists.txt | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca87a5359..d61a91441 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(PACKAGE "netCDF" CACHE STRING "") SET(netCDF_VERSION_MAJOR 4) SET(netCDF_VERSION_MINOR 3) SET(netCDF_VERSION_PATCH 1) -SET(netCDF_VERSION_NOTE "-rc4") +SET(netCDF_VERSION_NOTE "-rc5") SET(netCDF_VERSION ${netCDF_VERSION_MAJOR}.${netCDF_VERSION_MINOR}.${netCDF_VERSION_PATCH}${netCDF_VERSION_NOTE}) SET(VERSION ${netCDF_VERSION}) SET(netCDF_SO_VERSION 7.2.0) diff --git a/configure.ac b/configure.ac index 97de1f9b4..7b9955a7c 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_REVISION([$Id: configure.ac,v 1.450 2010/05/28 19:42:47 dmh Exp $]) AC_PREREQ([2.59]) # Initialize with name, version, and support email address. -AC_INIT([netCDF], [4.3.1-rc4], [support-netcdf@unidata.ucar.edu]) +AC_INIT([netCDF], [4.3.1-rc5], [support-netcdf@unidata.ucar.edu]) # Create the VERSION file, which contains the package version from # AC_INIT. From d1afda5c7df090b33faac4d79cb2437b93b3abc9 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 15:20:21 -0700 Subject: [PATCH 09/21] CMake: Added a check for libjpeg when compiling with HDF4 support. --- CMakeLists.txt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d61a91441..0d6435b57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,11 +464,30 @@ IF (ENABLE_HDF4) SET(HDF4_LIBRARIES ${HDF4_MFHDF_LIB} ${HDF4_DF_LIB}) # End include files, libraries. - MESSAGE(STATUS "HDF4 Libraries: ${HDF4_DF_LIB}, ${HDF4_MFHDF_LIB}") + MESSAGE(STATUS "HDF4 libraries: ${HDF4_DF_LIB}, ${HDF4_MFHDF_LIB}") OPTION(ENABLE_HDF4_FILE_TESTS "Run HDF4 File Tests." OFF) IF(ENABLE_HDF4_FILE_TESTS) SET(USE_HDF4_FILE_TESTS ON) ENDIF() + + MESSAGE(STATUS "Seeking HDF4 jpeg dependency.") + + # Look for the jpeglib.h header file. + FIND_PATH(JPEGLIB_H_INCLUDE_DIR jpeglib.h) + IF(NOT JPEGLIB_H_INCLUDE_DIR) + MESSAGE(FATAL_ERROR "HDF4 Support enabled but cannot find jpeglib.h") + ELSE() + SET(HAVE_JPEGLIB_H ON CACHE BOOL "") + INCLUDE_DIRECTORIES(${JPEGLIB_H_INCLUDE_DIR}) + ENDIF() + + FIND_LIBRARY(JPEG_LIB NAMES jpeg libjpeg) + IF(NOT JPEG_LIB) + MESSAGE(FATAL_ERROR "HDF4 Support enabled but cannot find libjpeg") + ENDIF() + SET(HDF4_LIBRARIES ${JPEG_LIB} ${HDF4_LIBRARIES}) + MESSAGE(STATUS "Found JPEG libraries: ${JPEG_LIB}") + ENDIF () # Option to Build DLL From d1886a552438b8f6ebdd1256ea3d6b36b518bd86 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 15:45:53 -0700 Subject: [PATCH 10/21] =?UTF-8?q?CMake:=20Added=20option=20to=20run=20HDF4?= =?UTF-8?q?=20file=20tests,=20as=20well=20as=20a=20check=20for=20=E2=80=98?= =?UTF-8?q?wget=E2=80=99;=20without=20wget,=20these=20tests=20cannot=20be?= =?UTF-8?q?=20run.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d6435b57..85a88f895 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,22 +454,18 @@ IF (ENABLE_HDF4) FIND_LIBRARY(HDF4_DF_LIB NAMES df libdf) IF(NOT HDF4_DF_LIB) - MESSAGE(FATAL_ERROR "HDF4 Support enabled, but cannot find df lib.") + MESSAGE(FATAL_ERROR "Can't find or link to the hdf4 df library.") ENDIF() FIND_LIBRARY(HDF4_MFHDF_LIB NAMES mfhdf libmfhdf) IF(NOT HDF4_MFHDF_LIB) - MESSAGE(FATAL_ERROR "HDF4 Support enabled, but cannot find mfhdf lib.") + MESSAGE(FATAL_ERROR "Can't find or link to the hdf4 mfhdf library.") ENDIF() SET(HDF4_LIBRARIES ${HDF4_MFHDF_LIB} ${HDF4_DF_LIB}) # End include files, libraries. MESSAGE(STATUS "HDF4 libraries: ${HDF4_DF_LIB}, ${HDF4_MFHDF_LIB}") - OPTION(ENABLE_HDF4_FILE_TESTS "Run HDF4 File Tests." OFF) - IF(ENABLE_HDF4_FILE_TESTS) - SET(USE_HDF4_FILE_TESTS ON) - ENDIF() - + MESSAGE(STATUS "Seeking HDF4 jpeg dependency.") # Look for the jpeglib.h header file. @@ -488,7 +484,20 @@ IF (ENABLE_HDF4) SET(HDF4_LIBRARIES ${JPEG_LIB} ${HDF4_LIBRARIES}) MESSAGE(STATUS "Found JPEG libraries: ${JPEG_LIB}") -ENDIF () + # Option to enable HDF4 file tests. + OPTION(ENABLE_HDF4_FILE_TESTS "Run HDF4 file tests. This fetches sample HDF4 files from the Unidata ftp site to test with (requires wget)." ON) + IF(ENABLE_HDF4_FILE_TESTS) + FIND_PROGRAM(PROG_WGET NAMES wget) + IF(PROG_WGET) + SET(USE_HDF4_FILE_TESTS ON) + ELSE() + MESSAGE(STATUS "Unable to locate 'wget'. Disabling hdf4 file tests.") + SET(USE_HDF4_FILE_TESTS OFF) + ENDIF() + + ENDIF() + + ENDIF () # Option to Build DLL IF(WIN32) From 7c6a9aa34a4dac61ea459cf6fb37ba29d9aa8f5c Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 16:03:03 -0700 Subject: [PATCH 11/21] Cleaned up configure.ac a little bit, added a check for libjpeg when compiling with hdf4 support. --- configure.ac | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7b9955a7c..80e183307 100644 --- a/configure.ac +++ b/configure.ac @@ -732,8 +732,9 @@ if test "x$enable_netcdf_4" = xyes; then fi AC_CHECK_LIB([df], [Hclose], [], [AC_MSG_ERROR([Can't find or link to the hdf4 df library. See config.log for errors.])]) AC_CHECK_LIB([mfhdf], [SDcreate], [], [AC_MSG_ERROR([Can't find or link to the hdf4 mfhdf library. See config.log for errors.])]) - #AC_SEARCH_LIBS([Hclose],[df], [], [AC_MSG_ERROR([Can't find or link to the hdf4 df library. See config.log for errors.])]) - #AC_SEARCH_LIBS([SDcreate],[mfhdf], [], [AC_MSG_ERROR([Can't find or link to the hdf4 mfhdf library. See config.log for errors.])]) + + AC_CHECK_LIB([jpeg], [jpeg_set_quality], [], [AC_MSG_ERROR([Can't find or link to the jpeg library (required by hdf4). See config.log for errors.])]) + AC_DEFINE([USE_HDF4], [1], [if true, use HDF4 too]) fi fi From 1d7ec898ff66f5b090b31c512e61f0a5985ba83a Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 22 Nov 2013 16:09:51 -0700 Subject: [PATCH 12/21] Updated release notes. --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f1cdc438b..6d9f30788 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,6 +8,10 @@ information, where '[NCF-XXX]' refers to https://www.unidata.ucar.edu/jira/brows ## 4.3.1 Released TBD +### 4.3.1-rc5 Released TBD + +* When compiling with `hdf4` support, both autotools and cmake-based builds now properly look for the `libjpeg` dependency and will link against it when found (or complain if it's not). Also added `ENABLE_HDF4_FILE_TESTS` option to CMake-based builds. + * Fixed bug in ncgen; it was not properly filling empty string constants ("") to be the proper length. [NCF-279] From 66434cdb8a804d330d293cfd2779d67f4c85bf63 Mon Sep 17 00:00:00 2001 From: Russ Rew Date: Tue, 26 Nov 2013 13:33:18 -0700 Subject: [PATCH 13/21] Fix test for proper error return when invalid coordinate specified for nc_get_var1_ushaort call. --- nc_test4/tst_converts2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nc_test4/tst_converts2.c b/nc_test4/tst_converts2.c index c449b787c..8b3370da0 100644 --- a/nc_test4/tst_converts2.c +++ b/nc_test4/tst_converts2.c @@ -102,8 +102,8 @@ main(int argc, char **argv) if (long_in != lval) ERR; /* This should fail. */ - coord[3] = 100; - if (nc_get_var1_ushort(ncid, varid, &coord[3], + coord[0] = 5; + if (nc_get_var1_ushort(ncid, varid, coord, &ushort_in) != NC_EINVALCOORDS) ERR; if (nc_close(ncid)) ERR; @@ -162,8 +162,8 @@ main(int argc, char **argv) if (long_in != lval) ERR; /* This should fail. */ - coord[3] = 100; - if (nc_get_var1_ushort(ncid, varid, &coord[3], + coord[0] = 5; + if (nc_get_var1_ushort(ncid, varid, coord, &ushort_in) != NC_EINVALCOORDS) ERR; if (nc_close(ncid)) ERR; From d484b9ac3323b391d73c2abd88a90ae130afedbc Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 27 Nov 2013 17:03:59 -0600 Subject: [PATCH 14/21] =?UTF-8?q?Corrected=20two=20possible=20=E2=80=98uni?= =?UTF-8?q?nitialized=20variable=E2=80=99,=20=E2=80=98dereference=20null?= =?UTF-8?q?=20pointer=E2=80=99=20bugs=20identified=20via=20clang=20static?= =?UTF-8?q?=20analysis.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oc2/oc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/oc2/oc.c b/oc2/oc.c index 3e797db5f..7e746fc18 100644 --- a/oc2/oc.c +++ b/oc2/oc.c @@ -967,7 +967,7 @@ OCerror oc_data_fieldbyname(OCobject link, OCobject datanode, const char* name, OCobject* fieldp) { OCerror err = OC_NOERR; - size_t count,i; + size_t i=0,count=0; OCobject ddsnode; OCVERIFY(OC_State,link); OCVERIFY(OC_Data,datanode); @@ -1292,7 +1292,10 @@ oc_data_octype(OCobject link, OCobject datanode, OCtype* typep) OCASSERT(data->template != NULL); if(typep == NULL) ocerr = OC_EINVAL; - else *typep = data->template->octype; + else if(data->template) + *typep = data->template->octype; + else + ocerr = OC_EINVAL; return ocerr; } From e1fc13b2152f0b2ea85f74be9d31a9de3c61b7c4 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 30 Nov 2013 23:20:28 -0600 Subject: [PATCH 15/21] Many changes to address NCF-177 (renaming dimensions and variables). Also many cleanups to fix compiler warnings, streamline iteration over objects in HDF5 file when opening the file, and generally straightening out the code to be cleaner and simpler. Tested on Mac OS/X with gcc 4.8 and OpenMPI (which uses clang). --- h5_test/tst_h_dimscales2.c | 46 -- h5_test/tst_h_dimscales3.c | 28 -- h5_test/tst_h_dimscales4.c | 154 ------ include/nc4internal.h | 15 +- libsrc4/nc4dim.c | 82 ++-- libsrc4/nc4file.c | 974 +++++++++++-------------------------- libsrc4/nc4grp.c | 32 +- libsrc4/nc4hdf.c | 752 +++++++++++----------------- libsrc4/nc4internal.c | 164 +++++-- libsrc4/nc4var.c | 107 ++-- nc_test4/renamegroup.c | 1 + nc_test4/tst_dims.c | 148 +++++- nc_test4/tst_dims2.c | 7 - nc_test4/tst_parallel3.c | 1 + ncgen/genlib.c | 19 +- ncgen3/ncgen.h | 1 + 16 files changed, 1020 insertions(+), 1511 deletions(-) diff --git a/h5_test/tst_h_dimscales2.c b/h5_test/tst_h_dimscales2.c index 634d80902..11082d979 100644 --- a/h5_test/tst_h_dimscales2.c +++ b/h5_test/tst_h_dimscales2.c @@ -20,11 +20,6 @@ #define DIMSCALE_LABEL "dimscale_label" #define STR_LEN 255 -/* typedef struct { */ -/* unsigned long fileno; /\*file number *\/ */ -/* haddr_t objno; /\*object number *\/ */ -/* } HDF5_OBJID_T; */ - herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid, void *visitor_data) { @@ -37,34 +32,21 @@ herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid, if (H5Iget_name(did, name1, STR_LEN) < 0) ERR; if (strcmp(&name1[1], VAR1_NAME)) ERR; - /*printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", - did, dim, dsid, name1);*/ - /* Get more info on the dimscale object.*/ if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR; objid->fileno[0] = statbuf.fileno[0]; objid->objno[0] = statbuf.objno[0]; objid->fileno[1] = statbuf.fileno[1]; objid->objno[1] = statbuf.objno[1]; - /*printf("for dsid: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ - if (H5Gget_objinfo(did, ".", 1, &statbuf) < 0) ERR; - /*printf("for did: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ return 0; } herr_t alien_visitor2(hid_t did, unsigned dim, hid_t dsid, void *visitor_data) { - char name1[STR_LEN]; H5G_stat_t statbuf; HDF5_OBJID_T *objid = visitor_data; - if (H5Iget_name(did, name1, STR_LEN) < 0) ERR; - /*printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", - did, dim, dsid, name1); */ - /* Get obj id of the dimscale object. THis will be used later to * match dimensions to dimscales. */ if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR; @@ -145,9 +127,6 @@ main() if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR; if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR; - /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", - obj_class, obj_name);*/ - /* Deal with object based on its obj_class. */ switch(obj_class) { @@ -179,9 +158,6 @@ main() dimscale_obj.objno[0] = statbuf.objno[0]; dimscale_obj.fileno[1] = statbuf.fileno[1]; dimscale_obj.objno[1] = statbuf.objno[1]; - /*printf("statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ - } else { @@ -193,8 +169,6 @@ main() /* Go through all dimscales for this var and learn about them. */ if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor, &vars_dimscale_obj) < 0) ERR; - /*printf("vars_dimscale_obj.fileno = %d vars_dimscale_obj.objno = %d\n", - vars_dimscale_obj.fileno, vars_dimscale_obj.objno);*/ if (vars_dimscale_obj.fileno[0] != dimscale_obj.fileno[0] || vars_dimscale_obj.objno[0] != dimscale_obj.objno[0] || vars_dimscale_obj.fileno[1] != dimscale_obj.fileno[1] || @@ -202,8 +176,6 @@ main() /* There's also a label for dimension 0. */ if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR; - - /*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/ } if (H5Dclose(datasetid) < 0) ERR; break; @@ -304,9 +276,6 @@ main() if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR; if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR; -/* printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", */ -/* obj_class, obj_name); */ - /* Deal with object based on its obj_class. */ switch(obj_class) { @@ -333,9 +302,6 @@ main() dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0]; dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1]; dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1]; -/* printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */ -/* dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt, */ -/* dimscale_obj[dimscale_cnt].objno); */ dimscale_cnt++; } else @@ -791,9 +757,6 @@ main() if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR; if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR; - /* printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", */ -/* obj_class, obj_name); */ - /* Deal with object based on its obj_class. */ switch(obj_class) { @@ -819,9 +782,6 @@ main() dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0]; dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1]; dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1]; - /* printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */ -/* dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt, */ -/* dimscale_obj[dimscale_cnt].objno); */ dimscale_cnt++; } else @@ -982,9 +942,6 @@ main() if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR; if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR; - /* printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", */ -/* obj_class, obj_name); */ - /* Deal with object based on its obj_class. */ switch(obj_class) { @@ -1010,9 +967,6 @@ main() dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0]; dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1]; dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1]; - /* printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */ -/* dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt, */ -/* dimscale_obj[dimscale_cnt].objno); */ dimscale_cnt++; } else diff --git a/h5_test/tst_h_dimscales3.c b/h5_test/tst_h_dimscales3.c index 6485807ff..97867d957 100644 --- a/h5_test/tst_h_dimscales3.c +++ b/h5_test/tst_h_dimscales3.c @@ -23,11 +23,6 @@ #define DIMSCALE_LABEL "dimscale_label" #define STR_LEN 255 -/* typedef struct { */ -/* unsigned long fileno; /\*file number *\/ */ -/* haddr_t objno; /\*object number *\/ */ -/* } HDF5_OBJID_T; */ - herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid, void *visitor_data) { @@ -40,34 +35,21 @@ herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid, if (H5Iget_name(did, name1, STR_LEN) < 0) ERR; if (strcmp(&name1[1], VAR1_NAME)) ERR; - /*printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", - did, dim, dsid, name1);*/ - /* Get more info on the dimscale object.*/ if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR; objid->fileno[0] = statbuf.fileno[0]; objid->objno[0] = statbuf.objno[0]; objid->fileno[1] = statbuf.fileno[1]; objid->objno[1] = statbuf.objno[1]; - /*printf("for dsid: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ - if (H5Gget_objinfo(did, ".", 1, &statbuf) < 0) ERR; - /*printf("for did: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ return 0; } herr_t alien_visitor2(hid_t did, unsigned dim, hid_t dsid, void *visitor_data) { - char name1[STR_LEN]; H5G_stat_t statbuf; HDF5_OBJID_T *objid = visitor_data; - if (H5Iget_name(did, name1, STR_LEN) < 0) ERR; - /*printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", - did, dim, dsid, name1); */ - /* Get obj id of the dimscale object. THis will be used later to * match dimensions to dimscales. */ if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR; @@ -144,9 +126,6 @@ main() if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR; if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR; - /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", - obj_class, obj_name);*/ - /* Deal with object based on its obj_class. */ switch(obj_class) { @@ -178,9 +157,6 @@ main() dimscale_obj.objno[0] = statbuf.objno[0]; dimscale_obj.fileno[1] = statbuf.fileno[1]; dimscale_obj.objno[1] = statbuf.objno[1]; - /*printf("statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ - } else { @@ -192,8 +168,6 @@ main() /* Go through all dimscales for this var and learn about them. */ if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor, &vars_dimscale_obj) < 0) ERR; - /*printf("vars_dimscale_obj.fileno = %d vars_dimscale_obj.objno = %d\n", - vars_dimscale_obj.fileno, vars_dimscale_obj.objno);*/ if (vars_dimscale_obj.fileno[0] != dimscale_obj.fileno[0] || vars_dimscale_obj.objno[0] != dimscale_obj.objno[0] || vars_dimscale_obj.fileno[1] != dimscale_obj.fileno[1] || @@ -201,8 +175,6 @@ main() /* There's also a label for dimension 0. */ if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR; - - /*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/ } if (H5Dclose(datasetid) < 0) ERR; break; diff --git a/h5_test/tst_h_dimscales4.c b/h5_test/tst_h_dimscales4.c index b74bef87a..028078381 100644 --- a/h5_test/tst_h_dimscales4.c +++ b/h5_test/tst_h_dimscales4.c @@ -27,75 +27,25 @@ #define NC_EHDFERR 255 #define DIM_WITHOUT_VARIABLE "This is a netCDF dimension but not a netCDF variable." -/* typedef struct { */ -/* unsigned long fileno; /\*file number *\/ */ -/* haddr_t objno; /\*object number *\/ */ -/* } HDF5_OBJID_T; */ - struct nc_hdf5_link_info { char name[STR_LEN]; H5I_type_t obj_type; }; -#if 0 -static herr_t -visit_link(hid_t g_id, const char *name, const H5L_info_t *info, - void *op_data) -{ - /* A positive return value causes the visit iterator to immediately - * return that positive value, indicating short-circuit - * success. The iterator can be restarted at the next group - * member. */ - int ret = 1; - hid_t id; - - strncpy(((struct nc_hdf5_link_info *)op_data)->name, name, NC_MAX_NAME); - - /* Open this critter. */ - if ((id = H5Oopen_by_addr(g_id, info->u.address)) < 0) - return NC_EHDFERR; - - /* Is this critter a group, type, data, attribute, or what? */ - if ((((struct nc_hdf5_link_info *)op_data)->obj_type = H5Iget_type(id)) < 0) - ret = NC_EHDFERR; - - /* Close the critter to release resouces. */ - if (H5Oclose(id) < 0) - return NC_EHDFERR; - - return ret; -} -#endif - herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid, void *visitor_data) { -#if 0 - char name1[STR_LEN]; -#endif H5G_stat_t statbuf; HDF5_OBJID_T *objid = visitor_data; - /* This should get "/var1", the name of the dataset that the scale - * is attached to. */ - /*if (H5Iget_name(did, name1, STR_LEN) < 0) ERR;*/ - -/* printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", - did, dim, dsid, name1);*/ - /* Get more info on the dimscale object.*/ if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR; objid->fileno[0] = statbuf.fileno[0]; objid->objno[0] = statbuf.objno[0]; objid->fileno[1] = statbuf.fileno[1]; objid->objno[1] = statbuf.objno[1]; -/* printf("for dsid: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ - if (H5Gget_objinfo(did, ".", 1, &statbuf) < 0) ERR; -/* printf("for did: statbuf.fileno = %d statbuf.objno = %d\n", - statbuf.fileno, statbuf.objno);*/ return 0; } @@ -105,9 +55,6 @@ main() printf("\n*** Checking HDF5 dimscales detach.\n"); printf("*** Creating a file with two vars with one dimension scale..."); { -#if 0 - hid_t cparmsid; -#endif hid_t fileid, grpid, spaceid, var1_id, var2_id, dimscaleid; hid_t fcpl_id, fapl_id, create_propid, access_propid; hsize_t dims[NDIMS] = {DIM_LEN}; @@ -186,107 +133,6 @@ main() if (H5Dclose(dimscaleid) < 0) ERR; if (H5Gclose(grpid) < 0) ERR; if (H5Fclose(fileid) < 0) ERR; - - /* /\* Now read the file and check it. *\/ */ - /* { */ - /* hid_t fileid, spaceid = 0, datasetid = 0; */ - /* hsize_t num_obj, i; */ - /* int obj_class; */ - /* char obj_name[STR_LEN + 1]; */ - /* char dimscale_name[STR_LEN+1]; */ - /* htri_t is_scale; */ - /* char label[STR_LEN+1]; */ - /* int num_scales; */ - /* hsize_t dims[1], maxdims[1]; */ - /* H5G_stat_t statbuf; */ - /* HDF5_OBJID_T dimscale_obj, vars_dimscale_obj; */ - /* struct nc_hdf5_link_info link_info; */ - /* hsize_t idx = 0; */ - - /* /\* Open the file. *\/ */ - /* if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR; */ - /* if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR; */ - - /* /\* Loop through objects in the root group. *\/ */ - /* if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR; */ - /* for (i = 0; i < num_obj; i++) */ - /* { */ - - /* if (H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, */ - /* &idx, visit_link, (void *)&link_info) < 0) ERR; */ - - /* printf("Encountered: HDF5 object link_info.name %s\n", link_info.name); */ - - /* /\* Deal with object based on its obj_class. *\/ */ - /* switch(link_info.obj_type) */ - /* { */ - /* case H5I_GROUP: */ - /* break; */ - /* case H5I_DATASET: */ - /* /\* Open the dataset. *\/ */ - /* if ((datasetid = H5Dopen1(fileid, link_info.name)) < 0) ERR; */ - - /* if ((spaceid = H5Dget_space(datasetid)) < 0) ERR; */ - /* if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR; */ - /* if (maxdims[0] != DIM_LEN) ERR; */ - /* if (H5Sclose(spaceid) < 0) ERR; */ - - /* /\* Is this a dimscale? *\/ */ - /* if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR; */ - /* if (is_scale && strcmp(link_info.name, DIMSCALE_NAME)) ERR; */ - /* if (is_scale) */ - /* { */ - /* /\* A dimscale comes with a NAME attribute, in */ - /* * addition to its real name. *\/ */ - /* if (H5DSget_scale_name(datasetid, dimscale_name, STR_LEN) < 0) ERR; */ - /* if (strcmp(dimscale_name, dimscale_wo_var)) ERR; */ - - /* /\* fileno and objno uniquely identify an object and a */ - /* * HDF5 file. *\/ */ - /* if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR; */ - /* dimscale_obj.fileno[0] = statbuf.fileno[0]; */ - /* dimscale_obj.objno[0] = statbuf.objno[0]; */ - /* dimscale_obj.fileno[1] = statbuf.fileno[1]; */ - /* dimscale_obj.objno[1] = statbuf.objno[1]; */ - /* /\*printf("scale statbuf.fileno = %d statbuf.objno = %d\n", */ - /* statbuf.fileno, statbuf.objno);*\/ */ - - /* } */ - /* else */ - /* { */ - /* /\* Here's how to get the number of scales attached */ - /* * to the dataset's dimension 0. *\/ */ - /* if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR; */ - /* if (num_scales != 1) ERR; */ - - /* /\* Go through all dimscales for this var and learn about them. *\/ */ - /* if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor, */ - /* &vars_dimscale_obj) < 0) ERR; */ - /* /\*printf("vars_dimscale_obj.fileno = %d vars_dimscale_obj.objno = %d\n", */ - /* vars_dimscale_obj.fileno, vars_dimscale_obj.objno);*\/ */ - /* /\* if (vars_dimscale_obj.fileno[0] != dimscale_obj.fileno[0] || *\/ */ - /* /\* vars_dimscale_obj.objno[0] != dimscale_obj.objno[0] || *\/ */ - /* /\* vars_dimscale_obj.fileno[1] != dimscale_obj.fileno[1] || *\/ */ - /* /\* vars_dimscale_obj.objno[1] != dimscale_obj.objno[1]) ERR; *\/ */ - - /* /\* There's also a label for dimension 0. *\/ */ - /* if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR; */ - - /* /\*printf("found non-scale dataset %s, label %s\n", link_info.name, label);*\/ */ - /* } */ - /* if (H5Dclose(datasetid) < 0) ERR; */ - /* break; */ - /* case H5I_DATATYPE: */ - /* break; */ - /* default: */ - /* printf("Unknown object!"); */ - /* ERR; */ - /* } */ - /* } */ - - /* /\* Close up the shop. *\/ */ - /* if (H5Fclose(fileid) < 0) ERR; */ - /* }*/ } SUMMARIZE_ERR; FINAL_RESULTS; diff --git a/include/nc4internal.h b/include/nc4internal.h index c02932c17..12dd29864 100644 --- a/include/nc4internal.h +++ b/include/nc4internal.h @@ -108,11 +108,9 @@ typedef struct NC_DIM_INFO struct NC_DIM_INFO *next; struct NC_DIM_INFO *prev; hid_t hdf_dimscaleid; - char *old_name; /* only used to rename dim */ - int dirty; - unsigned char coord_var_in_grp; + HDF5_OBJID_T hdf5_objid; struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */ - int too_long; /* True if len it too big to fit in local size_t. */ + int too_long; /* True if len is too big to fit in local size_t. */ } NC_DIM_INFO_T; typedef struct NC_ATT_INFO @@ -234,7 +232,6 @@ typedef struct NC_GRP_INFO int natts; struct NC_HDF5_FILE_INFO *nc4_info; char *name; - char *old_name; /* need when renaming group */ hid_t hdf_grpid; NC_TYPE_INFO_T *type; } NC_GRP_INFO_T; @@ -292,6 +289,7 @@ int nc4_convert_type(const void *src, void *dest, int dest_long); /* These functions do HDF5 things. */ +int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid); int nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset); int pg_var(NC_PG_T pg, NC *nc, int ncid, int varid, nc_type xtype, int is_long, void *ip); int nc4_pg_var1(NC_PG_T pg, NC *nc, int ncid, int varid, const size_t *indexp, @@ -306,7 +304,7 @@ int nc4_pg_varm(NC_PG_T pg, NC *nc, int ncid, int varid, const size_t *startp, int nc4_rec_match_dimscales(NC_GRP_INFO_T *grp); int nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, int *bad_coord_orderp); int nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order); -int nc4_rec_write_types(NC_GRP_INFO_T *grp); +int nc4_rec_write_groups_types(NC_GRP_INFO_T *grp); int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5); int nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var); int nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T * var); @@ -321,6 +319,7 @@ NC_GRP_INFO_T *nc4_find_nc_grp(int ncid); NC_GRP_INFO_T *nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid); NC *nc4_find_nc_file(int ncid, NC_HDF5_FILE_INFO_T**); int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, NC_GRP_INFO_T **dim_grp); +int nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var); int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len); int nc4_find_type(NC_HDF5_FILE_INFO_T *h5, int typeid1, NC_TYPE_INFO_T **type); NC_TYPE_INFO_T *nc4_rec_find_nc_type(NC_GRP_INFO_T *start_grp, hid_t target_nc_typeid); @@ -357,6 +356,10 @@ int nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp); int nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size, const char *name, const void *value); +/* Break & reform coordinate variables */ +int nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T *dim); +int nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T *dim); + int NC_check_name(const char *name); /* Check and normalize names. */ diff --git a/libsrc4/nc4dim.c b/libsrc4/nc4dim.c index f53fed4c2..bba142607 100644 --- a/libsrc4/nc4dim.c +++ b/libsrc4/nc4dim.c @@ -31,7 +31,7 @@ NC4_inq_unlimdim(int ncid, int *unlimdimidp) int found = 0; int retval; - LOG((2, "called nc_inq_unlimdim")); + LOG((2, "%s: called", __func__)); if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) return retval; @@ -74,7 +74,7 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp) char norm_name[NC_MAX_NAME + 1]; int retval = NC_NOERR; - LOG((2, "nc_def_dim: ncid 0x%x name %s len %d", ncid, name, + LOG((2, "%s: ncid 0x%x name %s len %d", __func__, ncid, name, (int)len)); /* Find our global metadata structure. */ @@ -137,7 +137,6 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp) return NC_ENOMEM; strcpy(grp->dim->name, norm_name); grp->dim->len = len; - grp->dim->dirty++; if (len == NC_UNLIMITED) grp->dim->unlimited++; @@ -160,7 +159,7 @@ NC4_inq_dimid(int ncid, const char *name, int *idp) int finished = 0; int retval; - LOG((2, "nc_inq_dimid: ncid 0x%x name %s", ncid, name)); + LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name)); /* Find metadata for this file. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -204,7 +203,7 @@ NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp) NC_DIM_INFO_T *dim; int ret = NC_NOERR; - LOG((2, "nc_inq_dim: ncid 0x%x dimid %d", ncid, dimid)); + LOG((2, "%s: ncid 0x%x dimid %d", __func__, ncid, dimid)); /* Find our global metadata structure. */ if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -277,7 +276,7 @@ NC4_rename_dim(int ncid, int dimid, const char *name) if (!name) return NC_EINVAL; - LOG((2, "nc_rename_dim: ncid 0x%x dimid %d name %s", ncid, + LOG((2, "%s: ncid 0x%x dimid %d name %s", __func__, ncid, dimid, name)); /* Find info for this file and group, and set pointer to each. */ @@ -313,33 +312,21 @@ NC4_rename_dim(int ncid, int dimid, const char *name) if (!dim) return NC_EBADDIM; - /* If not in define mode, switch to it, unless the new name is - * shorter. (This is in accordance with the v3 interface.) */ -/* if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(dim->name)) */ -/* { */ -/* if (h5->cmode & NC_CLASSIC_MODEL) */ -/* return NC_ENOTINDEFINE; */ -/* if ((retval = NC4_redef(ncid))) */ -/* return retval; */ -/* } */ - - /* Save the old name, we'll need it to rename this object when we - * sync to HDF5 file. But if there already is an old_name saved, - * just stick with what we've got, since the user might be renaming - * the crap out of this thing, without ever syncing with the - * file. When the sync does take place, we only need the original - * name of the dim, not any of the intermediate ones. If the user - * could just make up his mind, we could all get on to writing some - * data... */ - if (!dim->old_name) + /* Check for renaming dimension w/o variable */ + if (dim->hdf_dimscaleid) { - dim->old_name = dim->name; - dim->name = NULL; - } + /* Sanity check */ + assert(!dim->coord_var); - /* Check if this is a coordinate variable, and if so, mark it dirty */ - if (dim->coord_var) - dim->coord_var->dirty++; + /* Close the HDF5 dataset */ + if (H5Dclose(dim->hdf_dimscaleid) < 0) + return NC_EHDFERR; + dim->hdf_dimscaleid = 0; + + /* Now delete the dataset (it will be recreated later, if necessary) */ + if (H5Gunlink(grp->hdf_grpid, dim->name) < 0) + return NC_EDIMMETA; + } /* Give the dimension its new name in metadata. UTF8 normalization * has been done. */ @@ -349,6 +336,37 @@ NC4_rename_dim(int ncid, int dimid, const char *name) return NC_ENOMEM; strcpy(dim->name, norm_name); + /* Check if dimension was a coordinate variable, but names are different now */ + if (dim->coord_var && strcmp(dim->name, dim->coord_var->name)) + { + /* Break up the coordinate variable */ + if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim))) + return retval; + } + + /* Check if dimension should become a coordinate variable */ + if (!dim->coord_var) + { + NC_VAR_INFO_T *var; + + /* Attempt to find a variable with the same name as the dimension in + * the current group. */ + if ((retval = nc4_find_var(grp, dim->name, &var))) + return retval; + + /* Check if we found a variable and the variable has the dimension in + * index 0. */ + if (var && var->dim[0] == dim) + { + /* Sanity check */ + assert(var->dimids[0] == dim->dimid); + + /* Reform the coordinate variable */ + if ((retval = nc4_reform_coord_var(grp, var, dim))) + return retval; + } + } + return NC_NOERR; } @@ -366,7 +384,7 @@ NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) int num_unlim = 0; int retval; - LOG((2, "nc_inq_unlimdims: ncid 0x%x", ncid)); + LOG((2, "%s: ncid 0x%x", __func__, ncid)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) diff --git a/libsrc4/nc4file.c b/libsrc4/nc4file.c index c99621ede..0f38c1baf 100644 --- a/libsrc4/nc4file.c +++ b/libsrc4/nc4file.c @@ -15,7 +15,7 @@ COPYRIGHT file for copying and redistribution conditions. #include "nc4internal.h" #include "nc4dispatch.h" -#include +#include "H5DSpublic.h" #ifdef USE_HDF4 #include @@ -44,8 +44,7 @@ extern int num_spaces; /* Forward */ static int NC4_enddef(int ncid); -static int nc4_rec_read_types(NC_GRP_INFO_T *grp); -static int nc4_rec_read_vars(NC_GRP_INFO_T *grp); +static int nc4_rec_read_metadata(NC_GRP_INFO_T *grp); static int close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort); #ifdef IGNORE @@ -163,7 +162,7 @@ nc_check_for_hdf(const char *path, int use_parallel, MPI_Comm comm, MPI_Info inf char blob[MAGIC_NUMBER_LEN]; assert(hdf_file && path); - LOG((3, "nc_check_for_hdf: path %s", path)); + LOG((3, "%s: path %s", __func__, path)); /* HDF5 function handles possible user block at beginning of file */ if(H5Fis_hdf5(path)) @@ -237,7 +236,7 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info, else flags = H5F_ACC_TRUNC; - LOG((3, "nc4_create_file: path %s mode 0x%x", path, cmode)); + LOG((3, "%s: path %s mode 0x%x", __func__, path, cmode)); assert(nc && path); /* If this file already exists, and NC_NOCLOBBER is specified, @@ -322,8 +321,8 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info, if (H5Pset_cache(fapl_id, 0, nc4_chunk_cache_nelems, nc4_chunk_cache_size, nc4_chunk_cache_preemption) < 0) BAIL(NC_EHDFERR); - LOG((4, "nc4_create_file: set HDF raw chunk cache to size %d nelems %d preemption %f", - nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption)); + LOG((4, "%s: set HDF raw chunk cache to size %d nelems %d preemption %f", + __func__, nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption)); #endif /* USE_PARALLEL */ if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) @@ -382,14 +381,6 @@ exit: /*failure exit*/ if (fapl_id != H5P_DEFAULT) H5Pclose(fapl_id); if(!nc4_info) return retval; close_netcdf4_file(nc4_info,1); /* treat like abort */ -#if 0 - if (nc4_info->hdfid > 0) H5Fclose(nc4_info->hdfid); - if (nc4_info->root_grp) { - free(nc4_info->root_grp->name); - free(nc4_info->root_grp); - } - free(nc4_info); -#endif return retval; } @@ -419,8 +410,8 @@ NC4_create(const char* path, int cmode, size_t initialsz, int basepe, assert(nc_file && path); - LOG((1, "nc4_create_file: path %s cmode 0x%x comm %d info %d", - path, cmode, comm, info)); + LOG((1, "%s: path %s cmode 0x%x comm %d info %d", + __func__, path, cmode, comm, info)); #ifdef USE_PARALLEL if (mpidata) @@ -487,13 +478,11 @@ NC4_create(const char* path, int cmode, size_t initialsz, int basepe, * which does not have any coordinate data. */ static int read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, - hsize_t scale_size, hsize_t max_scale_size, - int *dim_without_var) + const H5G_stat_t *statbuf, hsize_t scale_size, hsize_t max_scale_size, + NC_DIM_INFO_T **dim) { - /*char *start_of_len;*/ char dimscale_name_att[NC_MAX_NAME + 1] = ""; - hid_t attid = 0; - int max_len; + htri_t attr_exists; int retval; /* Add a dimension for this scale. */ @@ -506,21 +495,28 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, /* Does this dataset have a hidden attribute that tells us its * dimid? If so, read it. */ - H5E_BEGIN_TRY { + if ((attr_exists = H5Aexists(datasetid, NC_DIMID_ATT_NAME)) < 0) + return NC_EHDFERR; + if (attr_exists) + { + hid_t attid; + if ((attid = H5Aopen_by_name(datasetid, ".", NC_DIMID_ATT_NAME, H5P_DEFAULT, H5P_DEFAULT)) > 0) { if (H5Aread(attid, H5T_NATIVE_INT, &grp->dim->dimid) < 0) + { + H5Aclose(attid); return NC_EHDFERR; + } if (H5Aclose(attid) < 0) return NC_EHDFERR; } - } H5E_END_TRY; + } - max_len = strlen(obj_name) > NC_MAX_NAME ? NC_MAX_NAME : strlen(obj_name); - if (!(grp->dim->name = malloc((max_len + 1) * sizeof(char)))) + if (!(grp->dim->name = malloc((strlen(obj_name) + 1) * sizeof(char)))) return NC_ENOMEM; - strncpy(grp->dim->name, obj_name, max_len + 1); + strcpy(grp->dim->name, obj_name); if (SIZEOF_SIZE_T < 8 && scale_size > NC_MAX_UINT) { grp->dim->len = NC_MAX_UINT; @@ -528,7 +524,10 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, } else grp->dim->len = scale_size; - grp->dim->hdf_dimscaleid = datasetid; + grp->dim->hdf5_objid.fileno[0] = statbuf->fileno[0]; + grp->dim->hdf5_objid.fileno[1] = statbuf->fileno[1]; + grp->dim->hdf5_objid.objno[0] = statbuf->objno[0]; + grp->dim->hdf5_objid.objno[1] = statbuf->objno[1]; /* If the dimscale has an unlimited dimension, then this dimension * is unlimited. */ @@ -550,10 +549,16 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, return retval; grp->dim->len = *lenp; } - (*dim_without_var)++; + + /* Hold open the dataset, since the dimension doesn't have a coordinate variable */ + grp->dim->hdf_dimscaleid = datasetid; + H5Iinc_ref(grp->dim->hdf_dimscaleid); /* Increment number of objects using ID */ } } + /* Set the dimension created */ + *dim = grp->dim; + return NC_NOERR; } @@ -563,6 +568,7 @@ static int read_coord_dimids(NC_VAR_INFO_T *var) { hid_t coord_att_typeid = -1, coord_attid = -1, spaceid = -1; + hssize_t npoints; int ret = 0; /* There is a hidden attribute telling us the ids of the @@ -570,15 +576,20 @@ read_coord_dimids(NC_VAR_INFO_T *var) * variable. Read it. */ if ((coord_attid = H5Aopen_name(var->hdf_datasetid, COORDINATES)) < 0) ret++; if (!ret && (coord_att_typeid = H5Aget_type(coord_attid)) < 0) ret++; - if (!ret && H5Aread(coord_attid, coord_att_typeid, var->dimids) < 0) ret++; - LOG((4, "dimscale %s is multidimensional and has coords", var->name)); /* How many dimensions are there? */ - if ((spaceid = H5Aget_space(coord_attid)) < 0) ret++; + if (!ret && (spaceid = H5Aget_space(coord_attid)) < 0) ret++; #ifdef EXTRA_TESTS num_spaces++; #endif - if (H5Sget_simple_extent_npoints(spaceid) < 0) ret++; + if (!ret && (npoints = H5Sget_simple_extent_npoints(spaceid)) < 0) ret++; + + /* Check that the number of points is the same as the number of dimensions + * for the variable */ + if (npoints != var->ndims) ret++; + + if (!ret && H5Aread(coord_attid, coord_att_typeid, var->dimids) < 0) ret++; + LOG((4, "dimscale %s is multidimensional and has coords", var->name)); /* Set my HDF5 IDs free! */ if (spaceid >= 0 && H5Sclose(spaceid) < 0) ret++; @@ -603,8 +614,6 @@ dimscale_visitor(hid_t did, unsigned dim, hid_t dsid, return -1; /* Pass this information back to caller. */ -/* (*(HDF5_OBJID_T *)dimscale_hdf5_objids).fileno = statbuf.fileno; - (*(HDF5_OBJID_T *)dimscale_hdf5_objids).objno = statbuf.objno;*/ (*(HDF5_OBJID_T *)dimscale_hdf5_objids).fileno[0] = statbuf.fileno[0]; (*(HDF5_OBJID_T *)dimscale_hdf5_objids).fileno[1] = statbuf.fileno[1]; (*(HDF5_OBJID_T *)dimscale_hdf5_objids).objno[0] = statbuf.objno[0]; @@ -736,9 +745,6 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid, NC_TYPE_INFO_T *type; htri_t is_str, equal = 0; hid_t class, native_typeid, hdf_typeid; -#if 0 - nc_type my_nc_type = 0; -#endif H5T_order_t order; int endianness; nc_type nc_type_constant[NUM_TYPES] = {NC_CHAR, NC_BYTE, NC_SHORT, NC_INT, NC_FLOAT, @@ -813,12 +819,7 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid, if ((equal = H5Tequal(native_typeid, native_type_constant[t])) < 0) return NC_EHDFERR; if (equal) - { -#if 0 - my_nc_type = nc_type_constant[t]; -#endif break; - } } /* Find out about endianness. */ @@ -888,9 +889,8 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att) size_t fixed_size = 0; assert(att->name); - LOG((5, "read_hdf5_att: att->attnum %d att->name %s " - "att->xtype %d att->len %d", att->attnum, att->name, - att->xtype, att->len)); + LOG((5, "%s: att->attnum %d att->name %s att->xtype %d att->len %d", + __func__, att->attnum, att->name, att->xtype, att->len)); /* Get type of attribute in file. */ if ((file_typeid = H5Aget_type(attid)) < 0) @@ -923,12 +923,9 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att) /* If both att_ndims and att_npoints are zero, then this is a * zero length att. */ if (att_ndims == 0 && att_npoints == 0) - { dims[0] = 0; - } - else if (att->xtype == NC_STRING) { + else if (att->xtype == NC_STRING) dims[0] = att_npoints; - } else if (att->xtype == NC_CHAR) { /* NC_CHAR attributes are written as a scalar in HDF5, of type @@ -1073,11 +1070,11 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att) * stash it in the group's list of types. Return the netcdf typeid * through a pointer, if caller desires it. */ static int -read_type(NC_GRP_INFO_T *grp, char *type_name) +read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name) { NC_TYPE_INFO_T *type; H5T_class_t class; - hid_t hdf_typeid, native_typeid = 0; + hid_t native_typeid = 0; int nmembers; hid_t member_hdf_typeid, base_hdf_typeid = 0; char *member_name = NULL; @@ -1091,13 +1088,7 @@ read_type(NC_GRP_INFO_T *grp, char *type_name) assert(grp && type_name); - if (strlen(type_name) > NC_MAX_NAME) - return NC_EBADNAME; - - LOG((4, "read_type: type_name %s grp->name %s", type_name, grp->name)); - - if ((hdf_typeid = H5Topen2(grp->hdf_grpid, type_name, H5P_DEFAULT)) < 0) - return NC_EHDFERR; + LOG((4, "%s: type_name %s grp->name %s", __func__, type_name, grp->name)); /* What is the native type for this platform? */ if ((native_typeid = H5Tget_native_type(hdf_typeid, H5T_DIR_DEFAULT)) < 0) @@ -1193,6 +1184,7 @@ read_type(NC_GRP_INFO_T *grp, char *type_name) type->base_nc_type = base_nc_type; type->committed++; type->hdf_typeid = hdf_typeid; + H5Iinc_ref(type->hdf_typeid); /* Increment number of objects using ID */ type->native_typeid = native_typeid; /* Read info about each member of this compound type. */ @@ -1323,9 +1315,11 @@ read_type(NC_GRP_INFO_T *grp, char *type_name) * including the attributes. */ static int read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, - size_t ndims, int is_scale, int num_scales, hid_t access_pid) + size_t ndims, NC_DIM_INFO_T *dim) { NC_VAR_INFO_T *var = NULL; + hid_t access_pid = 0; + int incr_id_rc = 0; /* Whether the dataset ID's ref count has been incremented */ int natts, a, d; NC_ATT_INFO_T *att; @@ -1347,7 +1341,7 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, int f; assert(obj_name && grp); - LOG((4, "read_var: obj_name %s", obj_name)); + LOG((4, "%s: obj_name %s", __func__, obj_name)); /* Add a variable to the end of the group's var list. */ if ((retval = nc4_var_list_add(&grp->var, &var))) @@ -1358,6 +1352,8 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, /* Fill in what we already know. */ var->hdf_datasetid = datasetid; + H5Iinc_ref(var->hdf_datasetid); /* Increment number of objects using ID */ + incr_id_rc++; /* Indicate that we've incremented the ref. count (for errors) */ var->varid = grp->nvars++; var->created++; var->ndims = ndims; @@ -1372,27 +1368,45 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, return NC_ENOMEM; } + /* Get the current chunk cache settings. */ + if ((access_pid = H5Dget_access_plist(datasetid)) < 0) + BAIL(NC_EVARMETA); +#ifdef EXTRA_TESTS + num_plists++; +#endif + /* Learn about current chunk cache settings. */ if ((H5Pget_chunk_cache(access_pid, &(var->chunk_cache_nelems), &(var->chunk_cache_size), &rdcc_w0)) < 0) return NC_EHDFERR; var->chunk_cache_preemption = rdcc_w0; - /* Allocate space for the name. */ - if (!(var->name = malloc((strlen(obj_name) + 1) * sizeof(char)))) - return NC_ENOMEM; - /* Check for a weird case: a non-coordinate variable that has the * same name as a dimension. It's legal in netcdf, and requires * that the HDF5 dataset name be changed. */ - if (!strncmp(obj_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND))) + if (strlen(obj_name) > strlen(NON_COORD_PREPEND) && + !strncmp(obj_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND))) { - if (strlen(obj_name) > NC_MAX_NAME) - return NC_EMAXNAME; + /* Allocate space for the name. */ + if (!(var->name = malloc(((strlen(obj_name) - strlen(NON_COORD_PREPEND))+ 1) * sizeof(char)))) + return NC_ENOMEM; + strcpy(var->name, &obj_name[strlen(NON_COORD_PREPEND)]); + + /* Allocate space for the HDF5 name. */ + if (!(var->hdf5_name = malloc((strlen(obj_name) + 1) * sizeof(char)))) + return NC_ENOMEM; + + strcpy(var->hdf5_name, obj_name); } else + { + /* Allocate space for the name. */ + if (!(var->name = malloc((strlen(obj_name) + 1) * sizeof(char)))) + return NC_ENOMEM; + strcpy(var->name, obj_name); + } /* Find out what filters are applied to this HDF5 dataset, * fletcher32, deflate, and/or shuffle. All other filters are @@ -1415,10 +1429,8 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, for (d = 0; d < var->ndims; d++) var->chunksizes[d] = chunksize[d]; } - else if (layout == H5D_CONTIGUOUS) + else if (layout == H5D_CONTIGUOUS || layout == H5D_COMPACT) var->contiguous++; - else if (layout == H5D_COMPACT) - var->contiguous++; /* The possible values of filter (which is just an int) can be * found in H5Zpublic.h. */ @@ -1497,10 +1509,8 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, else var->no_fill = 1; - /* If it's a scale, mark it as such. If not, allocate space to - * remember whether the dimscale has been attached for each - * dimension. */ - if (is_scale) + /* If it's a scale, mark it as such. */ + if (dim) { assert(ndims); var->dimscale++; @@ -1511,41 +1521,46 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, } else { - var->dimids[0] = grp->dim->dimid; - var->dim[0] = grp->dim; - if(0 == strcmp(var->name, grp->dim->name)) { - grp->dim->coord_var = var; - grp->dim->coord_var_in_grp++; - } /* end if */ + /* sanity check */ + assert(0 == strcmp(var->name, dim->name)); + + var->dimids[0] = dim->dimid; + var->dim[0] = dim; } + dim->coord_var = var; } - else - if (num_scales && ndims && - !(var->dimscale_attached = calloc(ndims, sizeof(int)))) - BAIL(NC_ENOMEM); - - /* If this is not a scale, and has scales, iterate + /* If this is not a scale, but has scales, iterate * through them. (i.e. this is a variable that is not a * coordinate variable) */ - if (!is_scale && num_scales) + else { - /* Store id information allowing us to match hdf5 - * dimscales to netcdf dimensions. */ - if (!(var->dimscale_hdf5_objids = malloc(ndims * sizeof(struct hdf5_objid)))) - BAIL(NC_ENOMEM); - for (d = 0; d < var->ndims; d++) + int num_scales = 0; + + /* Find out how many scales are attached to this + * dataset. H5DSget_num_scales returns an error if there are no + * scales, so convert a negative return value to zero. */ + num_scales = H5DSget_num_scales(datasetid, 0); + if (num_scales < 0) + num_scales = 0; + + if (num_scales && ndims) { - LOG((5, "read_var: about to iterate over scales for dim %d", d)); - if (H5DSiterate_scales(var->hdf_datasetid, d, NULL, dimscale_visitor, - &(var->dimscale_hdf5_objids[d])) < 0) - BAIL(NC_EHDFERR); -/* LOG((5, "read_var: collected scale info for dim %d " - "var %s fileno[0] %d objno[0] %d fileno[1] %d objno[1] %d", - d, var->name, var->dimscale_hdf5_objids[d].fileno[0], - var->dimscale_hdf5_objids[d].objno[0], - var->dimscale_hdf5_objids[d].fileno[1], - var->dimscale_hdf5_objids[d].objno[1]));*/ - var->dimscale_attached[d]++; + /* Allocate space to remember whether the dimscale has been attached + * for each dimension. */ + if (NULL == (var->dimscale_attached = calloc(ndims, sizeof(int)))) + BAIL(NC_ENOMEM); + + /* Store id information allowing us to match hdf5 + * dimscales to netcdf dimensions. */ + if (NULL == (var->dimscale_hdf5_objids = malloc(ndims * sizeof(struct hdf5_objid)))) + BAIL(NC_ENOMEM); + for (d = 0; d < var->ndims; d++) + { + if (H5DSiterate_scales(var->hdf_datasetid, d, NULL, dimscale_visitor, + &(var->dimscale_hdf5_objids[d])) < 0) + BAIL(NC_EHDFERR); + var->dimscale_attached[d]++; + } } } @@ -1566,52 +1581,44 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, BAIL(NC_EATTMETA); if (H5Aget_name(attid, NC_MAX_HDF5_NAME, att_name) < 0) BAIL(NC_EATTMETA); - LOG((4, "read_var: a %d att_name %s", a, att_name)); + LOG((4, "%s:: a %d att_name %s", __func__, a, att_name)); /* Should we ignore this attribute? */ if (strcmp(att_name, REFERENCE_LIST) && strcmp(att_name, CLASS) && strcmp(att_name, DIMENSION_LIST) && strcmp(att_name, NAME) && - strcmp(att_name, COORDINATES)) + strcmp(att_name, COORDINATES) && + strcmp(att_name, NC_DIMID_ATT_NAME)) { - /* Is this the hidden attribute that holds the netCDF - * dimension id for a coordinate variable? */ - if (!strcmp(att_name, NC_DIMID_ATT_NAME)) - { - - } - else - { - /* Add to the end of the list of atts for this var. */ - if ((retval = nc4_att_list_add(&var->att))) - BAIL(retval); - for (att = var->att; att->next; att = att->next) - ; - - /* Fill in the information we know. */ - att->attnum = var->natts++; - if (!(att->name = malloc((strlen(att_name) + 1) * sizeof(char)))) - BAIL(NC_ENOMEM); - strcpy(att->name, att_name); - - /* Read the rest of the info about the att, - * including its values. */ - if ((retval = read_hdf5_att(grp, attid, att))) + /* Add to the end of the list of atts for this var. */ + if ((retval = nc4_att_list_add(&var->att))) + BAIL(retval); + for (att = var->att; att->next; att = att->next) + ; + + /* Fill in the information we know. */ + att->attnum = var->natts++; + if (!(att->name = malloc((strlen(att_name) + 1) * sizeof(char)))) + BAIL(NC_ENOMEM); + strcpy(att->name, att_name); + + /* Read the rest of the info about the att, + * including its values. */ + if ((retval = read_hdf5_att(grp, attid, att))) + { + if (NC_EBADTYPID == retval) { - if (NC_EBADTYPID == retval) - { - if ((retval = nc4_att_list_del(&var->att, att))) - BAIL(retval); - continue; - } - else - BAIL(retval); + if ((retval = nc4_att_list_del(&var->att, att))) + BAIL(retval); + continue; } - - att->created++; - } /* endif not HDF5 att */ - } + else + BAIL(retval); + } + + att->created++; + } /* endif not HDF5 att */ } /* next attribute */ /* Is this a deflated variable with a chunksize greater than the @@ -1620,11 +1627,18 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, BAIL(retval); exit: - if (var && retval) + if (retval) { - if(nc4_var_list_del(&grp->var, var)) - BAIL2(NC_EHDFERR); + if (incr_id_rc && H5Idec_ref(datasetid) < 0) + BAIL2(NC_EHDFERR); + if (var && nc4_var_list_del(&grp->var, var)) + BAIL2(NC_EHDFERR); } + if (access_pid && H5Pclose(access_pid) < 0) + BAIL2(retval); +#ifdef EXTRA_TESTS + num_plists--; +#endif if (propid > 0 && H5Pclose(propid) < 0) BAIL2(NC_EHDFERR); #ifdef EXTRA_TESTS @@ -1705,32 +1719,18 @@ read_grp_atts(NC_GRP_INFO_T *grp) return retval; } -/* This function is called when nc4_rec_read_vars encounters an HDF5 +/* This function is called when nc4_rec_read_metadata encounters an HDF5 * dataset when reading a file. */ static int -read_dataset(NC_GRP_INFO_T *grp, const char *obj_name) +read_dataset(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name, + const H5G_stat_t *statbuf) { - hid_t datasetid = 0; - hid_t spaceid = 0, access_pid = 0; + NC_DIM_INFO_T *dim = NULL; /* Dimension created for scales */ + hid_t spaceid = 0; int ndims; - hsize_t *dims = NULL; - hsize_t *max_dims = NULL; int is_scale = 0; - int dim_without_var = 0; - int num_scales = 0; int retval = NC_NOERR; - /* Open this dataset. */ - if ((datasetid = H5Dopen2(grp->hdf_grpid, obj_name, H5P_DEFAULT)) < 0) - BAIL(NC_EVARMETA); - - /* Get the current chunk cache settings. */ - if ((access_pid = H5Dget_access_plist(datasetid)) < 0) - BAIL(NC_EVARMETA); -#ifdef EXTRA_TESTS - num_plists++; -#endif - /* Get the dimension information for this dataset. */ if ((spaceid = H5Dget_space(datasetid)) < 0) BAIL(NC_EHDFERR); @@ -1739,144 +1739,48 @@ read_dataset(NC_GRP_INFO_T *grp, const char *obj_name) #endif if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) BAIL(NC_EHDFERR); - -#if 0 - /* Removed check to remove nc4 dependency on - maximum dimensions. */ - if (ndims > NC_MAX_DIMS) - BAIL(NC_EMAXDIMS); -#endif - - if( (dims = (hsize_t*)malloc(sizeof(hsize_t)*ndims)) == NULL) - BAIL(errno); - if( (max_dims = (hsize_t*)malloc(sizeof(hsize_t)*ndims)) == NULL) - BAIL(errno); - - if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) - BAIL(NC_EHDFERR); /* Is this a dimscale? */ if ((is_scale = H5DSis_scale(datasetid)) < 0) BAIL(NC_EHDFERR); if (is_scale) { + hsize_t dims[H5S_MAX_RANK]; + hsize_t max_dims[H5S_MAX_RANK]; + + /* Query the scale's size & max. size */ + if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) + BAIL(NC_EHDFERR); + /* Read the scale information. */ - if ((retval = read_scale(grp, datasetid, obj_name, dims[0], - max_dims[0], &dim_without_var))) + if ((retval = read_scale(grp, datasetid, obj_name, statbuf, dims[0], + max_dims[0], &dim))) BAIL(retval); } - else - { - /* Find out how many scales are attached to this - * dataset. H5DSget_num_scales returns an error if there are no - * scales, so convert a negative return value to zero. */ - num_scales = H5DSget_num_scales(datasetid, 0); - if (num_scales < 0) - num_scales = 0; - } /* Add a var to the linked list, and get its metadata, * unless this is one of those funny dimscales that are a * dimension in netCDF but not a variable. (Spooky!) */ - if (!dim_without_var) - if ((retval = read_var(grp, datasetid, obj_name, ndims, - is_scale, num_scales, access_pid))) + if (NULL == dim || (dim && !dim->hdf_dimscaleid)) + if ((retval = read_var(grp, datasetid, obj_name, ndims, dim))) BAIL(retval); - if (access_pid && H5Pclose(access_pid) < 0) - BAIL2(retval); -#ifdef EXTRA_TESTS - num_plists--; -#endif - if (spaceid && H5Sclose(spaceid) < 0) - BAIL2(retval); -#ifdef EXTRA_TESTS - num_spaces--; -#endif - - if(dims) free(dims); - if(max_dims) free(max_dims); - - return NC_NOERR; - exit: - if (access_pid && H5Pclose(access_pid) < 0) - BAIL2(retval); -#ifdef EXTRA_TESTS - num_plists--; -#endif - if (datasetid && H5Dclose(datasetid) < 0) - BAIL2(retval); if (spaceid && H5Sclose(spaceid) <0) BAIL2(retval); #ifdef EXTRA_TESTS num_spaces--; #endif - if(dims) free(dims); - if(max_dims) free(max_dims); return retval; } -/* Given index, get the HDF5 name of an object and the class of the - * object (group, type, dataset, etc.). This function will try to use - * creation ordering, but if that fails it will use default - * (i.e. alphabetical) ordering. (This is necessary to read existing - * HDF5 archives without creation ordering). */ -/* static int */ -/* get_name_by_idx(NC_HDF5_FILE_INFO_T *h5, hid_t hdf_grpid, int i, */ -/* int *obj_class, char *obj_name) */ -/* { */ -/* H5O_info_t obj_info; */ -/* H5_index_t idx_field = H5_INDEX_CRT_ORDER; */ -/* ssize_t size; */ -/* herr_t res; */ - -/* /\* These HDF5 macros prevent an HDF5 error message when a */ -/* * non-creation-ordered HDF5 file is opened. *\/ */ -/* H5E_BEGIN_TRY { */ -/* res = H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, */ -/* i, &obj_info, H5P_DEFAULT); */ -/* } H5E_END_TRY; */ - -/* /\* Creation ordering not available, so make sure this file is */ -/* * opened for read-only access. This is a plain old HDF5 file being */ -/* * read by netCDF-4. *\/ */ -/* if (res < 0) */ -/* { */ -/* if (H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_NAME, H5_ITER_INC, */ -/* i, &obj_info, H5P_DEFAULT) < 0) */ -/* return NC_EHDFERR; */ -/* if (!h5->no_write) */ -/* return NC_ECANTWRITE; */ -/* h5->ignore_creationorder = 1; */ -/* idx_field = H5_INDEX_NAME; */ -/* } */ - -/* *obj_class = obj_info.type; */ -/* if ((size = H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i, */ -/* NULL, 0, H5P_DEFAULT)) < 0) */ -/* return NC_EHDFERR; */ -/* if (size > NC_MAX_NAME) */ -/* return NC_EMAXNAME; */ -/* if (H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i, */ -/* obj_name, size+1, H5P_DEFAULT) < 0) */ -/* return NC_EHDFERR; */ - -/* LOG((4, "get_name_by_idx: encountered HDF5 object obj_name %s", obj_name)); */ - -/* return NC_NOERR; */ -/* } */ - -#define USE_ITERATE_CODE -#ifdef USE_ITERATE_CODE - static int -nc4_rec_read_types_cb(hid_t grpid, const char *name, const H5L_info_t *info, +nc4_rec_read_metadata_cb(hid_t grpid, const char *name, const H5L_info_t *info, void *_op_data) { hid_t oid=-1; - H5I_type_t otype=-1; + H5G_stat_t statbuf; char oname[NC_MAX_NAME + 1]; NC_GRP_INFO_T *child_grp; NC_GRP_INFO_T *grp = (NC_GRP_INFO_T *) (_op_data); @@ -1886,46 +1790,77 @@ nc4_rec_read_types_cb(hid_t grpid, const char *name, const H5L_info_t *info, if ((oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0) return H5_ITER_ERROR; - if ((otype = H5Iget_type( oid ))<0) { - H5Oclose(oid); - return H5_ITER_ERROR; - } - H5Oclose(oid); - + /* Get more info about the object.*/ + if (H5Gget_objinfo(oid, ".", 1, &statbuf) < 0) + return H5_ITER_ERROR; + strncpy(oname, name, NC_MAX_NAME); - /* Deal with groups and types; ignore the rest. */ - if (otype == H5I_GROUP) + /* Deal with objects. */ + switch(statbuf.type) { - LOG((3, "found group %s", oname)); - if (nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++, - grp, grp->nc4_info->controller, oname, &child_grp)) - return H5_ITER_ERROR; - - if (nc4_rec_read_types(child_grp)) - return H5_ITER_ERROR; - } - else if (otype == H5I_DATATYPE) - { - LOG((3, "found datatype %s", oname)); - if (read_type(grp, oname)) - return H5_ITER_ERROR; + case H5G_GROUP: + LOG((3, "found group %s", oname)); + + /* Add group to file's hierarchy */ + if (nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++, + grp, grp->nc4_info->controller, oname, &child_grp)) + return H5_ITER_ERROR; + + /* Recursively read the child group's metadata */ + if (nc4_rec_read_metadata(child_grp)) + return H5_ITER_ERROR; + break; + + case H5G_DATASET: + { + int retval = NC_NOERR; + + LOG((3, "found dataset %s", oname)); + + /* Learn all about this dataset, which may be a dimscale + * (i.e. dimension metadata), or real data. */ + if ((retval = read_dataset(grp, oid, oname, &statbuf))) + { + /* Allow NC_EBADTYPID to transparently skip over datasets + * which have a datatype that netCDF-4 doesn't undertand + * (currently), but break out of iteration for other + * errors. + */ + if(NC_EBADTYPID != retval) + return H5_ITER_ERROR; + } + } + break; + + case H5G_TYPE: + LOG((3, "found datatype %s", oname)); + if (read_type(grp, oid, oname)) + return H5_ITER_ERROR; + break; + + default: + LOG((0, "Unknown object class %d in %s!", statbuf.type, __func__)); } + /* Close the object */ + if (H5Oclose(oid) < 0) + return H5_ITER_ERROR; + return (H5_ITER_CONT); } static int -nc4_rec_read_types(NC_GRP_INFO_T *grp) +nc4_rec_read_metadata(NC_GRP_INFO_T *grp) { hsize_t idx=0; - int res = 0; + int retval; hid_t pid = 0; unsigned crt_order_flags = 0; - NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; + H5_index_t iter_index; assert(grp && grp->name); - LOG((3, "nc4_rec_read_types: grp->name %s", grp->name)); + LOG((3, "%s: grp->name %s", __func__, grp->name)); /* Open this HDF5 group and retain its grpid. It will remain open * with HDF5 until this file is nc_closed. */ @@ -1946,135 +1881,33 @@ nc4_rec_read_types(NC_GRP_INFO_T *grp) } assert(grp->hdf_grpid > 0); + /* Get the group creation flags, to check for creation ordering */ pid = H5Gget_create_plist(grp->hdf_grpid); H5Pget_link_creation_order(pid, &crt_order_flags); - if(H5Pclose(pid) < 0) + if (H5Pclose(pid) < 0) return NC_EHDFERR; - - crt_order_flags = crt_order_flags & H5_INDEX_CRT_ORDER; - if (crt_order_flags == H5_INDEX_CRT_ORDER) + /* Set the iteration index to use */ + if (crt_order_flags & H5P_CRT_ORDER_TRACKED) + iter_index = H5_INDEX_CRT_ORDER; + else { - res = H5Literate(grp->hdf_grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, - &idx, nc4_rec_read_types_cb, (void *)grp); - } else - { - /* Without creation ordering, file must be read-only. */ - if (!idx && !h5->no_write) - return NC_ECANTWRITE; - - res = H5Literate(grp->hdf_grpid, H5_INDEX_NAME, H5_ITER_INC, - &idx, nc4_rec_read_types_cb, (void *)grp); + NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; + + /* Without creation ordering, file must be read-only. */ + if (!h5->no_write) + return NC_ECANTWRITE; + + iter_index = H5_INDEX_NAME; } - if (res<0) + + /* Iterate over links in this group, processing all the objects + * and recursively handling the types encountered + */ + if (H5Literate(grp->hdf_grpid, iter_index, H5_ITER_INC, &idx, + nc4_rec_read_metadata_cb, (void *)grp) < 0) return NC_EHDFERR; - return NC_NOERR; /* everything worked! */ -} -static int -nc4_rec_read_vars_cb(hid_t grpid, const char *name, const H5L_info_t *info, - void *_op_data) -{ - hid_t oid=-1; - H5I_type_t otype=-1; - char oname[NC_MAX_NAME + 1]; - NC_GRP_INFO_T *child_grp; - NC_GRP_INFO_T *grp = (NC_GRP_INFO_T *) (_op_data); -#if 0 - NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; -#endif - - memset(oname, 0, NC_MAX_NAME); - /* Open this critter. */ - if ((oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0) - return H5_ITER_ERROR; - - if ((otype = H5Iget_type( oid ))<0) { - H5Oclose(oid); - return H5_ITER_ERROR; - } - H5Oclose(oid); - - strncpy(oname, name, NC_MAX_NAME); - - /* Deal with datasets. */ - switch(otype) - { - case H5I_GROUP: - LOG((3, "re-encountering group %s", oname)); - - /* The NC_GROUP_INFO_T for this group already exists. Find it. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) - if (!strcmp(child_grp->name, oname)) - break; - if (!child_grp) - return H5_ITER_ERROR; - - /* Recursively read the child group's vars. */ - if (nc4_rec_read_vars(child_grp)) - return H5_ITER_ERROR; - break; - case H5I_DATASET: - { - int retval = NC_NOERR; - - LOG((3, "found dataset %s", oname)); - - /* Learn all about this dataset, which may be a dimscale - * (i.e. dimension metadata), or real data. */ - if ((retval = read_dataset(grp, oname))) { - if(NC_EBADTYPID == retval) - return H5_ITER_CONT; - else - return H5_ITER_ERROR; - } - } - break; - case H5I_DATATYPE: - LOG((3, "already handled type %s", oname)); - break; - default: - LOG((0, "Unknown object class %d in nc4_rec_read_vars!", otype)); - } - return (H5_ITER_CONT); -} - -static int -nc4_rec_read_vars(NC_GRP_INFO_T *grp) -{ - hsize_t idx = 0; - int retval = NC_NOERR; - int res = 0; - hid_t pid = 0; - unsigned crt_order_flags = 0; - NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; - - assert(grp && grp->name && grp->hdf_grpid > 0); - LOG((3, "nc4_rec_read_vars: grp->name %s", grp->name)); - - pid = H5Gget_create_plist(grp->hdf_grpid); - H5Pget_link_creation_order(pid, &crt_order_flags); - if(H5Pclose(pid) < 0) - return NC_EHDFERR; - - crt_order_flags = crt_order_flags & H5_INDEX_CRT_ORDER; - - if (crt_order_flags == H5_INDEX_CRT_ORDER) - { - res = H5Literate(grp->hdf_grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, - &idx, nc4_rec_read_vars_cb, (void *)grp); - } else - { - /* Without creation ordering, file must be read-only. */ - if (!idx && !h5->no_write) - return NC_ECANTWRITE; - - res = H5Literate(grp->hdf_grpid, H5_INDEX_NAME, H5_ITER_INC, - &idx, nc4_rec_read_vars_cb, (void *)grp); - } - if (res<0) - return NC_EHDFERR; - /* Scan the group for global (i.e. group-level) attributes. */ if ((retval = read_grp_atts(grp))) return retval; @@ -2082,243 +1915,6 @@ nc4_rec_read_vars(NC_GRP_INFO_T *grp) return NC_NOERR; /* everything worked! */ } -#else - -/** \internal -This struct is used to pass information back from the callback -function used with H5Literate. -*/ -struct nc_hdf5_link_info -{ - char name[NC_MAX_NAME + 1]; - H5I_type_t obj_type; -}; - -/* This is a callback function for H5Literate(). - -The parameters of this callback function have the following values or -meanings: - -g_id Group that serves as root of the iteration; same value as the -H5Lvisit group_id parameter - -name Name of link, relative to g_id, being examined at current step of -the iteration - -info H5L_info_t struct containing information regarding that link - -op_data User-defined pointer to data required by the application in -processing the link; a pass-through of the op_data pointer provided -with the H5Lvisit function call - -*/ -static herr_t -visit_link(hid_t g_id, const char *name, const H5L_info_t *info, - void *op_data) -{ - /* A positive return value causes the visit iterator to immediately - * return that positive value, indicating short-circuit - * success. The iterator can be restarted at the next group - * member. */ - int ret = 1; - hid_t id; - - /* Get the name, truncating at NC_MAX_NAME. */ - strncpy(((struct nc_hdf5_link_info *)op_data)->name, name, - NC_MAX_NAME); - - /* Open this critter. */ - if ((id = H5Oopen_by_addr(g_id, info->u.address)) < 0) - return NC_EHDFERR; - - /* Is this critter a group, type, data, attribute, or what? */ - if ((((struct nc_hdf5_link_info *)op_data)->obj_type = H5Iget_type(id)) < 0) - ret = NC_EHDFERR; - - /* Close the critter to release resouces. */ - if (H5Oclose(id) < 0) - return NC_EHDFERR; - - return ret; -} - -/* Iterate over one link in the group at a time, returning - * link_info. The creation_ordering and idx pointers keep track of - * whether creation ordering works and the most recently examined - * link. */ -static int -nc4_iterate_link(int *ordering_checked, int *creation_ordering, - hid_t grpid, hsize_t *idx, struct nc_hdf5_link_info *link_info) -{ - int res = 0; - - if (*creation_ordering) - { - /* These HDF5 macros prevent an HDF5 error message when a - * non-creation-ordered HDF5 file is opened. */ - H5E_BEGIN_TRY { - res = H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, - idx, visit_link, (void *)link_info); - if (res < 0 && *ordering_checked) - return NC_EHDFERR; - } H5E_END_TRY; - } - - if (!*creation_ordering || res < 0) - { - if (H5Literate(grpid, H5_INDEX_NAME, H5_ITER_INC, idx, - visit_link, link_info) != 1) - return NC_EHDFERR; - /* If it didn't work with creation ordering, but did without, - * then we don't have creation ordering. */ - *creation_ordering = 0; - } - - *ordering_checked = 1; - return NC_NOERR; -} - -/* Recursively open groups and read types. */ -int -nc4_rec_read_types(NC_GRP_INFO_T *grp) -{ - hsize_t num_obj, i; - NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info; - NC_GRP_INFO_T *child_grp; - hsize_t idx = 0; - struct nc_hdf5_link_info link_info; - int ordering_checked = 0; - int creation_ordering = 1; /* Assume we have it. */ - int retval = NC_NOERR; - - assert(grp && grp->name); - LOG((3, "nc4_rec_read_types: grp->name %s", grp->name)); - - /* Open this HDF5 group and retain its grpid. It will remain open - * with HDF5 until this file is nc_closed. */ - if (!grp->hdf_grpid) - { - if (grp->parent) - { - if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, - grp->name, H5P_DEFAULT)) < 0) - return NC_EHDFERR; - } - else - { - if ((grp->hdf_grpid = H5Gopen2(grp->nc4_info->hdfid, - "/", H5P_DEFAULT)) < 0) - return NC_EHDFERR; - } - } - assert(grp->hdf_grpid > 0); - - /* How many objects in this group? */ - if (H5Gget_num_objs(grp->hdf_grpid, &num_obj) < 0) - return NC_EVARMETA; - - /* For each object in the group... */ - for (i = 0; i < num_obj; i++) - { - if ((retval = nc4_iterate_link(&ordering_checked, &creation_ordering, - grp->hdf_grpid, &idx, &link_info))) - return retval; - - /* Without creation ordering, file must be read-only. */ - if (!i && !creation_ordering && !h5->no_write) - return NC_ECANTWRITE; - - /* Deal with groups and types; ignore the rest. */ - if (link_info.obj_type == H5I_GROUP) - { - LOG((3, "found group %s", link_info.name)); - if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++, - grp, grp->file, link_info.name, &child_grp))) - return retval; - if ((retval = nc4_rec_read_types(child_grp))) - return retval; - } - else if (link_info.obj_type == H5I_DATATYPE) - { - LOG((3, "found datatype %s", link_info.name)); - if ((retval = read_type(grp, link_info.name))) - return retval; - } - } - - return NC_NOERR; /* everything worked! */ -} - -/* This function recursively reads all the var and attribute metadata - in a HDF5 group, and creates and fills in the netCDF-4 global - metadata structure. */ -int -nc4_rec_read_vars(NC_GRP_INFO_T *grp) -{ - hsize_t num_obj, i; - NC_GRP_INFO_T *child_grp; - struct nc_hdf5_link_info link_info; - hsize_t idx = 0; - int ordering_checked = 0; - int creation_ordering = 1; /* Assume we have it. */ - int retval = NC_NOERR; - - assert(grp && grp->name && grp->hdf_grpid > 0); - LOG((3, "nc4_rec_read_vars: grp->name %s", grp->name)); - - /* How many objects in this group? */ - if (H5Gget_num_objs(grp->hdf_grpid, &num_obj) < 0) - return NC_EVARMETA; - - /* For each object in the group... */ - for (i = 0; i < num_obj; i++) - { - if ((retval = nc4_iterate_link(&ordering_checked, &creation_ordering, - grp->hdf_grpid, &idx, &link_info))) - return retval; - - /* Deal with datasets. */ - switch(link_info.obj_type) - { - case H5I_GROUP: - LOG((3, "re-encountering group %s", link_info.name)); - - /* The NC_GROUP_INFO_T for this group already exists. Find it. */ - for (child_grp = grp->children; child_grp; child_grp = child_grp->next) - if (!strcmp(child_grp->name, link_info.name)) - break; - if (!child_grp) - return NC_EHDFERR; - - /* Recursively read the child group's vars. */ - if ((retval = nc4_rec_read_vars(child_grp))) - return retval; - break; - case H5I_DATASET: - LOG((3, "found dataset %s", link_info.name)); - - /* Learn all about this dataset, which may be a dimscale - * (i.e. dimension metadata), or real data. */ - if ((retval = read_dataset(grp, link_info.name))) - return retval; - break; - case H5I_DATATYPE: - LOG((3, "already handled type %s", link_info.name)); - break; - default: - LOG((0, "Unknown object class %d in nc4_rec_read_vars!", - link_info.obj_type)); - } - } - - /* Scan the group for global (i.e. group-level) attributes. */ - if ((retval = read_grp_atts(grp))) - return retval; - - return NC_NOERR; /* everything worked! */ -} -#endif - /* Open a netcdf-4 file. Things have already been kicked off in * ncfunc.c in nc_open, but here the netCDF-4 part of opening a file * is handled. */ @@ -2336,7 +1932,7 @@ nc4_open_file(const char *path, int mode, MPI_Comm comm, int info_duped = 0; /* Whether the MPI Info object was duplicated */ #endif /* !USE_PARALLEL */ - LOG((3, "nc4_open_file: path %s mode %d", path, mode)); + LOG((3, "%s: path %s mode %d", __func__, path, mode)); assert(path && nc); /* Stop diskless open in its tracks */ if(mode & NC_DISKLESS) @@ -2403,8 +1999,8 @@ nc4_open_file(const char *path, int mode, MPI_Comm comm, if (H5Pset_cache(fapl_id, 0, nc4_chunk_cache_nelems, nc4_chunk_cache_size, nc4_chunk_cache_preemption) < 0) BAIL(NC_EHDFERR); - LOG((4, "nc4_open_file: set HDF raw chunk cache to size %d nelems %d preemption %f", - nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption)); + LOG((4, "%s: set HDF raw chunk cache to size %d nelems %d preemption %f", + __func__, nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption)); #endif /* USE_PARALLEL */ /* The NetCDF-3.x prototype contains an mode option NC_SHARE for @@ -2421,9 +2017,7 @@ nc4_open_file(const char *path, int mode, MPI_Comm comm, * information may be difficult to resolve here, if, for example, a * dataset of user-defined type is encountered before the * definition of that type. */ - if ((retval = nc4_rec_read_types(nc4_info->root_grp))) - BAIL(retval); - if ((retval = nc4_rec_read_vars(nc4_info->root_grp))) + if ((retval = nc4_rec_read_metadata(nc4_info->root_grp))) BAIL(retval); /* Now figure out which netCDF dims are indicated by the dimscale @@ -2457,14 +2051,6 @@ exit: if (fapl_id != H5P_DEFAULT) H5Pclose(fapl_id); if (!nc4_info) return retval; close_netcdf4_file(nc4_info,1); /* treat like abort*/ -#if 0 - if (nc4_info->hdfid > 0) H5Fclose(nc4_info->hdfid); - if (nc4_info->root_grp) { - free(nc4_info->root_grp->name); - free(nc4_info->root_grp); - } - free(nc4_info); -#endif return retval; } @@ -2558,7 +2144,7 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc) int retval; NC_HDF5_FILE_INFO_T* nc4_info = NULL; - LOG((3, "nc4_open_hdf4_file: path %s mode %d", path, mode)); + LOG((3, "%s: path %s mode %d", __func__, path, mode)); assert(path && nc); /* Must be read-only access to hdf4 files. */ @@ -2840,8 +2426,8 @@ NC4_open(const char *path, int mode, int basepe, size_t *chunksizehintp, assert(nc_file && path); - LOG((1, "nc_open_file: path %s mode %d comm %d info %d", - path, mode, comm, info)); + LOG((1, "%s: path %s mode %d comm %d info %d", + __func__, path, mode, comm, info)); #ifdef USE_PARALLEL if (mpidata) @@ -2936,7 +2522,7 @@ NC4_set_fill(int ncid, int fillmode, int *old_modep) NC *nc; NC_HDF5_FILE_INFO_T* nc4_info; - LOG((2, "nc_set_fill: ncid 0x%x fillmode %d", ncid, fillmode)); + LOG((2, "%s: ncid 0x%x fillmode %d", __func__, ncid, fillmode)); if (!(nc = nc4_find_nc_file(ncid,&nc4_info))) return NC_EBADID; @@ -2974,7 +2560,7 @@ NC4_redef(int ncid) //NC *nc; NC_HDF5_FILE_INFO_T* nc4_info; - LOG((1, "nc_redef: ncid 0x%x", ncid)); + LOG((1, "%s: ncid 0x%x", __func__, ncid)); /* Find this file's metadata. */ if (!(nc4_find_nc_file(ncid,&nc4_info))) @@ -3024,7 +2610,7 @@ static int NC4_enddef(int ncid) NC *nc; NC_HDF5_FILE_INFO_T* nc4_info; - LOG((1, "nc_enddef: ncid 0x%x", ncid)); + LOG((1, "%s: ncid 0x%x", __func__, ncid)); if (!(nc = nc4_find_nc_file(ncid,&nc4_info))) return NC_EBADID; @@ -3055,7 +2641,7 @@ sync_netcdf4_file(NC_HDF5_FILE_INFO_T *h5) int retval; assert(h5); - LOG((3, "sync_netcdf4_file")); + LOG((3, "%s", __func__)); /* If we're in define mode, that's an error, for strict nc3 rules, * otherwise, end define mode. */ @@ -3081,7 +2667,8 @@ sync_netcdf4_file(NC_HDF5_FILE_INFO_T *h5) if (!(h5->cmode & NC_NOWRITE)) { int bad_coord_order = 0; /* if detected, propagate to all groups to consistently store dimids */ - if ((retval = nc4_rec_write_types(h5->root_grp))) + + if ((retval = nc4_rec_write_groups_types(h5->root_grp))) return retval; if ((retval = nc4_rec_detect_need_to_preserve_dimids(h5->root_grp, &bad_coord_order))) return retval; @@ -3089,11 +2676,8 @@ sync_netcdf4_file(NC_HDF5_FILE_INFO_T *h5) return retval; } - H5Fflush(h5->hdfid, H5F_SCOPE_GLOBAL); - - /* Reread all the metadata. */ - /*if ((retval = nc4_rec_read_metadata(grp))) - return retval;*/ + if (H5Fflush(h5->hdfid, H5F_SCOPE_GLOBAL) < 0) + return NC_EHDFERR; return retval; } @@ -3107,7 +2691,7 @@ NC4_sync(int ncid) int retval; NC_HDF5_FILE_INFO_T* nc4_info; - LOG((2, "nc_sync: ncid 0x%x", ncid)); + LOG((2, "%s: ncid 0x%x", __func__, ncid)); if (!(nc = nc4_find_nc_file(ncid,&nc4_info))) return NC_EBADID; @@ -3140,8 +2724,7 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort) int retval = NC_NOERR; assert(h5 && h5->root_grp); - LOG((3, "close_netcdf4_file: h5->path %s abort %d", - h5->controller->path, abort)); + LOG((3, "%s: h5->path %s abort %d", __func__, h5->controller->path, abort)); /* According to the docs, always end define mode on close. */ if (h5->flags & NC_INDEF) @@ -3151,19 +2734,19 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort) * file. */ if (!h5->no_write && !abort) if ((retval = sync_netcdf4_file(h5))) - goto done; + goto exit; /* Delete all the list contents for vars, dims, and atts, in each * group. */ if ((retval = nc4_rec_grp_del(&h5->root_grp, h5->root_grp))) - goto done; + goto exit; /* Close hdf file. */ if (h5->hdf4) { #ifdef USE_HDF4 if (SDend(h5->sdid)) - {retval = NC_EHDFERR; goto done;} + BAIL_QUIET(NC_EHDFERR); #endif /* USE_HDF4 */ } else @@ -3180,10 +2763,11 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort) if (H5Fclose(h5->hdfid) < 0) { int nobjs; + nobjs = H5Fget_obj_count(h5->hdfid, H5F_OBJ_ALL); /* Apparently we can get an error even when nobjs == 0 */ if(nobjs < 0) { - {retval = NC_EHDFERR; goto done;} + BAIL_QUIET(NC_EHDFERR); } else if(nobjs > 0) { #ifdef LOGGING /* If the close doesn't work, probably there are still some HDF5 @@ -3192,12 +2776,12 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort) * out. */ LOG((0, "There are %d HDF5 objects open!", nobjs)); #endif - retval = NC_EHDFERR; goto done; + BAIL_QUIET(NC_EHDFERR); } } } -done: +exit: /* Free the nc4_info struct; above code should have reclaimed everything else */ if(h5 != NULL) @@ -3221,7 +2805,7 @@ NC4_abort(int ncid) int retval = NC_NOERR; NC_HDF5_FILE_INFO_T* nc4_info; - LOG((2, "nc_abort: ncid 0x%x", ncid)); + LOG((2, "%s: ncid 0x%x", __func__, ncid)); /* Find metadata for this file. */ if (!(nc = nc4_find_nc_file(ncid,&nc4_info))) @@ -3263,7 +2847,7 @@ NC4_close(int ncid) NC_HDF5_FILE_INFO_T *h5; int retval; - LOG((1, "nc_close: ncid 0x%x", ncid)); + LOG((1, "%s: ncid 0x%x", __func__, ncid)); /* Find our metadata for this file. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -3301,7 +2885,7 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp) NC_VAR_INFO_T *var; int retval; - LOG((2, "nc_inq: ncid 0x%x", ncid)); + LOG((2, "%s: ncid 0x%x", __func__, ncid)); /* Find file metadata. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -3361,7 +2945,7 @@ int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5) { assert(h5); - LOG((3, "nc4_enddef_netcdf4_file")); + LOG((3, "%s", __func__)); /* If we're not in define mode, return an error. */ if (!(h5->flags & NC_INDEF)) diff --git a/libsrc4/nc4grp.c b/libsrc4/nc4grp.c index 667a06597..a58a3ecc6 100644 --- a/libsrc4/nc4grp.c +++ b/libsrc4/nc4grp.c @@ -23,7 +23,7 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid) char norm_name[NC_MAX_NAME + 1]; int retval; - LOG((2, "nc_def_grp: parent_ncid 0x%x name %s", parent_ncid, name)); + LOG((2, "%s: parent_ncid 0x%x name %s", __func__, parent_ncid, name)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_grp_h5(parent_ncid, &grp, &h5))) @@ -98,19 +98,25 @@ NC4_rename_grp(int grpid, const char *name) if ((retval = NC4_redef(grpid))) return retval; - /* Save the old name, we'll need it to rename this object when we - * sync to HDF5 file. But if there already is an old_name saved, - * just stick with what we've got, since the user might be renaming - * the crap out of this thing, without ever syncing with the - * file. When the sync does take place, we only need the original - * name of the grp, not any of the intermediate ones. If the user - * could just make up his mind, we could all get on to writing some - * data... */ - if (!grp->old_name) + /* Rename the group, if it exists in the file */ + if (grp->hdf_grpid) { - if (!(grp->old_name = malloc((strlen(grp->name) + 1) * sizeof(char)))) - return NC_ENOMEM; - strcpy(grp->old_name, grp->name); + /* Close the group */ + if (H5Gclose(grp->hdf_grpid) < 0) + return NC_EHDFERR; + grp->hdf_grpid = 0; + + /* Attempt to rename & re-open the group, if the parent group is open */ + if (grp->parent->hdf_grpid) + { + /* Rename the group */ + if (H5Gmove(grp->parent->hdf_grpid, grp->name, name) < 0) + return NC_EHDFERR; + + /* Reopen the group, with the new name */ + if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, name, H5P_DEFAULT)) < 0) + return NC_EHDFERR; + } } /* Give the group its new name in metadata. UTF8 normalization diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index c34494c4a..bc5a8ebbf 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -51,7 +51,7 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) int retval; assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0); - LOG((3, "rec_reattach_scales: grp->name %s", grp->name)); + LOG((3, "%s: grp->name %s", __func__, grp->name)); /* If there are any child groups, attach dimscale there, if needed. */ for (child_grp = grp->children; child_grp; child_grp = child_grp->next) @@ -63,8 +63,8 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) for (d = 0; d < var->ndims; d++) if (var->dimids[d] == dimid && !var->dimscale) { - LOG((2, "rec_reattach_scaled: attaching scale for dimid %d to var %s", - var->dimids[d], var->name)); + LOG((2, "%s: attaching scale for dimid %d to var %s", + __func__, var->dimids[d], var->name)); if (var->created) { if (H5DSattach_scale(var->hdf_datasetid, dimscaleid, d) < 0) @@ -82,7 +82,7 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) * that case, I need to recreate the dim's dimension scale dataset, * and then I need to go to every var in the file which uses that * dimension, and attach the new dimension scale. */ -static int +int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) { NC_VAR_INFO_T *var; @@ -91,66 +91,32 @@ rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid) int retval; assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0); - LOG((3, "rec_detach_scales: grp->name %s", grp->name)); + LOG((3, "%s: grp->name %s", __func__, grp->name)); - /* If there are any child groups, attach dimscale there, if needed. */ + /* If there are any child groups, detach dimscale there, if needed. */ for (child_grp = grp->children; child_grp; child_grp = child_grp->next) if ((retval = rec_detach_scales(child_grp, dimid, dimscaleid))) return retval; - /* If there are no vars, we are done. */ - if (!grp->var) - return NC_NOERR; - - /* Find any (already created) vars that use this dimension id. Go - * through the list backwards to accomdate a HDF5 bug. */ - for (var = grp->var; var->next; var = var->next) - ; - - for ( ; var; var = var->prev) + /* Find any vars that use this dimension id. */ + for (var = grp->var; var; var = var->next) for (d = 0; d < var->ndims; d++) if (var->dimids[d] == dimid && !var->dimscale) { - LOG((2, "rec_detach_scales: detaching scale for dimid %d to var %s", - var->dimids[d], var->name)); + LOG((2, "%s: detaching scale for dimid %d to var %s", + __func__, var->dimids[d], var->name)); if (var->created) - { - if (var->dimscale_attached[d]) + if (var->dimscale_attached && var->dimscale_attached[d]) { if (H5DSdetach_scale(var->hdf_datasetid, dimscaleid, d) < 0) return NC_EHDFERR; var->dimscale_attached[d] = 0; } - } } return NC_NOERR; } -static int -getfullname(int grpid, NC_GRP_INFO_T* grp, char** fullnamep) -{ - int retval = NC_NOERR; - size_t len; - char* fullname = NULL; - retval = nc_inq_grpname_full(grpid,&len,NULL); - if(retval != NC_NOERR) goto done; - fullname = (char*)malloc(len+1); - if(fullname == NULL) - {retval = NC_ENOMEM; goto done;} - retval = nc_inq_grpname_full(grpid,&len,fullname); - if(retval != NC_NOERR) goto done; - fullname[len] = '\0'; -done: - if(retval != NC_NOERR) { - if(fullname) free(fullname); - } else { - if(fullnamep) *fullnamep = fullname; - } - return retval; -} - - /* Open the dataset and leave it open. */ int nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset) @@ -518,7 +484,7 @@ log_dim_info(NC_VAR_INFO_T *var, hsize_t *fdims, hsize_t *fmaxdims, int d2; /* Print some debugging info... */ - LOG((4, "nc4_put_vara: var name %s ndims %d", var->name, var->ndims)); + LOG((4, "%s: var name %s ndims %d", __func__, var->name, var->ndims)); LOG((4, "File space, and requested:")); for (d2 = 0; d2 < var->ndims; d2++) { @@ -548,8 +514,8 @@ set_par_access(NC_HDF5_FILE_INFO_T *h5, NC_VAR_INFO_T *var, hid_t xfer_plistid) if (H5Pset_dxpl_mpio(xfer_plistid, hdf5_xfer_mode) < 0) return NC_EPARINIT; - LOG((4, "hdf5_xfer_mode: %d H5FD_MPIO_COLLECTIVE: %d H5FD_MPIO_INDEPENDENT: %d", - (int)hdf5_xfer_mode, H5FD_MPIO_COLLECTIVE, H5FD_MPIO_INDEPENDENT)); + LOG((4, "%s: %d H5FD_MPIO_COLLECTIVE: %d H5FD_MPIO_INDEPENDENT: %d", + __func__, (int)hdf5_xfer_mode, H5FD_MPIO_COLLECTIVE, H5FD_MPIO_INDEPENDENT)); } return NC_NOERR; } @@ -593,8 +559,8 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, h5 = NC4_DATA(nc); assert(grp && h5 && var && var->name); - LOG((3, "nc4_put_vara: var->name %s mem_nc_type %d is_long %d", - var->name, mem_nc_type, is_long)); + LOG((3, "%s: var->name %s mem_nc_type %d is_long %d", + __func__, var->name, mem_nc_type, is_long)); /* Check some stuff about the type and the file. If the file must * be switched from define mode, it happens here. */ @@ -612,8 +578,8 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp, * a non-coordinate (and non-scalar) variable that has the same * name as a dimension. */ if (var->hdf5_name && strlen(var->hdf5_name) >= strlen(NON_COORD_PREPEND) && - strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 && - var->ndims) + strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 && + var->ndims) if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdf5_name, H5P_DEFAULT)) < 0) return NC_ENOTVAR; @@ -915,8 +881,8 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, h5 = NC4_DATA(nc); assert(grp && h5 && var && var->name); - LOG((3, "nc4_get_vara: var->name %s mem_nc_type %d is_long %d", - var->name, mem_nc_type, is_long)); + LOG((3, "%s: var->name %s mem_nc_type %d is_long %d", + __func__, var->name, mem_nc_type, is_long)); /* Check some stuff about the type and the file. */ if ((retval = check_for_vara(&mem_nc_type, var, h5))) @@ -933,8 +899,8 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp, * a non-coordinate (and non-scalar) variable that has the same * name as a dimension. */ if (var->hdf5_name && strlen(var->hdf5_name) >= strlen(NON_COORD_PREPEND) && - strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 && - var->ndims) + strncmp(var->hdf5_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)) == 0 && + var->ndims) if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdf5_name, H5P_DEFAULT)) < 0) return NC_ENOTVAR; @@ -1296,6 +1262,7 @@ static int write_netcdf4_dimid(hid_t datasetid, int dimid) { hid_t dimid_spaceid, dimid_attid; + htri_t attr_exists; /* Create the space. */ if ((dimid_spaceid = H5Screate(H5S_SCALAR)) < 0) @@ -1305,19 +1272,21 @@ write_netcdf4_dimid(hid_t datasetid, int dimid) #endif /* Does the attribute already exist? If so, don't try to create it. */ - H5E_BEGIN_TRY { + if ((attr_exists = H5Aexists(datasetid, NC_DIMID_ATT_NAME)) < 0) + return NC_EHDFERR; + if (attr_exists) dimid_attid = H5Aopen_by_name(datasetid, ".", NC_DIMID_ATT_NAME, H5P_DEFAULT, H5P_DEFAULT); - } H5E_END_TRY; + else + /* Create the attribute if needed. */ + dimid_attid = H5Acreate(datasetid, NC_DIMID_ATT_NAME, + H5T_NATIVE_INT, dimid_spaceid, H5P_DEFAULT); + if (dimid_attid < 0) + return NC_EHDFERR; - /* Create the attribute if needed. */ - if (dimid_attid < 0) - if ((dimid_attid = H5Acreate(datasetid, NC_DIMID_ATT_NAME, - H5T_NATIVE_INT, dimid_spaceid, H5P_DEFAULT)) < 0) - return NC_EHDFERR; /* Write it. */ - LOG((4, "write_netcdf4_dimid: writting secret dimid %d", dimid)); + LOG((4, "%s: writting secret dimid %d", __func__, dimid)); if (H5Awrite(dimid_attid, H5T_NATIVE_INT, &dimid) < 0) return NC_EHDFERR; @@ -1333,7 +1302,7 @@ write_netcdf4_dimid(hid_t datasetid, int dimid) return NC_NOERR; } -/* This function creates the HDF5 dataset for a variabale. */ +/* This function creates the HDF5 dataset for a variable. */ static int var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) { @@ -1346,7 +1315,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) char *name_to_use; int retval = NC_NOERR; - LOG((3, "var_create_dataset: name %s", var->name)); + LOG((3, "%s:: name %s", __func__, var->name)); /* Scalar or not, we need a creation property list. */ if ((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0) @@ -1542,7 +1511,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) /* At long last, create the dataset. */ name_to_use = var->hdf5_name ? var->hdf5_name : var->name; - LOG((4, "var_create_dataset: about to H5Dcreate dataset %s of type 0x%x", + LOG((4, "%s: about to H5Dcreate dataset %s of type 0x%x", __func__, name_to_use, typeid)); if ((var->hdf_datasetid = H5Dcreate2(grp->hdf_grpid, name_to_use, typeid, spaceid, H5P_DEFAULT, plistid, access_plistid)) < 0) @@ -1557,16 +1526,6 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) { if (H5DSset_scale(var->hdf_datasetid, var->name) < 0) BAIL(NC_EHDFERR); - for (dim = grp->dim; dim; dim = dim->next) - if (strcmp(dim->name, var->name) == 0) - { - dim->hdf_dimscaleid = var->hdf_datasetid; - break; - } - - /* Make sure we found a dimension, and gave it a dimscale id. */ - if (!dim || !dim->hdf_dimscaleid) - BAIL(NC_EDIMMETA); /* If this is a multidimensional coordinate variable, write a * coordinates attribute. */ @@ -1576,10 +1535,8 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, int write_dimid) /* If desired, write the netCDF dimid. */ if (write_dimid) - if ((retval = write_netcdf4_dimid(var->hdf_datasetid, - var->dimids[0]))) + if ((retval = write_netcdf4_dimid(var->hdf_datasetid, var->dimids[0]))) BAIL(retval); - } exit: @@ -1654,13 +1611,14 @@ put_att_grpa(NC_GRP_INFO_T *grp, int varid, NC_ATT_INFO_T *att) hid_t datasetid = 0, locid; hid_t attid = 0, spaceid = 0, file_typeid = 0; hsize_t dims[1]; /* netcdf attributes always 1-D. */ + htri_t attr_exists; int retval = NC_NOERR; void *data; int phoney_data = 99; assert(att->name); - LOG((3, "put_att_grpa: varid %d att->attnum %d att->name %s " - "att->xtype %d att->len %d", varid, att->attnum, att->name, + LOG((3, "%s: varid %d att->attnum %d att->name %s att->xtype %d att->len %d", + __func__, varid, att->attnum, att->name, att->xtype, att->len)); /* If the file is read-only, return an error. */ @@ -1678,9 +1636,13 @@ put_att_grpa(NC_GRP_INFO_T *grp, int varid, NC_ATT_INFO_T *att) } /* Delete the att if it exists already. */ - H5E_BEGIN_TRY { - H5Adelete(locid, att->name); - } H5E_END_TRY; + if ((attr_exists = H5Aexists(locid, att->name)) < 0) + return NC_EHDFERR; + if (attr_exists) + { + if (H5Adelete(locid, att->name) < 0) + return NC_EHDFERR; + } /* Get the length ready, and find the HDF type we'll be * writing. */ @@ -2028,9 +1990,18 @@ attach_dimscales(NC_GRP_INFO_T *grp) for (dim1 = g->dim; dim1; dim1 = dim1->next) if (var->dimids[d] == dim1->dimid) { - LOG((2, "attach_dimscales: attaching scale for dimid %d to var %s", - var->dimids[d], var->name)); - if (H5DSattach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0) + hid_t dim_datasetid; /* Dataset ID for dimension */ + + LOG((2, "%s: attaching scale for dimid %d to var %s", + __func__, var->dimids[d], var->name)); + + /* Find dataset ID for dimension */ + if (dim1->coord_var) + dim_datasetid = dim1->coord_var->hdf_datasetid; + else + dim_datasetid = dim1->hdf_dimscaleid; + assert(dim_datasetid > 0); + if (H5DSattach_scale(var->hdf_datasetid, dim_datasetid, d) < 0) BAIL(NC_EHDFERR); var->dimscale_attached[d]++; break; @@ -2052,6 +2023,7 @@ attach_dimscales(NC_GRP_INFO_T *grp) } } /* next d */ } + exit: return retval; } @@ -2067,7 +2039,7 @@ write_attlist(NC_ATT_INFO_T *attlist, int varid, NC_GRP_INFO_T *grp) { if (att->dirty) { - LOG((4, "write_attlist: writing att %s to varid %d", att->name, varid)); + LOG((4, "%s: writing att %s to varid %d", __func__, att->name, varid)); if ((retval = put_att_grpa(grp, varid, att))) return retval; att->dirty = 0; @@ -2077,114 +2049,31 @@ write_attlist(NC_ATT_INFO_T *attlist, int varid, NC_GRP_INFO_T *grp) return NC_NOERR; } -/* Using the HDF5 group iterator is more efficient than the original - * code (O(n) vs O(n**2) for n variables in the group) */ -#define USE_ITERATE_CODE -#ifdef USE_ITERATE_CODE -typedef struct { - char *name; /* The name of the object to searched*/ - int *exists; /* 1 if the object exists, 0 otherswise */ -} var_exists_iter_info; - -/*------------------------------------------------------------------------- - * Function: var_exists_cb - * - * Purpose: Callback routine for checking an object by its name - * - * Return: Exist: 1 - * Not exist: 0 - * Failure: -1 - * - * Programmer: Peter Cao - * 1/25/2012 - * - *------------------------------------------------------------------------- - */ -static int -var_exists_cb(hid_t grpid, const char *name, const H5L_info_t *info, - void *_op_data) -{ - var_exists_iter_info *iter_info = (var_exists_iter_info *)_op_data; - H5I_type_t otype; - hid_t oid; - - if ((oid = H5Oopen(grpid, name, H5P_DEFAULT)) < 0) - return H5_ITER_STOP; - - if ((otype = H5Iget_type( oid ))<0) { - H5Oclose(oid); - return H5_ITER_STOP; - } - H5Oclose(oid); - - if (otype == H5I_DATASET) { - if (!strcmp(iter_info->name, name)) { - *(iter_info->exists) = 1; - return (H5_ITER_STOP); - } - } - - return (H5_ITER_CONT); -} /* end var_exists_cb() */ - static int var_exists(hid_t grpid, char *name, int *exists) { - hsize_t num_obj; - var_exists_iter_info iter_info; - iter_info.name = name; - iter_info.exists = exists; + htri_t link_exists; - if (H5Gget_num_objs(grpid, &num_obj) < 0) - return NC_EVARMETA; - - if (!name) - return NC_NOERR; - - *exists = 0; - if (H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL, var_exists_cb, &iter_info) < 0) - return NC_EHDFERR; - - return NC_NOERR; -} -#else -static int -var_exists(hid_t grpid, char *name, int *exists) -{ - hsize_t num_obj, i; - H5O_info_t obj_info; - int obj_class; - char obj_name[NC_MAX_NAME + 1]; - ssize_t size; - int retval = NC_NOERR; - + /* Reset the boolean */ *exists = 0; - if (H5Gget_num_objs(grpid, &num_obj) < 0) - return NC_EVARMETA; - for (i = 0; i < num_obj; i++) + + /* Check if the object name exists in the group */ + if ((link_exists = H5Lexists(grpid, name, H5P_DEFAULT)) < 0) + return NC_EHDFERR; + if (link_exists) { - if (H5Oget_info_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0) + H5G_stat_t statbuf; + + /* Get info about the object */ + if (H5Gget_objinfo(grpid, name, 1, &statbuf) < 0) return NC_EHDFERR; - obj_class = obj_info.type; - if ((size = H5Lget_name_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, NULL, 0, H5P_DEFAULT)) < 0) - return NC_EHDFERR; - if (size > NC_MAX_NAME) - return NC_EMAXNAME; - if (H5Lget_name_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i, obj_name, size+1, H5P_DEFAULT) < 0) - return NC_EHDFERR; - if (obj_class == H5O_TYPE_DATASET) - { - if (!strncmp(name, obj_name, NC_MAX_NAME)) - { - *exists = 1; - return NC_NOERR; - } - } + + if (H5G_DATASET == statbuf.type) + *exists = 1; } - return retval; + return NC_NOERR; } -#endif /* USE_ITERATE_CODE */ /* This function writes a variable. The principle difficulty comes * from the possibility that this is a coordinate variable, and was @@ -2201,13 +2090,12 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) if (!var->dirty) { if (write_dimid && var->ndims) - if ((retval = write_netcdf4_dimid(var->hdf_datasetid, - var->dimids[0]))) + if ((retval = write_netcdf4_dimid(var->hdf_datasetid, var->dimids[0]))) BAIL(retval); } else { - LOG((4, "write_var: writing var %s", var->name)); + LOG((4, "%s: writing var %s", __func__, var->name)); if (var->created) replace_existing_var = 1; @@ -2226,26 +2114,30 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) * this object exists in the HDF group. */ if (var->dimscale) for (d1 = grp->dim; d1; d1 = d1->next) - if (!strcmp(d1->name, var->name) || - !strcmp(d1->old_name, var->name)) + if (!strcmp(d1->name, var->name)) { if ((retval = var_exists(grp->hdf_grpid, var->name, &exists))) return retval; if (exists) { + hid_t dim_datasetid; /* Dataset ID for dimension */ + + /* Indicate that the variable already exists */ replace_existing_var++; + /* Find dataset ID for dimension */ + if (d1->coord_var) + dim_datasetid = d1->coord_var->hdf_datasetid; + else + dim_datasetid = d1->hdf_dimscaleid; + assert(dim_datasetid > 0); + /* If we're replacing an existing dimscale dataset, go to - * every var in the file and detatch this dimension scale, + * every var in the file and detach this dimension scale, * because we have to delete it. */ if ((retval = rec_detach_scales(grp->nc4_info->root_grp, - var->dimids[0], d1->hdf_dimscaleid))) + var->dimids[0], dim_datasetid))) return retval; - - /* Check if this variable should no longer be a dimscale */ - /* (Because its dim was renamed) */ - if (!strcmp(d1->old_name, var->name)) - var->dimscale = 0; break; } } @@ -2253,15 +2145,8 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) /* Delete the HDF5 dataset that is to be replaced. */ if (replace_existing_var) { - /* If this is a dimension scale, do this stuff. */ - if (d1) - { - assert(d1 && d1->hdf_dimscaleid); - if (H5Dclose(d1->hdf_dimscaleid) < 0) - return NC_EDIMMETA; - d1->hdf_dimscaleid = 0; - } - else + /* If this is not a dimension scale, do this stuff. */ + if (!var->dimscale && var->dimscale_attached) { int dims_detached = 0; int finished = 0; @@ -2271,24 +2156,32 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) /* If this is a regular var, detach all its dim scales. */ for (d = 0; d < var->ndims; d++) - for (g = grp; g && !finished; g = g->parent) - for (dim1 = g->dim; dim1; dim1 = dim1->next) - if (var->dimids[d] == dim1->dimid) - { - if(var->hdf_datasetid != dim1->hdf_dimscaleid) - if (H5DSdetach_scale(var->hdf_datasetid, dim1->hdf_dimscaleid, d) < 0) - BAIL(NC_EHDFERR); - if(var->dimscale_attached) - var->dimscale_attached[d] = 0; - if (dims_detached++ == var->ndims) - finished++; - } - - /* Free the HDF5 dataset id. */ - if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) - BAIL(NC_EHDFERR); - var->hdf_datasetid = 0; + if (var->dimscale_attached[d]) + for (g = grp; g && !finished; g = g->parent) + for (dim1 = g->dim; dim1; dim1 = dim1->next) + if (var->dimids[d] == dim1->dimid) + { + hid_t dim_datasetid; /* Dataset ID for dimension */ + + /* Find dataset ID for dimension */ + if (dim1->coord_var) + dim_datasetid = dim1->coord_var->hdf_datasetid; + else + dim_datasetid = dim1->hdf_dimscaleid; + assert(dim_datasetid > 0); + + if (H5DSdetach_scale(var->hdf_datasetid, dim_datasetid, d) < 0) + BAIL(NC_EHDFERR); + var->dimscale_attached[d] = 0; + if (dims_detached++ == var->ndims) + finished++; + } } + + /* Free the HDF5 dataset id. */ + if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) + BAIL(NC_EHDFERR); + var->hdf_datasetid = 0; /* Now delete the variable. */ if (H5Gunlink(grp->hdf_grpid, var->name) < 0) @@ -2299,14 +2192,12 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) if ((retval = var_create_dataset(grp, var, write_dimid))) return retval; - /* Reattach this scale everywhere it is used. (Recall that - * netCDF dimscales are always 1-D). */ - /* (Only do this if the variable is still a dimscale) */ - if (d1 && replace_existing_var && var->dimscale) + /* If this is a dimension scale, reattach the scale everywhere it + * is used. (Recall that netCDF dimscales are always 1-D). */ + if (replace_existing_var && var->dimscale) { - d1->hdf_dimscaleid = var->hdf_datasetid; if ((retval = rec_reattach_scales(grp->nc4_info->root_grp, - var->dimids[0], d1->hdf_dimscaleid))) + var->dimids[0], var->hdf_datasetid))) return retval; } } @@ -2324,83 +2215,75 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, int write_dimid) static int write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid) { - hid_t spaceid, create_propid; - hsize_t dims[1], max_dims[1], chunk_dims[1] = {1}; - int dimscale_exists = 0; - char dimscale_wo_var[NC_MAX_NAME]; int retval; - if (dim->dirty) + /* If there's no dimscale dataset for this dim, create one, + * and mark that it should be hidden from netCDF as a + * variable. (That is, it should appear as a dimension + * without an associated variable.) */ + if (0 == dim->hdf_dimscaleid) { - /* If there's no dimscale dataset for this dim, create one, - * and mark that it should be hidden from netCDF as a - * variable. (That is, it should appear as a dimension - * without an associated variable.) */ - if (!dimscale_exists) + hid_t spaceid, create_propid; + hsize_t dims[1], max_dims[1], chunk_dims[1] = {1}; + char dimscale_wo_var[NC_MAX_NAME]; + + LOG((4, "%s: creating dim %s", __func__, dim->name)); + + /* Sanity check */ + assert(NULL == dim->coord_var); + + /* Create a property list. If this dimension scale is + * unlimited (i.e. it's an unlimited dimension), then set + * up chunking, with a chunksize of 1. */ + if ((create_propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) + BAIL(NC_EHDFERR); +#ifdef EXTRA_TESTS + num_plists++; +#endif + dims[0] = dim->len; + max_dims[0] = dim->len; + if (dim->unlimited) { - LOG((4, "write_dim: creating dim %s", dim->name)); - - /* Create a property list. If this dimension scale is - * unlimited (i.e. it's an unlimited dimension), then set - * up chunking, with a chunksize of 1. */ - if ((create_propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) + max_dims[0] = H5S_UNLIMITED; + if (H5Pset_chunk(create_propid, 1, chunk_dims) < 0) BAIL(NC_EHDFERR); -#ifdef EXTRA_TESTS - num_plists++; -#endif - dims[0] = dim->len; - max_dims[0] = dim->len; - if (dim->unlimited) - { - max_dims[0] = H5S_UNLIMITED; - if (H5Pset_chunk(create_propid, 1, chunk_dims) < 0) - BAIL(NC_EHDFERR); - } - - /* Set up space. */ - if ((spaceid = H5Screate_simple(1, dims, max_dims)) < 0) - BAIL(NC_EHDFERR); -#ifdef EXTRA_TESTS - num_spaces++; -#endif - - /* If we define, and then rename this dimension before - * creation of the dimscale dataset, then we can throw - * away the old_name of the dimension. */ - if (dim->old_name && strlen(dim->old_name)) - strcpy(dim->old_name, ""); - - if (H5Pset_attr_creation_order(create_propid, H5P_CRT_ORDER_TRACKED| - H5P_CRT_ORDER_INDEXED) < 0) - BAIL(NC_EHDFERR); - - /* Create the dataset that will be the dimension scale. */ - LOG((4, "write_dim: about to H5Dcreate a dimscale dataset %s", dim->name)); - if ((dim->hdf_dimscaleid = H5Dcreate1(grp->hdf_grpid, dim->name, H5T_IEEE_F32BE, - spaceid, create_propid)) < 0) - BAIL(NC_EHDFERR); - - /* Close the spaceid and create_propid. */ - if (H5Sclose(spaceid) < 0) - BAIL(NC_EHDFERR); -#ifdef EXTRA_TESTS - num_spaces--; -#endif - if (H5Pclose(create_propid) < 0) - BAIL(NC_EHDFERR); -#ifdef EXTRA_TESTS - num_plists--; -#endif - - /* Indicate that this is a scale. Also indicate that not - * be shown to the user as a variable. It is hidden. It is - * a DIM WITHOUT A VARIABLE! */ - sprintf(dimscale_wo_var, "%s%10d", DIM_WITHOUT_VARIABLE, (int)dim->len); - if (H5DSset_scale(dim->hdf_dimscaleid, dimscale_wo_var) < 0) - BAIL(NC_EHDFERR); - } - dim->dirty = 0; + + /* Set up space. */ + if ((spaceid = H5Screate_simple(1, dims, max_dims)) < 0) + BAIL(NC_EHDFERR); +#ifdef EXTRA_TESTS + num_spaces++; +#endif + + if (H5Pset_attr_creation_order(create_propid, H5P_CRT_ORDER_TRACKED| + H5P_CRT_ORDER_INDEXED) < 0) + BAIL(NC_EHDFERR); + + /* Create the dataset that will be the dimension scale. */ + LOG((4, "%s: about to H5Dcreate a dimscale dataset %s", __func__, dim->name)); + if ((dim->hdf_dimscaleid = H5Dcreate1(grp->hdf_grpid, dim->name, H5T_IEEE_F32BE, + spaceid, create_propid)) < 0) + BAIL(NC_EHDFERR); + + /* Close the spaceid and create_propid. */ + if (H5Sclose(spaceid) < 0) + BAIL(NC_EHDFERR); +#ifdef EXTRA_TESTS + num_spaces--; +#endif + if (H5Pclose(create_propid) < 0) + BAIL(NC_EHDFERR); +#ifdef EXTRA_TESTS + num_plists--; +#endif + + /* Indicate that this is a scale. Also indicate that not + * be shown to the user as a variable. It is hidden. It is + * a DIM WITHOUT A VARIABLE! */ + sprintf(dimscale_wo_var, "%s%10d", DIM_WITHOUT_VARIABLE, (int)dim->len); + if (H5DSset_scale(dim->hdf_dimscaleid, dimscale_wo_var) < 0) + BAIL(NC_EHDFERR); } /* Did we extend an unlimited dimension? */ @@ -2450,24 +2333,12 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid) } } - /* Did we rename this dimension? */ - if (dim->old_name && strlen(dim->old_name)) - { - /* Rename the dimension's dataset in the HDF5 file. */ - if (H5Gmove2(grp->hdf_grpid, dim->old_name, grp->hdf_grpid, dim->name) < 0) - return NC_EHDFERR; - - /* Reset old_name. */ - strcpy(dim->old_name, ""); - } - /* If desired, write the secret dimid. This will be used instead of * the dimid that the dimension would otherwise receive based on * creation order. This can be necessary when dims and their * coordinate variables were created in different order. */ if (write_dimid && dim->hdf_dimscaleid) - if ((retval = write_netcdf4_dimid(dim->hdf_dimscaleid, - dim->dimid))) + if ((retval = write_netcdf4_dimid(dim->hdf_dimscaleid, dim->dimid))) BAIL(retval); return NC_NOERR; @@ -2484,56 +2355,51 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, int write_dimid) int nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, int *bad_coord_orderp) { - NC_DIM_INFO_T *dim; NC_VAR_INFO_T *var; NC_GRP_INFO_T *child_grp; int last_dimid = -1; int retval; - /* If the user writes coord vars in a different order then he - * defined their dimensions, then, when the file is reopened, the - * order of the dimids will change to match the order of the coord - * vars. Detect if this is about to happen. */ + /* Iterate over variables in this group */ for (var = grp->var; var; var = var->next) { - LOG((5, "checking %s for out of order coord var", var->name)); - if (var->ndims && var->dimscale) + /* Only matters for dimension scale variables, with non-scalar dimensionality */ + if (var->dimscale && var->ndims) { + /* If the user writes coord vars in a different order then he + * defined their dimensions, then, when the file is reopened, the + * order of the dimids will change to match the order of the coord + * vars. Detect if this is about to happen. */ if (var->dimids[0] < last_dimid) - { - *bad_coord_orderp = 1; - return NC_NOERR; - } - last_dimid = var->dimids[0]; + { + LOG((5, "%s: %s is out of order coord var", __func__, var->name)); + *bad_coord_orderp = 1; + return NC_NOERR; + } + last_dimid = var->dimids[0]; + + /* If there are multidimensional coordinate variables defined, then + * it's also necessary to preserve dimension IDs when the file is + * reopened ... */ + if (var->ndims > 1) + { + LOG((5, "%s: %s is multidimensional coord var", __func__, var->name)); + *bad_coord_orderp = 1; + return NC_NOERR; + } + + /* Did the user define a dimension, end define mode, reenter define + * mode, and then define a coordinate variable for that dimension? + * If so, dimensions will be out of order. */ + if (var->dirty && !var->created) + { + LOG((5, "%s: coord var defined after enddef/redef", __func__)); + *bad_coord_orderp = 1; + return NC_NOERR; + } } } - /* If there are multidimensional coordinate variables defined, then - * it's also necessary to preserve dimension IDs when the file is - * reopened ... */ - for (var = grp->var; var; var = var->next) - { - LOG((5, "checking %s for multidimensional coord var", var->name)); - if (var->ndims > 1 && var->dimscale) - { - *bad_coord_orderp = 1; - return NC_NOERR; - } - } - - /* Did the user define a dimension, end define mode, reenter define - * mode, and then define a coordinate variable for that dimension? - * If so, dimensions will be out of order. */ - for (var = grp->var; var; var = var->next) - if (var->dirty && !var->created && var->ndims) - for (dim = grp->dim; dim; dim = dim->next) - if (!strcmp(dim->name, var->name) && !dim->dirty) - { - LOG((5, "coord var defined after enddef/redef")); - *bad_coord_orderp = 1; - return NC_NOERR; - } - /* If there are any child groups, check them also for this condition. */ for (child_grp = grp->children; child_grp; child_grp = child_grp->next) if ((retval = nc4_rec_detect_need_to_preserve_dimids(child_grp, bad_coord_orderp))) @@ -2557,7 +2423,7 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) int retval; assert(grp && grp->name && grp->hdf_grpid); - LOG((3, "nc4_rec_write_metadata: grp->name %s, bad_coord_order %d", grp->name, bad_coord_order)); + LOG((3, "%s: grp->name %s, bad_coord_order %d", __func__, grp->name, bad_coord_order)); /* Write global attributes for this group. */ if ((retval = write_attlist(grp->att, NC_GLOBAL, grp))) @@ -2581,15 +2447,15 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) * has an associated coord var. */ for (found_coord = 0; dim && !found_coord; dim = dim->prev) { - if (!dim->coord_var_in_grp) + if (!dim->coord_var) { if ((retval = write_dim(dim, grp, bad_coord_order))) return retval; } else { - found_coord++; coord_varid = dim->coord_var->varid; + found_coord++; } } @@ -2607,37 +2473,6 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, int bad_coord_order) if ((retval = attach_dimscales(grp))) return retval; - /* Rename this group */ - if (grp->old_name && strlen(grp->old_name)) - { - /* We need to get the full name for the new name and the old name */ - char* oldfullname = NULL; - char* newfullname = NULL; - char* tmp = NULL; - int nc_groupid = 0; - /* Construct the group's full ncid */ - nc_groupid = (grp->nc4_info->controller->ext_ncid) | (grp->nc_grpid); - /* Temporarily make group's name be old name so we can get the - old full name */ - tmp = grp->name; - grp->name = grp->old_name; - retval = getfullname(nc_groupid,grp,&oldfullname); - if(retval != NC_NOERR) goto done; - /* repeat for the new name */ - grp->name = tmp; - retval = getfullname(nc_groupid,grp,&newfullname); - if(retval != NC_NOERR) goto done; - - if(H5Lmove(grp->nc4_info->hdfid, oldfullname, grp->nc4_info->hdfid, newfullname, H5P_DEFAULT, H5P_DEFAULT) < 0) - {retval = NC_EHDFERR; goto done;} - /* Reset old_name. */ - strcpy(grp->old_name, ""); -done: - if(oldfullname) free(oldfullname); - if(newfullname) free(newfullname); - if(retval) return retval; - } - /* If there are any child groups, write their metadata. */ for (child_grp = grp->children; child_grp; child_grp = child_grp->next) if ((retval = nc4_rec_write_metadata(child_grp, bad_coord_order))) @@ -2648,14 +2483,14 @@ done: /* Recursively write all groups and types. */ int -nc4_rec_write_types(NC_GRP_INFO_T *grp) +nc4_rec_write_groups_types(NC_GRP_INFO_T *grp) { NC_GRP_INFO_T *child_grp; NC_TYPE_INFO_T *type; int retval; assert(grp && grp->name); - LOG((3, "nc4_rec_write_types: grp->name %s", grp->name)); + LOG((3, "%s: grp->name %s", __func__, grp->name)); /* Create the group in the HDF5 file if it doesn't exist. */ if (!grp->hdf_grpid) @@ -2675,7 +2510,7 @@ nc4_rec_write_types(NC_GRP_INFO_T *grp) /* If there are any child groups, write their groups and types. */ for (child_grp = grp->children; child_grp; child_grp = child_grp->next) - if ((retval = nc4_rec_write_types(child_grp))) + if ((retval = nc4_rec_write_groups_types(child_grp))) return retval; return NC_NOERR; @@ -2747,8 +2582,7 @@ nc4_pg_varm(NC_PG_T pg, NC *nc, int ncid, int varid, const size_t *start, int i; int retval = NC_NOERR; - LOG((3, "nc4_pg_varm: ncid 0x%x varid %d xtype %d", ncid, varid, - xtype)); + LOG((3, "%s: ncid 0x%x varid %d xtype %d", __func__, ncid, varid, xtype)); /* Find metadata for this file and var. */ assert(nc); @@ -3048,8 +2882,8 @@ nc4_convert_type(const void *src, void *dest, size_t count = 0; *range_error = 0; - LOG((3, "nc4_convert_type: len %d src_type %d dest_type %d src_long %d" - " dest_long %d", len, src_type, dest_type, src_long, dest_long)); + LOG((3, "%s: len %d src_type %d dest_type %d src_long %d dest_long %d", + __func__, len, src_type, dest_type, src_long, dest_long)); /* OK, this is ugly. If you can think of anything better, I'm open to suggestions! @@ -3069,7 +2903,7 @@ nc4_convert_type(const void *src, void *dest, *cp1++ = *cp++; break; default: - LOG((0, "nc4_convert_type: Uknown destination type.")); + LOG((0, "%s: Uknown destination type.", __func__)); } break; case NC_BYTE: @@ -3141,8 +2975,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *bp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3203,8 +3037,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *ubp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3276,8 +3110,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *sp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3341,8 +3175,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *usp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3432,8 +3266,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *lp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } } @@ -3522,8 +3356,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *ip++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } } @@ -3604,8 +3438,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *uip++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3689,8 +3523,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *lip++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3774,8 +3608,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *ulip++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3867,8 +3701,8 @@ nc4_convert_type(const void *src, void *dest, *dp++ = *fp++; break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; @@ -3964,14 +3798,14 @@ nc4_convert_type(const void *src, void *dest, } break; default: - LOG((0, "nc4_convert_type: unexpected dest type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected dest type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } break; default: - LOG((0, "nc4_convert_type: unexpected src type. " - "src_type %d, dest_type %d", src_type, dest_type)); + LOG((0, "%s: unexpected src type. src_type %d, dest_type %d", + __func__, src_type, dest_type)); return NC_EBADTYPE; } return NC_NOERR; @@ -3986,12 +3820,10 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) NC_GRP_INFO_T *g; NC_VAR_INFO_T *var; NC_DIM_INFO_T *dim; - H5G_stat_t statbuf; - int d, finished; int retval = NC_NOERR; assert(grp && grp->name); - LOG((4, "nc4_rec_match_dimscales: grp->name %s", grp->name)); + LOG((4, "%s: grp->name %s", __func__, grp->name)); /* Perform var dimscale match for child groups. */ for (g = grp->children; g; g = g->next) @@ -4002,49 +3834,48 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) * try and find a dimension for them. */ for (var = grp->var; var; var = var->next) { - /* Are there dimscales for this variable? */ - if (var->dimscale_hdf5_objids) + /* Skip dimension scale variables */ + if (!var->dimscale) { - for (d = 0; d < var->ndims; d++) + int d; + + /* Are there dimscales for this variable? */ + if (var->dimscale_hdf5_objids) { - LOG((5, "nc4_rec_match_dimscales: var %s has dimscale info...", var->name)); - /* Look at all the dims in this group to see if they - * match. */ - finished = 0; - for (g = grp; g && !finished; g = g->parent) + for (d = 0; d < var->ndims; d++) { - for (dim = g->dim; dim; dim = dim->next) + int finished = 0; + + LOG((5, "%s: var %s has dimscale info...", __func__, var->name)); + /* Look at all the dims in this group to see if they + * match. */ + for (g = grp; g && !finished; g = g->parent) { - if (!dim->hdf_dimscaleid) - return NC_EDIMMETA; - if (H5Gget_objinfo(dim->hdf_dimscaleid, ".", 1, &statbuf) < 0) - return NC_EHDFERR; - if (var->dimscale_hdf5_objids[d].fileno[0] == statbuf.fileno[0] && - var->dimscale_hdf5_objids[d].objno[0] == statbuf.objno[0] && - var->dimscale_hdf5_objids[d].fileno[1] == statbuf.fileno[1] && - var->dimscale_hdf5_objids[d].objno[1] == statbuf.objno[1]) + for (dim = g->dim; dim; dim = dim->next) { - LOG((4, "nc4_rec_match_dimscales: for dimension %d, found dim %s", - d, dim->name)); - var->dimids[d] = dim->dimid; - finished++; - break; - } - } /* next dim */ - } /* next grp */ - LOG((5, "nc4_rec_match_dimscales: dimid for this dimscale is %d", var->xtype)); - } /* next var->dim */ - } - else - { - if (!var->dimscale) - { + if (var->dimscale_hdf5_objids[d].fileno[0] == dim->hdf5_objid.fileno[0] && + var->dimscale_hdf5_objids[d].objno[0] == dim->hdf5_objid.objno[0] && + var->dimscale_hdf5_objids[d].fileno[1] == dim->hdf5_objid.fileno[1] && + var->dimscale_hdf5_objids[d].objno[1] == dim->hdf5_objid.objno[1]) + { + LOG((4, "%s: for dimension %d, found dim %s", + __func__, d, dim->name)); + var->dimids[d] = dim->dimid; + finished++; + break; + } + } /* next dim */ + } /* next grp */ + LOG((5, "%s: dimid for this dimscale is %d", __func__, var->xtype)); + } /* next var->dim */ + } + /* No dimscales for this var! Invent phony dimensions. */ + else + { hid_t spaceid = 0; hsize_t *h5dimlen = NULL, *h5dimlenmax = NULL; int dataset_ndims; - /* No dimscales for this var! Invent phony dimensions. */ - /* Find the space information for this dimension. */ if ((spaceid = H5Dget_space(var->hdf_datasetid)) < 0) return NC_EHDFERR; @@ -4087,9 +3918,6 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) * size. */ for (d = 0; d < var->ndims; d++) { - NC_DIM_INFO_T *dim = NULL; - char phony_dim_name[NC_MAX_NAME + 1]; - /* Is there already a phony dimension of the correct size? */ for (dim = grp->dim; dim; dim = dim->next) if ((dim->len == h5dimlen[d]) && @@ -4100,7 +3928,9 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp) /* Didn't find a phony dim? Then create one. */ if (!dim) { - LOG((3, "nc4_rec_match_dimscales: creating phony dim for var %s", var->name)); + char phony_dim_name[NC_MAX_NAME + 1]; + + LOG((3, "%s: creating phony dim for var %s", __func__, var->name)); if ((retval = nc4_dim_list_add(&grp->dim))) return retval; grp->ndims++; @@ -4137,7 +3967,7 @@ nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype, int is_long, NC_TYPE_INFO_T *type; int retval; - LOG((4, "nc4_get_typelen_mem xtype: %d", xtype)); + LOG((4, "%s xtype: %d", __func__, xtype)); assert(len); /* If this is an atomic type, the answer is easy. */ diff --git a/libsrc4/nc4internal.c b/libsrc4/nc4internal.c index f6befe2c3..ad0e597a2 100644 --- a/libsrc4/nc4internal.c +++ b/libsrc4/nc4internal.c @@ -16,6 +16,7 @@ conditions. #include "nc4internal.h" #include "nc.h" /* from libsrc */ #include "ncdispatch.h" /* from libdispatch */ +#include "H5DSpublic.h" #include #if 0 /*def USE_PNETCDF*/ @@ -125,7 +126,7 @@ find_var_dim_max_length(NC_GRP_INFO_T *grp, int varid, int dimid, size_t *maxlen if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid, h5dimlen, h5dimlenmax)) < 0) BAIL(NC_EHDFERR); - LOG((5, "find_var_shape_nc: varid %d len %d max: %d", + LOG((5, "find_var_dim_max_length: varid %d len %d max: %d", varid, (int)h5dimlen[0], (int)h5dimlenmax[0])); for (d=0; ddimids[d] == dimid) { @@ -176,30 +177,10 @@ nc4_nc4f_list_add(NC *nc, const char *path, int mode) return nc4_grp_list_add(&(h5->root_grp), h5->next_nc_grpid++, NULL, nc, NC_GROUP_NAME, &grp); } -/* /\* Given an ncid, find the relevant group and return a pointer to */ -/* * it. *\/ */ -/* NC_GRP_INFO_T * */ -/* find_nc_grp(int ncid) */ -/* { */ -/* NC *f; */ - -/* for (f = nc_file; f; f = f->next) */ -/* { */ -/* if (f->ext_ncid == (ncid & FILE_ID_MASK)) */ -/* { */ -/* assert(f->nc4_info && f->nc4_info->root_grp); */ -/* return nc4_rec_find_grp(f->nc4_info->root_grp, (ncid & GRP_ID_MASK)); */ -/* } */ -/* } */ - -/* return NULL; */ -/* } */ /* Given an ncid, find the relevant group and return a pointer to it, * return an error of this is not a netcdf-4 file (or if strict nc3 is * turned on for this file.) */ - - int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp) { @@ -365,6 +346,20 @@ nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, return NC_NOERR; } +/* Find a var (by name) in a grp. */ +int +nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var) +{ + assert(grp && var && name); + + /* Find the var info. */ + for ((*var) = grp->var; (*var); (*var) = (*var)->next) + if (0 == strcmp(name, (*var)->name)) + break; + + return NC_NOERR; +} + /* Recursively hunt for a HDF type id. */ NC_TYPE_INFO_T * nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid) @@ -703,8 +698,7 @@ nc4_grp_list_add(NC_GRP_INFO_T **list, int new_nc_grpid, { NC_GRP_INFO_T *g; - LOG((3, "grp_list_add: new_nc_grpid %d name %s ", - new_nc_grpid, name)); + LOG((3, "%s: new_nc_grpid %d name %s ", __func__, new_nc_grpid, name)); /* Get the memory to store this groups info. */ if (!(*grp = calloc(1, sizeof(NC_GRP_INFO_T)))) @@ -1089,8 +1083,6 @@ nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim) /* Free memory allocated for names. */ if (dim->name) free(dim->name); - if (dim->old_name) - free(dim->old_name); free(dim); return NC_NOERR; @@ -1125,7 +1117,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) int retval; assert(grp); - LOG((3, "nc4_rec_grp_del: grp->name %s", grp->name)); + LOG((3, "%s: grp->name %s", __func__, grp->name)); /* Recursively call this function for each child, if any, stopping * if there is an error. */ @@ -1143,7 +1135,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) att = grp->att; while (att) { - LOG((4, "nc4_rec_grp_del: deleting att %s", att->name)); + LOG((4, "%s: deleting att %s", __func__, att->name)); a = att->next; if ((retval = nc4_att_list_del(&grp->att, att))) return retval; @@ -1154,11 +1146,10 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) var = grp->var; while (var) { - LOG((4, "nc4_rec_grp_del: deleting var %s", var->name)); + LOG((4, "%s: deleting var %s", __func__, var->name)); /* Close HDF5 dataset associated with this var, unless it's a * scale. */ - if (var->hdf_datasetid && !var->dimscale && - H5Dclose(var->hdf_datasetid) < 0) + if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0) return NC_EHDFERR; v = var->next; if ((retval = nc4_var_list_del(&grp->var, var))) @@ -1170,7 +1161,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) dim = grp->dim; while (dim) { - LOG((4, "nc4_rec_grp_del: deleting dim %s", dim->name)); + LOG((4, "%s: deleting dim %s", __func__, dim->name)); /* Close HDF5 dataset associated with this dim. */ if (dim->hdf_dimscaleid && H5Dclose(dim->hdf_dimscaleid) < 0) return NC_EHDFERR; @@ -1184,7 +1175,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) type = grp->type; while (type) { - LOG((4, "nc4_rec_grp_del: deleting type %s", type->name)); + LOG((4, "%s: deleting type %s", __func__, type->name)); t = type->next; if ((retval = type_list_del(&grp->type, type))) return retval; @@ -1192,7 +1183,7 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp) } /* Tell HDF5 we're closing this group. */ - LOG((4, "nc4_rec_grp_del: closing group %s", grp->name)); + LOG((4, "%s: closing group %s", __func__, grp->name)); if (grp->hdf_grpid && H5Gclose(grp->hdf_grpid) < 0) return NC_EHDFERR; @@ -1262,6 +1253,113 @@ nc4_att_list_del(NC_ATT_INFO_T **list, NC_ATT_INFO_T *att) return NC_NOERR; } +/* Break a coordinate variable to separate the dimension and the variable */ +int +nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T *dim) +{ + int retval = NC_NOERR; + + /* Sanity checks */ + assert(dim->coord_var == coord_var); + assert(coord_var->dim[0] == dim); + assert(coord_var->dimids[0] == dim->dimid); + assert(0 == dim->hdf_dimscaleid); + + /* If we're replacing an existing dimscale dataset, go to + * every var in the file and detach this dimension scale. */ + if ((retval = rec_detach_scales(grp->nc4_info->root_grp, + dim->dimid, coord_var->hdf_datasetid))) + return retval; + + /* Allow attached dimscales to be tracked on the [former] coordinate variable */ + if (coord_var->ndims) + { + /* Coordinate variables shouldn't have dimscales attached */ + assert(NULL == coord_var->dimscale_attached); + + /* Allocate space for tracking them */ + if (NULL == (coord_var->dimscale_attached = calloc(coord_var->ndims, sizeof(int)))) + return NC_ENOMEM; + } + + /* Detach dimension from variable */ + coord_var->dimscale = 0; + coord_var->dirty++; + dim->coord_var = NULL; + + return NC_NOERR; +} + +/* Reform a coordinate variable from a dimension and a variable */ +int +nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim) +{ + int retval = NC_NOERR; + + /* Attach variable to dimension */ + var->dimscale++; + var->dirty++; + dim->coord_var = var; + + /* Detach dimscales from the [new] coordinate variable */ + if(var->dimscale_attached) + { + int dims_detached = 0; + int finished = 0; + int d; + + /* Loop over all dimensions for variable */ + for (d = 0; d < var->ndims && !finished; d++) + /* Is there a dimscale attached to this axis? */ + if(var->dimscale_attached[d]) + { + NC_GRP_INFO_T *g; + + for (g = grp; g && !finished; g = g->parent) + { + NC_DIM_INFO_T *dim1; + + for (dim1 = g->dim; dim1 && !finished; dim1 = dim1->next) + if (var->dimids[d] == dim1->dimid) + { + hid_t dim_datasetid; /* Dataset ID for dimension */ + + /* Find dataset ID for dimension */ + if (dim1->coord_var) + dim_datasetid = dim1->coord_var->hdf_datasetid; + else + dim_datasetid = dim1->hdf_dimscaleid; + assert(dim_datasetid > 0); + if (H5DSdetach_scale(var->hdf_datasetid, dim_datasetid, d) < 0) + BAIL(NC_EHDFERR); + var->dimscale_attached[d] = 0; + if (dims_detached++ == var->ndims) + finished++; + } + } + } + + /* Release & reset the array tracking attached dimscales */ + free(var->dimscale_attached); + var->dimscale_attached = NULL; + } + + /* Use variable's dataset ID for the dimscale ID */ + if (dim->hdf_dimscaleid) + { + if (H5Dclose(dim->hdf_dimscaleid) < 0) + BAIL(NC_EHDFERR); + dim->hdf_dimscaleid = 0; + + /* Now delete the dimscale's dataset (it will be recreated later, if necessary) */ + if (H5Gunlink(grp->hdf_grpid, dim->name) < 0) + return NC_EDIMMETA; + } + + exit: + return retval; +} + /* Normalize a UTF8 name. Put the result in norm_name, which can be * NC_MAX_NAME + 1 in size. This function makes sure the free() gets * called on the return from utf8proc_NFC, and also ensures that the diff --git a/libsrc4/nc4var.c b/libsrc4/nc4var.c index 08a4b3b49..71c5f4db5 100644 --- a/libsrc4/nc4var.c +++ b/libsrc4/nc4var.c @@ -66,9 +66,6 @@ nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var) #ifdef EXTRA_TESTS num_plists--; #endif - - if (var->dimscale) - var->dim[0]->hdf_dimscaleid = var->hdf_datasetid; } return NC_NOERR; @@ -293,8 +290,8 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var) if (suggested_size > var->dim[d]->len) suggested_size = var->dim[d]->len; var->chunksizes[d] = suggested_size ? suggested_size : 1; - LOG((4, "nc_def_var_nc4: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d " - "chunksize %ld", var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d])); + LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d " + "chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d])); } /* Find total chunk size. */ @@ -348,9 +345,7 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, NC_HDF5_FILE_INFO_T *h5; NC_TYPE_INFO_T *type_info; char norm_name[NC_MAX_NAME + 1]; - int num_unlim = 0; int d; - size_t num_values = 1; int retval; /* Find info for this file and group, and set pointer to each. */ @@ -406,14 +401,10 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, { if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, NULL))) return retval; - if (dim->unlimited) - num_unlim++; - else - num_values *= dim->len; } /* These degrubbing messages sure are handy! */ - LOG((3, "nc_def_var_nc4: name %s type %d ndims %d", norm_name, xtype, ndims)); + LOG((3, "%s: name %s type %d ndims %d", __func__, norm_name, xtype, ndims)); #ifdef LOGGING { int dd; @@ -455,8 +446,6 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, &var->type_info->size))) return retval; } - if (!num_unlim) - var->contiguous = 1; /* Allocate space for dimension information. */ if (ndims) @@ -467,21 +456,49 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, return NC_ENOMEM; } + /* Assign dimensions to the variable */ /* At the same time, check to see if this is a coordinate * variable. If so, it will have the same name as one of its * dimensions. If it is a coordinate var, is it a coordinate var in * the same group as the dim? */ + /* Also, check whether we should use contiguous or chunked storage */ + var->contiguous = 1; for (d = 0; d < ndims; d++) { NC_GRP_INFO_T *dim_grp; + + /* Look up each dimension */ if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, &dim_grp))) return retval; - if (strcmp(dim->name, norm_name) == 0 && dim_grp == grp && d == 0) + + /* Check for dim index 0 having the same name, in the same group */ + if (d == 0 && dim_grp == grp && strcmp(dim->name, norm_name) == 0) { var->dimscale++; dim->coord_var = var; - dim->coord_var_in_grp++; + + /* Use variable's dataset ID for the dimscale ID */ + if (dim->hdf_dimscaleid) + { + /* Detach dimscale from any variables using it */ + if ((retval = rec_detach_scales(grp, dimidsp[d], dim->hdf_dimscaleid)) < 0) + return retval; + + if (H5Dclose(dim->hdf_dimscaleid) < 0) + return NC_EHDFERR; + dim->hdf_dimscaleid = 0; + + /* Now delete the dataset (it will be recreated later, if necessary) */ + if (H5Gunlink(grp->hdf_grpid, dim->name) < 0) + return NC_EDIMMETA; + } } + + /* Check for unlimited dimension and turn off contiguous storage */ + if (dim->unlimited) + var->contiguous = 0; + + /* Track dimensions for variable */ var->dimids[d] = dimidsp[d]; var->dim[d] = dim; } @@ -547,8 +564,8 @@ NC4_def_var(int ncid, const char *name, nc_type xtype, int ndims, NC *nc; NC_HDF5_FILE_INFO_T *h5; - LOG((2, "nc_def_var: ncid 0x%x name %s xtype %d ndims %d", - ncid, name, xtype, ndims)); + LOG((2, "%s: ncid 0x%x name %s xtype %d ndims %d", + __func__, ncid, name, xtype, ndims)); /* If there are dimensions, I need their ids. */ if (ndims && !dimidsp) @@ -596,7 +613,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep, int d; int retval; - LOG((2, "nc_inq_var_all: ncid 0x%x varid %d", ncid, varid)); + LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -726,7 +743,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate, int d; int retval; - LOG((2, "nc_def_var_extra: ncid 0x%x varid %d", ncid, varid)); + LOG((2, "%s: ncid 0x%x varid %d", __func__, ncid, varid)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -786,7 +803,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate, var->deflate = *deflate; if (*deflate) var->deflate_level = *deflate_level; - LOG((3, "nc_def_var_extra: *deflate_level %d", *deflate_level)); + LOG((3, "%s: *deflate_level %d", __func__, *deflate_level)); } /* Szip in use? */ @@ -1070,7 +1087,7 @@ NC4_inq_varid(int ncid, const char *name, int *varidp) if (!varidp) return NC_NOERR; - LOG((2, "nc_inq_varid: ncid 0x%x name %s", ncid, name)); + LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, NULL))) @@ -1114,8 +1131,8 @@ NC4_rename_var(int ncid, int varid, const char *name) NC_VAR_INFO_T *var; int retval = NC_NOERR; - LOG((2, "nc_rename_var: ncid 0x%x varid %d name %s", - ncid, varid, name)); + LOG((2, "%s: ncid 0x%x varid %d name %s", + __func__, ncid, varid, name)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) @@ -1174,6 +1191,38 @@ NC4_rename_var(int ncid, int varid, const char *name) return NC_ENOMEM; strcpy(var->name, name); + /* Check if this was a coordinate variable previously, but names are different now */ + if (var->dimscale && strcmp(var->name, var->dim[0]->name)) + { + /* Break up the coordinate variable */ + if ((retval = nc4_break_coord_var(grp, var, var->dim[0]))) + return retval; + } + + /* Check if this should become a coordinate variable */ + if (!var->dimscale) + { + /* Only variables with >0 dimensions can become coordinate variables */ + if (var->ndims) + { + NC_GRP_INFO_T *dim_grp; + NC_DIM_INFO_T *dim; + + /* Check to see if this is became a coordinate variable. If so, it + * will have the same name as dimension index 0. If it is a + * coordinate var, is it a coordinate var in the same group as the dim? + */ + if ((retval = nc4_find_dim(grp, var->dimids[0], &dim, &dim_grp))) + return retval; + if (strcmp(dim->name, name) == 0 && dim_grp == grp) + { + /* Reform the coordinate variable */ + if ((retval = nc4_reform_coord_var(grp, var, dim))) + return retval; + } + } + } + exit: return retval; } @@ -1191,7 +1240,7 @@ NC4_var_par_access(int ncid, int varid, int par_access) NC_VAR_INFO_T *var; int retval; - LOG((1, "nc_var_par_access: ncid 0x%x varid %d par_access %d", ncid, + LOG((1, "%s: ncid 0x%x varid %d par_access %d", __func__, ncid, varid, par_access)); if (par_access != NC_INDEPENDENT && par_access != NC_COLLECTIVE) @@ -1245,8 +1294,8 @@ nc4_put_vara_tc(int ncid, int varid, nc_type mem_type, int mem_type_is_long, NC_HDF5_FILE_INFO_T *h5; #endif - LOG((2, "nc4_put_vara_tc: ncid 0x%x varid %d mem_type %d mem_type_is_long %d", - ncid, varid, mem_type, mem_type_is_long)); + LOG((2, "%s: ncid 0x%x varid %d mem_type %d mem_type_is_long %d", + __func__, ncid, varid, mem_type, mem_type_is_long)); if (!(nc = nc4_find_nc_file(ncid,NULL))) return NC_EBADID; @@ -1375,8 +1424,8 @@ nc4_get_vara_tc(int ncid, int varid, nc_type mem_type, int mem_type_is_long, NC *nc; NC_HDF5_FILE_INFO_T* h5; - LOG((2, "nc4_get_vara_tc: ncid 0x%x varid %d mem_type %d mem_type_is_long %d", - ncid, varid, mem_type, mem_type_is_long)); + LOG((2, "%s: ncid 0x%x varid %d mem_type %d mem_type_is_long %d", + __func__, ncid, varid, mem_type, mem_type_is_long)); if (!(nc = nc4_find_nc_file(ncid,&h5))) return NC_EBADID; diff --git a/nc_test4/renamegroup.c b/nc_test4/renamegroup.c index c66ea7e7f..3189eecc1 100644 --- a/nc_test4/renamegroup.c +++ b/nc_test4/renamegroup.c @@ -7,6 +7,7 @@ #include #include +#include #define LOGGING #include "netcdf.h" diff --git a/nc_test4/tst_dims.c b/nc_test4/tst_dims.c index dbcfbd1be..03a550b54 100644 --- a/nc_test4/tst_dims.c +++ b/nc_test4/tst_dims.c @@ -15,7 +15,6 @@ #define LEVEL_NAME "level" #define TIME_NAME "time" #define DIM5_NAME "twilight_zone" -#define DIM_NAME "dim" #define LAT_LEN 1 #define LON_LEN 2 #define LEVEL_LEN 3 @@ -171,6 +170,153 @@ main(int argc, char **argv) if (nc_close(ncid)) ERR; } + SUMMARIZE_ERR; + printf("*** Testing renaming dimensions and vars..."); + { +#define FILE_NAME1 "foo1.nc" +#define FILE_NAME2 "foo2.nc" +#define FILE_NAME3 "foo3.nc" +#define FILE_NAME4 "foo4.nc" +#define DIM_NAME "lat_T42" +#define VAR_NAME DIM_NAME +#define DIM_NAME2 "lat" +#define VAR_NAME2 DIM_NAME2 +#define RANK_lat_T42 1 + int ncid, varid, dimid; + int lat_T42_dim; + size_t lat_T42_len = 3; + int lat_T42_id; + int lat_T42_dims[RANK_lat_T42]; + char name[NC_MAX_NAME + 1]; + + /* =========== */ + /* Sub-test #1 */ + /* =========== */ + /* create file with dimension and associated coordinate variable */ + if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR; + if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR; + lat_T42_dims[0] = lat_T42_dim; + if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, rename coordinate dimension and then associated variable */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR; + if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR; + if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, check coordinate dimension and associated variable names */ + /* Should be just like they created the file with DIM_NAME2 & VAR_NAME2 to + * begin with. + */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR; + if (nc_inq_dimname(ncid, dimid, name)) ERR; + if (strcmp(name, DIM_NAME2)) ERR; + if (nc_inq_varname(ncid, varid, name)) ERR; + if (strcmp(name, VAR_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* =========== */ + /* Sub-test #2 */ + /* =========== */ + /* create file with dimension and associated coordinate variable */ + if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR; + if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR; + lat_T42_dims[0] = lat_T42_dim; + if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, just rename coordinate dimension */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR; + if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, check coordinate dimension and associated variable names */ + /* Should be just like the file was created with DIM_NAME2 to begin with */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR; + if (nc_inq_dimname(ncid, dimid, name)) ERR; + if (strcmp(name, DIM_NAME2)) ERR; + if (nc_inq_varname(ncid, varid, name)) ERR; + if (strcmp(name, VAR_NAME)) ERR; + if (nc_close(ncid)) ERR; + + + /* =========== */ + /* Sub-test #3 */ + /* =========== */ + /* create file with dimension and associated coordinate variable */ + if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR; + if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR; + lat_T42_dims[0] = lat_T42_dim; + if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, just rename variable */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR; + if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, check coordinate dimension and associated variable names */ + /* Should be just like the file was created with VAR_NAME2 to begin with */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR; + if (nc_inq_dimname(ncid, dimid, name)) ERR; + if (strcmp(name, DIM_NAME)) ERR; + if (nc_inq_varname(ncid, varid, name)) ERR; + if (strcmp(name, VAR_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* =========== */ + /* Sub-test #4 */ + /* =========== */ + /* create file with dimension and associated coordinate variable */ + if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR; + if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR; + lat_T42_dims[0] = lat_T42_dim; + if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, rename associated variable and then coordinate dimension */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR; + if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR; + if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR; + if (nc_close(ncid)) ERR; + + + /* reopen file, check coordinate dimension and associated variable names */ + /* Should be just like they created the file with DIM_NAME2 & VAR_NAME2 to + * begin with. + */ + if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR; + if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR; + if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR; + if (nc_inq_dimname(ncid, dimid, name)) ERR; + if (strcmp(name, DIM_NAME2)) ERR; + if (nc_inq_varname(ncid, varid, name)) ERR; + if (strcmp(name, VAR_NAME2)) ERR; + if (nc_close(ncid)) ERR; + } + SUMMARIZE_ERR; printf("*** Testing file with just one unlimited dimension..."); { diff --git a/nc_test4/tst_dims2.c b/nc_test4/tst_dims2.c index 77aee5fa6..d7ead94f1 100644 --- a/nc_test4/tst_dims2.c +++ b/nc_test4/tst_dims2.c @@ -68,9 +68,6 @@ main(int argc, char **argv) * Christian! Next time I'm in Rostock I'll come by and buy you * a beer. ;-) */ #define TL 15 -#define SHUFFLE 0 -#define DEFLATE 1 -#define DEFLATE_LEVEL 5 int ncid; int time_dim; int tl_dim; @@ -137,9 +134,6 @@ main(int argc, char **argv) * Christian! Next time I'm in Rostock I'll come by and buy you * a beer. ;-) */ #define TL 15 -#define SHUFFLE 0 -#define DEFLATE 1 -#define DEFLATE_LEVEL 5 #define NDIMS2 2 #define NUM_TIMES 16 int ncid; @@ -247,7 +241,6 @@ main(int argc, char **argv) SUMMARIZE_ERR; printf("*** Checking multiple unlimited dimensions..."); { -#define MAX(x,y) ((x)>(y)?(x):(y)) #define NDIMS 2 #define MAX_VALUES 3 diff --git a/nc_test4/tst_parallel3.c b/nc_test4/tst_parallel3.c index 2adc3d1ab..27f9c98f0 100644 --- a/nc_test4/tst_parallel3.c +++ b/nc_test4/tst_parallel3.c @@ -53,6 +53,7 @@ int test_pio(int); int test_pio_attr(int); int test_pio_big(int); int test_pio_hyper(int); +int test_pio_extend(int); char* getenv_all(MPI_Comm comm, int root, const char* name); int facc_type; diff --git a/ncgen/genlib.c b/ncgen/genlib.c index 9243aefbd..9b6ae60f7 100644 --- a/ncgen/genlib.c +++ b/ncgen/genlib.c @@ -17,6 +17,7 @@ void define_netcdf(void) { char filename[2048+1]; + const char *fname; /* Rule for specifying the dataset name: 1. use -o name @@ -28,37 +29,43 @@ define_netcdf(void) */ if(netcdf_name) { /* -o flag name */ strcpy(filename,netcdf_name); + fname = filename; } else { /* construct a usable output file name */ if (cdlname != NULL && strcmp(cdlname,"-") != 0) {/* cmd line name */ char* p; + strncpy(filename,cdlname,2048); /* remove any suffix and prefix*/ p = strrchr(filename,'.'); if(p != NULL) {*p= '\0';} p = strrchr(filename,'/'); - if(p != NULL) {strncpy(filename,p+1,2048);} + if(p != NULL) + fname = p + 1; + else + fname = filename; } else {/* construct name from dataset name */ strncpy(filename,datasetname,2048); /* Reserve space for extension, terminating '\0' */ + fname = filename; } /* Append the proper extension */ - strcat(filename,binary_ext); + strcat(fname,binary_ext); } /* Execute exactly one of these */ #ifdef ENABLE_C - if (l_flag == L_C) gen_ncc(filename); else /* create C code to create netcdf */ + if (l_flag == L_C) gen_ncc(fname); else /* create C code to create netcdf */ #endif #ifdef ENABLE_F77 - if (l_flag == L_F77) gen_ncf77(filename); else /* create Fortran code */ + if (l_flag == L_F77) gen_ncf77(fname); else /* create Fortran code */ #endif #ifdef ENABLE_JAVA if(l_flag == L_JAVA) { - gen_ncjava(filename); + gen_ncjava(fname); } else #endif /* Binary is the default */ #ifdef ENABLE_BINARY - gen_netcdf(filename); /* create netcdf */ + gen_netcdf(fname); /* create netcdf */ #else derror("No language specified"); #endif diff --git a/ncgen3/ncgen.h b/ncgen3/ncgen.h index 92cb4732e..5d5a5c895 100644 --- a/ncgen3/ncgen.h +++ b/ncgen3/ncgen.h @@ -9,6 +9,7 @@ #define MAX_NC_ATTSIZE 20000 /* max size of attribute (for ncgen) */ #define MAXTRST 5000 /* max size of string value (for ncgen) */ +#include "config.h" #include "generic.h" extern int ncid; /* handle for netCDF */ From 4a894dc15486d13b4324f354d6a49f455a60f824 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 1 Dec 2013 00:09:27 -0600 Subject: [PATCH 16/21] Correct minor unmerged change. --- ncgen/genlib.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ncgen/genlib.c b/ncgen/genlib.c index ad0ff8ba9..990903cf8 100644 --- a/ncgen/genlib.c +++ b/ncgen/genlib.c @@ -41,7 +41,6 @@ define_netcdf(void) } else {/* construct name from dataset name */ strncpy(filename,datasetname,2048); /* Reserve space for extension, terminating '\0' */ - fname = filename; } /* Append the proper extension */ strncat(filename,binary_ext,2048-(strlen(filename) + strlen(binary_ext))); @@ -49,19 +48,19 @@ define_netcdf(void) /* Execute exactly one of these */ #ifdef ENABLE_C - if (l_flag == L_C) gen_ncc(fname); else /* create C code to create netcdf */ + if (l_flag == L_C) gen_ncc(filename); else /* create C code to create netcdf */ #endif #ifdef ENABLE_F77 - if (l_flag == L_F77) gen_ncf77(fname); else /* create Fortran code */ + if (l_flag == L_F77) gen_ncf77(filename); else /* create Fortran code */ #endif #ifdef ENABLE_JAVA if(l_flag == L_JAVA) { - gen_ncjava(fname); + gen_ncjava(filename); } else #endif /* Binary is the default */ #ifdef ENABLE_BINARY - gen_netcdf(fname); /* create netcdf */ + gen_netcdf(filename); /* create netcdf */ #else derror("No language specified"); #endif From 0af7499eb4246227ae21c942b023de68a8a4edd0 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 4 Dec 2013 16:02:43 -0700 Subject: [PATCH 17/21] Added a couple items to .gitignore. Corrected an issue reported by Coverity static analysis where memory was allocated but was not freed. --- .gitignore | 2 ++ oc2/ocutil.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 63322707b..3d49b8adb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ doxygen*.tmp \#*.*\# autom4te.cache myhtml +CMakeLists.txt.user +scan-build diff --git a/oc2/ocutil.c b/oc2/ocutil.c index f66a3b541..da9957c09 100644 --- a/oc2/ocutil.c +++ b/oc2/ocutil.c @@ -693,8 +693,10 @@ ocmktmp(const char* base, char** tmpnamep, int* fdp) tmpname = (char*)malloc(tmpsize); if(tmpname == NULL) return OC_ENOMEM; - if(!occopycat(tmpname,tmpsize,1,base)) - return OC_EOVERRUN; + if(!occopycat(tmpname,tmpsize,1,base)) { + free(tmpname); + return OC_EOVERRUN; + } #ifdef HAVE_MKSTEMP if(!occoncat(tmpname,tmpsize,1,"XXXXXX")) return OC_EOVERRUN; From 0bfdb80b68bf05f4f79c75232a6b0d9ee60b17cb Mon Sep 17 00:00:00 2001 From: Russ Rew Date: Thu, 5 Dec 2013 20:57:56 -0700 Subject: [PATCH 18/21] Added entry or NCF-177. --- RELEASE_NOTES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6d9f30788..4636b5699 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,6 +10,14 @@ information, where '[NCF-XXX]' refers to https://www.unidata.ucar.edu/jira/brows ### 4.3.1-rc5 Released TBD +* When opening a netCDF-4 file, streamline the iteration over objects in + the underlying HDF5 file. + +* Fixed netCDF-4 failure when renaming a dimension and renaming a + variable using that dimension, in either order. [NCF-177] + +[NCF-177]:https://bugtracking.unidata.ucar.edu/browse/NCF-177 + * When compiling with `hdf4` support, both autotools and cmake-based builds now properly look for the `libjpeg` dependency and will link against it when found (or complain if it's not). Also added `ENABLE_HDF4_FILE_TESTS` option to CMake-based builds. * Fixed bug in ncgen; it was not properly filling empty string constants From 45196f50ae63d4cb64f3518192a63a2193f2bd2c Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 6 Dec 2013 11:08:43 -0700 Subject: [PATCH 19/21] Updated documentation for forthcoming release candidate. --- RELEASE_NOTES.md | 2 +- man4/windows-binaries.md | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4636b5699..e443c02e9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,7 +8,7 @@ information, where '[NCF-XXX]' refers to https://www.unidata.ucar.edu/jira/brows ## 4.3.1 Released TBD -### 4.3.1-rc5 Released TBD +### 4.3.1-rc5 Released 2013-12-06 * When opening a netCDF-4 file, streamline the iteration over objects in the underlying HDF5 file. diff --git a/man4/windows-binaries.md b/man4/windows-binaries.md index dc422d295..0d72b7cf3 100644 --- a/man4/windows-binaries.md +++ b/man4/windows-binaries.md @@ -25,14 +25,14 @@ netCDF4+DAP | [netCDF4.3.0-NC4-DAP-32.exe][r4] | [netCDF4.3.0-NC4-DAP-64.exe][r -## Latest Release Candidate (netCDF-C 4.3.1-rc4) +## Latest Release Candidate (netCDF-C 4.3.1-rc5) Configuration | 32-bit | 64-bit | :-------------------|:-------- |:-------| -netCDF 3 | [netCDF4.3.1-rc4-NC3-32.exe][rc1] | [netCDF4.3.1-rc4-NC3-64.exe][rc5] -netCDF3+DAP | [netCDF4.3.1-rc4-NC3-DAP-32.exe][rc2] | [netCDF4.3.1-rc4-NC3-DAP-64.exe][rc6] -netCDF4 | [netCDF4.3.1-rc4-NC4-32.exe][rc3] | [netCDF4.3.1-rc4-NC4-64.exe][rc7] -netCDF4+DAP | [netCDF4.3.1-rc4-NC4-DAP-32.exe][rc4] | [netCDF4.3.1-rc4-NC4-DAP-64.exe][rc8] +netCDF 3 | [netCDF4.3.1-rc5-NC3-32.exe][rc1] | [netCDF4.3.1-rc5-NC3-64.exe][rc5] +netCDF3+DAP | [netCDF4.3.1-rc5-NC3-DAP-32.exe][rc2] | [netCDF4.3.1-rc5-NC3-DAP-64.exe][rc6] +netCDF4 | [netCDF4.3.1-rc5-NC4-32.exe][rc3] | [netCDF4.3.1-rc5-NC4-64.exe][rc7] +netCDF4+DAP | [netCDF4.3.1-rc5-NC4-DAP-32.exe][rc4] | [netCDF4.3.1-rc5-NC4-DAP-64.exe][rc8] # Using the netCDF-C Libraries with Visual Studio In order to use the netcdf libraries, you must ensure that the .dll files (along with any dependencies from deps/shared/bin) are on the system path. In order to compile a program using these libraries, you must first link your program against the appropriate 'import' (.lib) libraries. @@ -62,11 +62,11 @@ When installed, the netCDF libraries are placed in the specified locations, alon [r8]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.0-NC4-DAP-64.exe -[rc1]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC3-32.exe -[rc2]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC3-DAP-32.exe -[rc3]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC4-32.exe -[rc4]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC4-DAP-32.exe -[rc5]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC3-64.exe -[rc6]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC3-DAP-64.exe -[rc7]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC4-64.exe -[rc8]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc4-NC4-DAP-64.exe +[rc1]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC3-32.exe +[rc2]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC3-DAP-32.exe +[rc3]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC4-32.exe +[rc4]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC4-DAP-32.exe +[rc5]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC3-64.exe +[rc6]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC3-DAP-64.exe +[rc7]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC4-64.exe +[rc8]: http://www.unidata.ucar.edu/netcdf/win_netcdf/netCDF4.3.1-rc5-NC4-DAP-64.exe From 6d26b8c27c4485f34daad5190753e6c12b5fac71 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Fri, 6 Dec 2013 11:33:37 -0700 Subject: [PATCH 20/21] Fixed an issue with make distclean where a test file was not being deleted. --- nc_test4/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nc_test4/Makefile.am b/nc_test4/Makefile.am index 954562679..d32634186 100644 --- a/nc_test4/Makefile.am +++ b/nc_test4/Makefile.am @@ -129,7 +129,8 @@ radar_3d_chunking.txt tst_floats_1D.cdl floats_1D_3.nc floats_1D.cdl \ tst_*.nc tst_floats2_*.cdl tst_ints2_*.cdl tst_shorts2_*.cdl \ tst_elena_*.cdl tst_simple*.cdl tst_chunks.cdl pr_A1.* tauu_A1.* \ usi_01.* thetau_01.* tst_*.nc tst_*.h5 \ -tst_grp_rename.cdl tst_grp_rename.nc tst_grp_rename.dmp ref_grp_rename.cdl +tst_grp_rename.cdl tst_grp_rename.nc tst_grp_rename.dmp ref_grp_rename.cdl \ +foo1.nc if USE_HDF4_FILE_TESTS DISTCLEANFILES = AMSR_E_L2_Rain_V10_200905312326_A.hdf \ From c6cbfb57f5be8f29689e40852031d5e0b9b3ba6b Mon Sep 17 00:00:00 2001 From: dmh Date: Sat, 7 Dec 2013 20:19:53 -0700 Subject: [PATCH 21/21] Removed old code from NCF213 --- ncgen/semantics.c | 117 ---------------------------------------------- 1 file changed, 117 deletions(-) diff --git a/ncgen/semantics.c b/ncgen/semantics.c index f0d8f9bbc..5f00dedf1 100644 --- a/ncgen/semantics.c +++ b/ncgen/semantics.c @@ -18,7 +18,6 @@ static void processtypes(void); static void processtypesizes(void); static void processvars(void); static void processattributes(void); -static void processspecials(void); static void processunlimiteddims(void); static void processeconstrefs(void); static void processeconstrefsR(Datalist*); @@ -54,10 +53,6 @@ processsemantics(void) processtypesizes(); /* Process each var to fill in missing fields, etc*/ processvars(); - /* If we are not allowing certain special attributes, - but they were defined, convert them back to attributes - */ - processspecials(); /* Process attributes to connect to corresponding variable*/ processattributes(); /* Fix up enum constant values*/ @@ -707,118 +702,6 @@ processtypesizes(void) } } -#ifdef NCF213 /*Jira NCF-213*/ -/* We should not create an actual - attribute for any of the - special attributes. -*/ -static void -makespecial(int tag, Symbol* vsym, nc_type typ, Datalist* dlist) -{ - Symbol* attr = install(specialname(tag)); - attr->objectclass = NC_ATT; - attr->data = dlist; - if(vsym) { - Symbol* grp = vsym->container; - if(grp) listpush(grp->subnodes,(void*)attr); - attr->container = grp; - } - attr->att.var = vsym; - attr->typ.basetype = primsymbols[typ==NC_STRING?NC_CHAR:typ]; - listpush(attdefs,(void*)attr); -} -#endif /*NCF213*/ - -static void -processspecial1(Symbol* vsym) -{ - unsigned long flags = vsym->var.special.flags; - int i,tag; - NCConstant con; - Datalist* dlist = NULL; - if(flags == 0) return; /* no specials defined */ - con = nullconstant; - if((tag=(flags & _CHUNKSIZES_FLAG))) { - dlist = builddatalist(vsym->var.special.nchunks); - for(i=0;ivar.special.nchunks;i++) { - con = nullconstant; - con.nctype = NC_INT; - con.value.int32v = (int)vsym->var.special._ChunkSizes[i]; - dlappend(dlist,&con); - } - } else if((tag=(flags & _STORAGE_FLAG))) { - con.nctype = NC_STRING; - con.value.stringv.stringv - = (vsym->var.special._Storage == NC_CHUNKED? "chunked" - : "contiguous"); - con.value.stringv.len = strlen(con.value.stringv.stringv); - dlist = builddatalist(1); - dlappend(dlist,&con); - } - if((tag=(flags & _FLETCHER32_FLAG))) { - con.nctype = NC_STRING; - con.value.stringv.stringv - = (vsym->var.special._Fletcher32 == 1? "true" - : "false"); - con.value.stringv.len = strlen(con.value.stringv.stringv); - dlist = builddatalist(1); - dlappend(dlist,&con); - } - if((tag=(flags & _DEFLATE_FLAG))) { - con.nctype = NC_INT; - con.value.int32v = vsym->var.special._DeflateLevel; - dlist = builddatalist(1); - dlappend(dlist,&con); - } - if((tag=(flags & _SHUFFLE_FLAG))) { - con.nctype = NC_STRING; - con.value.stringv.stringv - = (vsym->var.special._Shuffle == 1? "true" - : "false"); - con.value.stringv.len = strlen(con.value.stringv.stringv); - dlist = builddatalist(1); - dlappend(dlist,&con); - } - if((tag=(flags & _ENDIAN_FLAG))) { - con.nctype = NC_STRING; - con.value.stringv.stringv - = (vsym->var.special._Endianness == 1? "little" - :"big"); - con.value.stringv.len = strlen(con.value.stringv.stringv); - dlist = builddatalist(1); - dlappend(dlist,&con); - } - if((tag=(flags & _NOFILL_FLAG))) { - con.nctype = NC_STRING; - /* Watch out: flags is NOFILL, but we store FILL */ - if(vsym->var.special._Fill == 1) { - con.value.stringv.stringv = "false"; - } else { - nofill_flag = 1; - con.value.stringv.stringv = "true"; - } - con.value.stringv.len = strlen(con.value.stringv.stringv); - dlist = builddatalist(1); - dlappend(dlist,&con); - } -#ifdef NCF213 /*Jira NCF-213*/ -/* We should not create an actual - attribute for any of the - special attributes. -*/ -#endif /*NCF213*/ -} - -static void -processspecials(void) -{ - int i; - for(i=0;i