Merge branch 'NCF-177' of https://github.com/qkoziol/netcdf-c into qkoziol-NCF-177

This commit is contained in:
Ward Fisher 2014-12-28 19:29:22 -08:00
commit e52bfa3593
11 changed files with 837 additions and 567 deletions

View File

@ -148,7 +148,11 @@ typedef struct NC_VAR_INFO
NC_DIM_INFO_T **dim;
int varid;
int natts;
nc_bool_t dirty; /* True if variable modified */
nc_bool_t is_new_var; /* True if variable is newly created */
nc_bool_t was_coord_var; /* True if variable was a coordinate var, but either the dim or var has been renamed */
nc_bool_t became_coord_var; /* True if variable _became_ a coordinate var, because either the dim or var has been renamed */
nc_bool_t fill_val_changed; /* True if variable's fill value changes after it has been created */
nc_bool_t attr_dirty; /* True if variable's attributes are dirty and should be rewritten */
nc_bool_t created; /* Variable has already been created (_not_ that it was just created) */
nc_bool_t written_to; /* True if variable has data written to it */
struct NC_TYPE_INFO *type_info;
@ -322,14 +326,15 @@ int nc4_convert_type(const void *src, void *dest,
/* These functions do HDF5 things. */
int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid);
int rec_reattach_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 nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
const size_t *countp, nc_type xtype, int is_long, void *op);
int nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
const size_t *countp, nc_type xtype, int is_long, void *op);
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_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, nc_bool_t *bad_coord_orderp);
int nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order);
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);

View File

@ -199,7 +199,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
NC_GRP_INFO_T *grp;
NC_HDF5_FILE_INFO_T *h5;
NC_VAR_INFO_T *var = NULL;
NC_ATT_INFO_T *att, **attlist = NULL, *varatt;
NC_ATT_INFO_T *att, **attlist = NULL;
char norm_name[NC_MAX_NAME + 1];
nc_bool_t new_att = NC_FALSE;
int retval = NC_NOERR, range_error = 0;
@ -334,11 +334,12 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
att->attnum = 0;
/* If this is the _FillValue attribute, then we will also have to
* copy the value to the fll_vlue pointer of the NC_VAR_INFO_T
* copy the value to the fill_vlue pointer of the NC_VAR_INFO_T
* struct for this var. (But ignore a global _FillValue
* attribute). */
if (!strcmp(att->name, _FillValue) && varid != NC_GLOBAL)
{
NC_ATT_INFO_T *varatt;
int size;
/* Fill value must be same type and have exactly one value */
@ -409,12 +410,11 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
}
else
memcpy(var->fill_value, data, type_size);
/* Mark the var and all its atts as dirty, so they get
* rewritten. */
var->dirty = NC_TRUE;
for (varatt = var->att; varatt; varatt = varatt->l.next)
varatt->dirty = NC_TRUE;
/* Indicate that the fill value was changed, if the variable has already
* been created in the file, so the dataset gets deleted and re-created. */
if (var->created)
var->fill_val_changed = NC_TRUE;
}
/* Copy the attribute data, if there is any. VLENs and string
@ -493,6 +493,10 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
att->dirty = NC_TRUE;
att->created = NC_FALSE;
/* Mark attributes on variable dirty, so they get written */
if(var)
var->attr_dirty = NC_TRUE;
exit:
/* If there was an error return it, otherwise return any potential
range error value. If none, return NC_NOERR as usual.*/
@ -794,8 +798,12 @@ NC4_del_att(int ncid, int varid, const char *name)
/* Delete it from the HDF5 file, if it's been created. */
if (att->created)
{
assert(locid);
if(H5Adelete(locid, att->name) < 0)
BAIL(NC_EATTMETA);
}
/* Renumber all following attributes. */
for (natt = att->l.next; natt; natt = natt->l.next)

View File

@ -268,7 +268,7 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
NC *nc;
NC_GRP_INFO_T *grp;
NC_HDF5_FILE_INFO_T *h5;
NC_DIM_INFO_T *dim;
NC_DIM_INFO_T *dim, *tmp_dim;
char norm_name[NC_MAX_NAME + 1];
int retval;
@ -299,17 +299,18 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
if ((retval = nc4_check_name(name, norm_name)))
return retval;
/* Make sure the new name is not already in use in this group. */
/* Check if name is in use, and retain a pointer to the correct dim */
tmp_dim = NULL;
for (dim = grp->dim; dim; dim = dim->l.next)
{
if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
return NC_ENAMEINUSE;
/* Find the dim. */
for (dim = grp->dim; dim; dim = dim->l.next)
if (dim->dimid == dimid)
break;
if (!dim)
tmp_dim = dim;
}
if (!tmp_dim)
return NC_EBADDIM;
dim = tmp_dim;
/* Check for renaming dimension w/o variable */
if (dim->hdf_dimscaleid)

View File

@ -1855,7 +1855,7 @@ read_dataset(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
NC_DIM_INFO_T *dim = NULL; /* Dimension created for scales */
hid_t spaceid = 0;
int ndims;
int is_scale = 0;
htri_t is_scale;
int retval = NC_NOERR;
/* Get the dimension information for this dataset. */
@ -2922,7 +2922,7 @@ sync_netcdf4_file(NC_HDF5_FILE_INFO_T *h5)
/* Write any metadata that has changed. */
if (!(h5->cmode & NC_NOWRITE))
{
int bad_coord_order = 0; /* if detected, propagate to all groups to consistently store dimids */
nc_bool_t bad_coord_order = NC_FALSE; /* if detected, propagate to all groups to consistently store dimids */
if ((retval = nc4_rec_write_groups_types(h5->root_grp)))
return retval;

File diff suppressed because it is too large Load Diff

View File

@ -1263,9 +1263,12 @@ nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T
/* Detach dimension from variable */
coord_var->dimscale = NC_FALSE;
coord_var->dirty = NC_TRUE;
dim->coord_var = NULL;
/* Set state transition indicators */
coord_var->was_coord_var = NC_TRUE;
coord_var->became_coord_var = NC_FALSE;
return NC_NOERR;
}
@ -1275,11 +1278,6 @@ 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 = NC_TRUE;
var->dirty = NC_TRUE;
dim->coord_var = var;
/* Detach dimscales from the [new] coordinate variable */
if(var->dimscale_attached)
{
@ -1335,6 +1333,26 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
return NC_EDIMMETA;
}
/* Attach variable to dimension */
var->dimscale = NC_TRUE;
dim->coord_var = var;
/* Check if this variable used to be a coord. var */
if (var->was_coord_var)
{
/* Reattach the scale everywhere it is used. */
/* (Recall that netCDF dimscales are always 1-D) */
if ((retval = rec_reattach_scales(grp->nc4_info->root_grp,
var->dimids[0], var->hdf_datasetid)))
return retval;
/* Set state transition indicator (cancels earlier transition) */
var->was_coord_var = NC_FALSE;
}
else
/* Set state transition indicator */
var->became_coord_var = NC_TRUE;
exit:
return retval;
}

View File

@ -413,7 +413,7 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype,
strcpy(var->name, norm_name);
var->varid = grp->nvars++;
var->ndims = ndims;
var->dirty = NC_TRUE;
var->is_new_var = NC_TRUE;
/* If this is a user-defined type, there is a type_info struct with
* all the type information. For atomic types, fake up a type_info
@ -1175,7 +1175,7 @@ NC4_rename_var(int ncid, int varid, const char *name)
NC *nc;
NC_GRP_INFO_T *grp;
NC_HDF5_FILE_INFO_T *h5;
NC_VAR_INFO_T *var;
NC_VAR_INFO_T *var, *tmp_var;
int retval = NC_NOERR;
LOG((2, "%s: ncid 0x%x varid %d name %s",
@ -1206,17 +1206,18 @@ NC4_rename_var(int ncid, int varid, const char *name)
if ((retval = NC_check_name(name)))
return retval;
/* Is name in use? */
/* Check if name is in use, and retain a pointer to the correct variable */
tmp_var = NULL;
for (var = grp->var; var; var = var->l.next)
{
if (!strncmp(var->name, name, NC_MAX_NAME))
return NC_ENAMEINUSE;
/* Find the var. */
for (var = grp->var; var; var = var->l.next)
if (var->varid == varid)
break;
if (!var)
tmp_var = var;
}
if (!tmp_var)
return NC_ENOTVAR;
var = tmp_var;
/* If we're not in define mode, new name must be of equal or
less size, if strict nc3 rules are in effect for this . */

View File

@ -8,7 +8,7 @@ SET(NC4_TESTS tst_dims tst_dims2 tst_dims3 tst_files tst_files4 tst_vars
tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts
t_type cdm_sea_soundings tst_vl tst_atts1 tst_atts2
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs
tst_h_scalar)
tst_h_scalar tst_rename)
# Note, renamegroup needs to be compiled before run_grp_rename
build_bin_test(renamegroup)

View File

@ -21,7 +21,7 @@ tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2 tst_fillbug \
tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts \
t_type cdm_sea_soundings tst_camrun tst_vl tst_atts1 tst_atts2 \
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug tst_h_refs \
tst_h_scalar
tst_h_scalar tst_rename
check_PROGRAMS = $(NC4_TESTS) renamegroup

View File

@ -92,9 +92,6 @@ int main(int argc, char **argv)
return -1;
}
if (facc_type != NC_MPIPOSIX)
facc_type = NC_MPIIO;
facc_type = NC_NETCDF4|NC_MPIIO;
facc_type_open = NC_MPIIO;

161
nc_test4/tst_rename.c Normal file
View File

@ -0,0 +1,161 @@
/*
* Demonstrate netcdf-4 rename bug.
*/
#include <netcdf.h>
#include <stdio.h>
/* On error, prints line number and file of test program. */
#define ERR do { \
fflush(stdout); \
fprintf(stderr, "Unexpected result, %s, line: %d\n", \
__FILE__, __LINE__); \
return 2; \
} while (0)
#define FILE_NAME3 "tst_rnfix3.nc"
#define FILE_NAME4 "tst_rnfix4.nc"
#define ODIM_NAME "lat" /* name for coord dim */
#define NDIM_NAME "tal" /* new name for coord dim */
#define OVAR_NAME "lat" /* name for coord var */
#define NVAR_NAME "tal" /* new name for coord var */
#define OVAR2_NAME "rh" /* name for non-coord var that uses coord dim */
#define VAR_RANK 1 /* all vars in this test are of same rank */
#define DIM_LEN 2 /* all dims in this test are of same len */
/* For renaming tests. Create small test file of specified format
* with a coordinate dimension, corresponding coordinate variable, and
* a non-coordinate variable that uses the coordinate dimension.
*/
int
create_test_file(
char *path, /* filename */
int format /* NC_FORMAT_CLASSIC, NC_FORMAT_64BIT,
NC_FORMAT_NETCDF4, or NC_FORMAT_NETCDF4_CLASSIC */
)
{
int ncid, dimid, varid, var2id;
int dims[VAR_RANK];
int lats[DIM_LEN] = {-90, 90};
float rh[DIM_LEN] = {0.25, 0.75};
switch (format) {
case (NC_FORMAT_CLASSIC):
if (nc_create(path, 0, &ncid)) ERR;
break;
case (NC_FORMAT_64BIT):
if (nc_create(path, NC_64BIT_OFFSET, &ncid)) ERR;
break;
case (NC_FORMAT_NETCDF4):
if (nc_create(path, NC_NETCDF4, &ncid)) ERR;
break;
case(NC_FORMAT_NETCDF4_CLASSIC):
if (nc_create(path, NC_NETCDF4 | NC_CLASSIC_MODEL, &ncid)) ERR;
break;
default:
ERR;
return NC_ENOTNC;
}
if (nc_def_dim(ncid, ODIM_NAME, DIM_LEN, &dimid)) ERR;
dims[0] = dimid;
if (nc_def_var(ncid, OVAR_NAME, NC_INT, VAR_RANK, dims, &varid)) ERR;
if (nc_def_var(ncid, OVAR2_NAME, NC_FLOAT, VAR_RANK, dims, &var2id)) ERR;
if (nc_enddef(ncid)) ERR; /* not necessary for netCDF-4 files */
if (nc_put_var_int(ncid, varid, lats)) ERR;
if (nc_put_var_float(ncid, var2id, rh)) ERR;
if (nc_close(ncid)) ERR;
return 0;
}
int
main(int argc, char **argv)
{
#define NUM_FORMATS 2
int formats[NUM_FORMATS] = {NC_FORMAT_NETCDF4, NC_FORMAT_NETCDF4_CLASSIC};
char *fmt_names[] = {"netCDF-4", "netCDF-4 classic model"};
char *file_names[] = {FILE_NAME3, FILE_NAME4};
int format;
fprintf(stderr,"*** Testing netcdf rename bugs and fixes.\n");
for(format = 0; format < NUM_FORMATS; format++)
{
int ncid, dimid, varid, var2id;
int lats[DIM_LEN] = {-90, 90};
int lats_in[DIM_LEN];
float rh[DIM_LEN] = {0.25, 0.75};
float rh_in[DIM_LEN];
int ii;
fprintf(stderr,"*** Test renaming coordinate variable and its dimension for %s...\n",
fmt_names[format]);
if (create_test_file(file_names[format], formats[format])) ERR;
if (nc_open(file_names[format], NC_WRITE, &ncid)) ERR;
if (nc_inq_dimid(ncid, ODIM_NAME, &dimid)) ERR;
if (nc_inq_varid(ncid, OVAR_NAME, &varid)) ERR;
if (nc_inq_varid(ncid, OVAR2_NAME, &var2id)) ERR;
if (nc_redef(ncid)) ERR; /* omitting this and nc_enddef call eliminates bug */
if (nc_rename_dim(ncid, dimid, NDIM_NAME)) ERR;
if (nc_rename_var(ncid, varid, NVAR_NAME)) ERR;
if (nc_enddef(ncid)) ERR;
if (nc_get_var_int(ncid, varid, lats_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (lats_in[ii] != lats[ii])
fprintf(stderr, "\tlats_in[%d] is %d, should be %d\n", ii, lats_in[ii], lats[ii]);
}
if (nc_get_var_float(ncid, var2id, rh_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (rh_in[ii] != rh[ii])
fprintf(stderr, "\trh_in[%d] is %g, should be %g\n", ii, rh_in[ii], rh[ii]);
}
if (nc_close(ncid)) ERR;
fprintf(stderr,"*** Test renaming just coordinate variable for %s...\n",
fmt_names[format]);
if (create_test_file(file_names[format], formats[format])) ERR;
if (nc_open(file_names[format], NC_WRITE, &ncid)) ERR;
if (nc_inq_dimid(ncid, ODIM_NAME, &dimid)) ERR;
if (nc_inq_varid(ncid, OVAR_NAME, &varid)) ERR;
if (nc_inq_varid(ncid, OVAR2_NAME, &var2id)) ERR;
if (nc_redef(ncid)) ERR; /* omitting this and nc_enddef call eliminates bug */
/* if (nc_rename_dim(ncid, dimid, NDIM_NAME)) ERR; */
if (nc_rename_var(ncid, varid, NVAR_NAME)) ERR;
if (nc_enddef(ncid)) ERR;
if (nc_get_var_int(ncid, varid, lats_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (lats_in[ii] != lats[ii])
fprintf(stderr, "\tlats_in[%d] is %d, should be %d\n", ii, lats_in[ii], lats[ii]);
}
if (nc_get_var_float(ncid, var2id, rh_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (rh_in[ii] != rh[ii])
fprintf(stderr, "\trh_in[%d] is %g, should be %g\n", ii, rh_in[ii], rh[ii]);
}
if (nc_close(ncid)) ERR;
fprintf(stderr,"*** Test renaming just coordinate dimension for %s...\n",
fmt_names[format]);
if (create_test_file(file_names[format], formats[format])) ERR;
if (nc_open(file_names[format], NC_WRITE, &ncid)) ERR;
if (nc_inq_dimid(ncid, ODIM_NAME, &dimid)) ERR;
if (nc_inq_varid(ncid, OVAR_NAME, &varid)) ERR;
if (nc_inq_varid(ncid, OVAR2_NAME, &var2id)) ERR;
if (nc_redef(ncid)) ERR; /* omitting this and nc_enddef call eliminates bug */
if (nc_rename_dim(ncid, dimid, NDIM_NAME)) ERR;
/* if (nc_rename_var(ncid, varid, NVAR_NAME)) ERR; */
if (nc_enddef(ncid)) ERR;
if (nc_get_var_int(ncid, varid, lats_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (lats_in[ii] != lats[ii])
fprintf(stderr, "\tlats_in[%d] is %d, should be %d\n", ii, lats_in[ii], lats[ii]);
}
if (nc_get_var_float(ncid, var2id, rh_in)) ERR;
for (ii = 0; ii < DIM_LEN; ii++) {
if (rh_in[ii] != rh[ii])
fprintf(stderr, "\trh_in[%d] is %g, should be %g\n", ii, rh_in[ii], rh[ii]);
}
if (nc_close(ncid)) ERR;
}
return(0);
}