From 8401e2087e9a73a00d2e0313648de2423eaea6fe Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Fri, 2 Dec 2016 08:17:47 -0700 Subject: [PATCH 01/12] Set variable no_fill to match database default (nc4) In nc4 mode, the variables were ignoring the default "database" fill/no_fill mode set via a call to nc_set_fill(). This sets the no_fill mode on the variable to match the default database setting at the time the variable is defined. --- libsrc4/nc4var.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc4/nc4var.c b/libsrc4/nc4var.c index 2da0d3e20..a808251c7 100644 --- a/libsrc4/nc4var.c +++ b/libsrc4/nc4var.c @@ -456,6 +456,7 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, var->varid = grp->nvars++; var->ndims = ndims; var->is_new_var = NC_TRUE; + var->no_fill = h5->fill_mode; nc4_vararray_add(grp, var); From f8e818385eae4b5e0e143c9241259ed4351f828b Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Mon, 5 Dec 2016 11:08:26 -0700 Subject: [PATCH 02/12] Modify previous no_fill setting HDF5 does not permit a variable to have no_fill == TRUE if the variable type is variable length. This includes types NC_STRING and NC_VLEN. The test above also excludes user-defined types which I'm not sure is needed or not. --- libsrc4/nc4var.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libsrc4/nc4var.c b/libsrc4/nc4var.c index a808251c7..b0baeec27 100644 --- a/libsrc4/nc4var.c +++ b/libsrc4/nc4var.c @@ -456,7 +456,6 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, var->varid = grp->nvars++; var->ndims = ndims; var->is_new_var = NC_TRUE; - var->no_fill = h5->fill_mode; nc4_vararray_add(grp, var); @@ -528,6 +527,13 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype, BAIL(NC_ENOMEM); } + /* Set variables no_fill to match the database default + * unless the variable type is variable length (NC_STRING or NC_VLEN) + * or is user-defined type. + */ + if (var->type_info->nc_type_class < NC_STRING) + var->no_fill = h5->fill_mode; + /* 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 From 73ccb364a9e1917d2658b6f08ba42a726e2e71f4 Mon Sep 17 00:00:00 2001 From: Wei-keng Liao Date: Fri, 24 Mar 2017 20:55:00 -0500 Subject: [PATCH 03/12] To solve NC_ELATEFILL error for NetCDF-4 files, mark all variables written at enddef. --- libsrc/Makefile.am | 2 +- libsrc4/nc4file.c | 10 ++++++++++ nc_test4/tst_vars2.c | 8 +++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libsrc/Makefile.am b/libsrc/Makefile.am index f7baf8720..ab15840bd 100644 --- a/libsrc/Makefile.am +++ b/libsrc/Makefile.am @@ -47,7 +47,7 @@ EXTRA_DIST = attr.m4 ncx.m4 putget.m4 $(man_MANS) CMakeLists.txt XGetopt.c # This tells make how to turn .m4 files into .c files. .m4.c: - m4 $(AM_M4FLAGS) $(M4FLAGS) -s $< >${srcdir}/$@ + m4 $(AM_M4FLAGS) $(M4FLAGS) -s $< > $@ # The C API man page. man_MANS = netcdf.3 diff --git a/libsrc4/nc4file.c b/libsrc4/nc4file.c index 90237ce9f..79ee63b35 100644 --- a/libsrc4/nc4file.c +++ b/libsrc4/nc4file.c @@ -2984,6 +2984,8 @@ static int NC4_enddef(int ncid) { NC *nc; NC_HDF5_FILE_INFO_T* nc4_info; + NC_GRP_INFO_T *grp; + int i; LOG((1, "%s: ncid 0x%x", __func__, ncid)); @@ -2991,6 +2993,14 @@ static int NC4_enddef(int ncid) return NC_EBADID; assert(nc4_info); + /* Find info for this file and group */ + if (!(grp = nc4_rec_find_grp(nc4_info->root_grp, (ncid & GRP_ID_MASK)))) + return NC_EBADGRPID; + + /* when exiting define mode, mark all variable written */ + for (i=0; ivars.nelems; i++) + grp->vars.value[i]->written_to = NC_TRUE; + return nc4_enddef_netcdf4_file(nc4_info); } diff --git a/nc_test4/tst_vars2.c b/nc_test4/tst_vars2.c index 5b8081bd3..4ed314720 100644 --- a/nc_test4/tst_vars2.c +++ b/nc_test4/tst_vars2.c @@ -61,13 +61,17 @@ main(int argc, char **argv) printf("**** testing simple fill value attribute creation..."); { + int status; /* Create a netcdf-4 file with one scalar var. Add fill * value. */ if (nc_create(FILE_NAME, cmode, &ncid)) ERR; if (nc_def_var(ncid, VAR_NAME, NC_BYTE, 0, NULL, &varid)) ERR; + if (nc_put_att_schar(ncid, varid, _FillValue, NC_BYTE, 1, &fill_value)) ERR; if (nc_enddef(ncid)) ERR; if (nc_redef(ncid)) ERR; - if (nc_put_att_schar(ncid, varid, _FillValue, NC_BYTE, 1, &fill_value)) ERR; + status = nc_put_att_schar(ncid, varid, _FillValue, NC_BYTE, 1, &fill_value); + if (status != NC_ELATEFILL) + printf("Error at line %d: expecting NC_ELATEFILL but got %s\n",__LINE__,nc_strerror(status)); if (nc_close(ncid)) ERR; /* Open the file and check. */ @@ -94,8 +98,6 @@ main(int argc, char **argv) if (nc_create(FILE_NAME, cmode, &ncid)) ERR; if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR; if (nc_def_var(ncid, VAR_NAME, NC_BYTE, NUM_DIMS, dimids, &varid)) ERR; - if (nc_enddef(ncid)) ERR; - if (nc_redef(ncid)) ERR; if (nc_put_att_schar(ncid, varid, _FillValue, NC_BYTE, 1, &fill_value)) ERR; if (nc_enddef(ncid)) ERR; From 0ff3616b0191a5d141448428a18f3d2488b2b2f1 Mon Sep 17 00:00:00 2001 From: Wei-keng Liao Date: Sat, 25 Mar 2017 13:59:39 -0500 Subject: [PATCH 04/12] NC_EINVAL should be returned when trying to set attribute _FillValue for global variable --- libdispatch/dattput.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/libdispatch/dattput.c b/libdispatch/dattput.c index 712375d6e..e58771ac1 100644 --- a/libdispatch/dattput.c +++ b/libdispatch/dattput.c @@ -53,6 +53,9 @@ nc_put_att_string(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, NC_STRING, len, (void*)value, NC_STRING); } @@ -141,6 +144,9 @@ int nc_put_att_text(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, NC_CHAR, len, (void *)value, NC_CHAR); } @@ -232,6 +238,9 @@ nc_put_att(int ncid, int varid, const char *name, nc_type xtype, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, value, xtype); } @@ -243,6 +252,9 @@ nc_put_att_schar(int ncid, int varid, const char *name, NC *ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_BYTE); } @@ -254,6 +266,9 @@ nc_put_att_uchar(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } @@ -265,6 +280,9 @@ nc_put_att_short(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_SHORT); } @@ -276,6 +294,9 @@ nc_put_att_int(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT); } @@ -287,6 +308,9 @@ nc_put_att_long(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, longtype); } @@ -298,6 +322,9 @@ nc_put_att_float(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_FLOAT); } @@ -309,6 +336,9 @@ nc_put_att_double(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_DOUBLE); } @@ -320,6 +350,9 @@ nc_put_att_ubyte(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } @@ -331,6 +364,9 @@ nc_put_att_ushort(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_USHORT); } @@ -342,6 +378,9 @@ nc_put_att_uint(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT); } @@ -354,6 +393,9 @@ nc_put_att_longlong(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT64); } @@ -366,6 +408,9 @@ nc_put_att_ulonglong(int ncid, int varid, const char *name, NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; + /* set global _FillValue is not allowed */ + if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) + return NC_EINVAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT64); } From f7f8a0ff90112ce231ad2858d10980412ca4e62c Mon Sep 17 00:00:00 2001 From: Wei-keng Liao Date: Sat, 25 Mar 2017 14:47:25 -0500 Subject: [PATCH 05/12] change error code from NC_EINVAL to NC_EGLOBAL when trying to set global _FillValue --- libdispatch/dattput.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libdispatch/dattput.c b/libdispatch/dattput.c index e58771ac1..a8a1feed2 100644 --- a/libdispatch/dattput.c +++ b/libdispatch/dattput.c @@ -37,7 +37,8 @@ apply. \param value Pointer to one or more values. \returns ::NC_NOERR No error. -\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue. +\returns ::NC_EINVAL More than one value for _FillValue. +\returns ::NC_EGLOBAL Trying to set global _FillValue. \returns ::NC_ENOTVAR Couldn't find varid. \returns ::NC_EBADTYPE Fill value and var must be same type. \returns ::NC_ENOMEM Out of memory @@ -55,7 +56,7 @@ nc_put_att_string(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, NC_STRING, len, (void*)value, NC_STRING); } @@ -90,7 +91,8 @@ apply. \param value Pointer to one or more values. \returns ::NC_NOERR No error. -\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue. +\returns ::NC_EINVAL More than one value for _FillValue. +\returns ::NC_EGLOBAL Trying to set global _FillValue. \returns ::NC_ENOTVAR Couldn't find varid. \returns ::NC_EBADTYPE Fill value and var must be same type. \returns ::NC_ENOMEM Out of memory @@ -146,7 +148,7 @@ int nc_put_att_text(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, NC_CHAR, len, (void *)value, NC_CHAR); } @@ -188,7 +190,8 @@ apply. \param value Pointer to one or more values. \returns ::NC_NOERR No error. -\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue. +\returns ::NC_EINVAL More than one value for _FillValue. +\returns ::NC_EGLOBAL Trying to set global _FillValue. \returns ::NC_ENOTVAR Couldn't find varid. \returns ::NC_EBADTYPE Fill value and var must be same type. \returns ::NC_ENOMEM Out of memory @@ -240,7 +243,7 @@ nc_put_att(int ncid, int varid, const char *name, nc_type xtype, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, value, xtype); } @@ -254,7 +257,7 @@ nc_put_att_schar(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_BYTE); } @@ -268,7 +271,7 @@ nc_put_att_uchar(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } @@ -282,7 +285,7 @@ nc_put_att_short(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_SHORT); } @@ -296,7 +299,7 @@ nc_put_att_int(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT); } @@ -310,7 +313,7 @@ nc_put_att_long(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, longtype); } @@ -324,7 +327,7 @@ nc_put_att_float(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_FLOAT); } @@ -338,7 +341,7 @@ nc_put_att_double(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_DOUBLE); } @@ -352,7 +355,7 @@ nc_put_att_ubyte(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } @@ -366,7 +369,7 @@ nc_put_att_ushort(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_USHORT); } @@ -380,7 +383,7 @@ nc_put_att_uint(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT); } @@ -395,7 +398,7 @@ nc_put_att_longlong(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT64); } @@ -410,7 +413,7 @@ nc_put_att_ulonglong(int ncid, int varid, const char *name, if(stat != NC_NOERR) return stat; /* set global _FillValue is not allowed */ if (varid == NC_GLOBAL && name != NULL && !strcmp(name, _FillValue)) - return NC_EINVAL; + return NC_EGLOBAL; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT64); } From 1508bd55298d8c1596b051879fe192c3d736b396 Mon Sep 17 00:00:00 2001 From: Wei-keng Liao Date: Wed, 29 Mar 2017 12:16:25 -0500 Subject: [PATCH 06/12] fix the previous commit that missed the case of re-open file --- libsrc4/nc4file.c | 6 +++++- nc_test4/tst_fill_attr_vanish.c | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libsrc4/nc4file.c b/libsrc4/nc4file.c index 79ee63b35..05a02bc60 100644 --- a/libsrc4/nc4file.c +++ b/libsrc4/nc4file.c @@ -2129,7 +2129,7 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp) hid_t pid = 0; unsigned crt_order_flags = 0; H5_index_t iter_index; - int retval = NC_NOERR; /* everything worked! */ + int i, retval = NC_NOERR; /* everything worked! */ assert(grp && grp->name); LOG((3, "%s: grp->name %s", __func__, grp->name)); @@ -2217,6 +2217,10 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp) if ((retval = read_grp_atts(grp))) BAIL(retval); + /* when exiting define mode, mark all variable written */ + for (i=0; ivars.nelems; i++) + grp->vars.value[i]->written_to = NC_TRUE; + exit: /* Clean up local information on error, if anything remains */ if (retval) diff --git a/nc_test4/tst_fill_attr_vanish.c b/nc_test4/tst_fill_attr_vanish.c index 2307ae8ec..511d41e1d 100644 --- a/nc_test4/tst_fill_attr_vanish.c +++ b/nc_test4/tst_fill_attr_vanish.c @@ -33,7 +33,7 @@ */ int main() { - int ncid, dimids[RANK_P], time_id, p_id, test_id; + int ncid, dimids[RANK_P], time_id, p_id, test_id, status; int ndims, dimids_in[RANK_P]; int test_data[1] = {1}; @@ -95,8 +95,15 @@ int main() } - printf("**** Adding _FillValue attribute.\n"); - if (nc_put_att_int(ncid, test_id, "_FillValue", NC_INT, 1, test_fill_val)) ERR; + printf("**** Expecting NC_ELATEFILL when adding _FillValue attribute if variable exists.\n"); + status = nc_put_att_int(ncid, test_id, "_FillValue", NC_INT, 1, test_fill_val); + if (status != NC_ELATEFILL) { + fflush(stdout); /* Make sure our stdout is synced with stderr. */ + err++; + fprintf(stderr, "Sorry! Expecting NC_ELATEFILL but got %s, at file %s line: %d\n", + nc_strerror(status), __FILE__, __LINE__); + return 2; + } /* Query existing attribute. */ { From 6b036cfc287f15c800d2e80440c0ba109b05c8d1 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 11:23:47 -0600 Subject: [PATCH 07/12] Adding test in support of https://github.com/Unidata/netcdf-c/issues/384 --- nc_test/CMakeLists.txt | 2 +- nc_test/Makefile.am | 4 ++-- nc_test/tst_elatefill.c | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 nc_test/tst_elatefill.c diff --git a/nc_test/CMakeLists.txt b/nc_test/CMakeLists.txt index f46ac171f..af7676547 100644 --- a/nc_test/CMakeLists.txt +++ b/nc_test/CMakeLists.txt @@ -22,7 +22,7 @@ TARGET_LINK_LIBRARIES(nc_test ) # Some extra stand-alone tests -SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type) +SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type tst_elatefill) IF(NOT HAVE_BASH) SET(TESTS ${TESTS} tst_atts3) diff --git a/nc_test/Makefile.am b/nc_test/Makefile.am index 242382909..e8d77cdb6 100644 --- a/nc_test/Makefile.am +++ b/nc_test/Makefile.am @@ -14,7 +14,7 @@ tst_*.nc t_nc.nc large_files.nc quick_large_files.nc \ tst_diskless.nc tst_diskless2.nc \ tst_diskless3.nc tst_diskless3_file.cdl tst_diskless3_memory.cdl \ tst_diskless4.cdl tst_diskless4.nc tst_formatx.nc nc_test_cdf5.nc \ -unlim.nc tst_inq_type.nc +unlim.nc tst_inq_type.nc tst_elatefill.nc # These are the tests which are always run. TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm \ @@ -22,7 +22,7 @@ TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm \ tst_meta tst_inq_type tst_utf8_validate tst_utf8_phrases if USE_NETCDF4 -TESTPROGRAMS += tst_atts tst_put_vars +TESTPROGRAMS += tst_atts tst_put_vars tst_elatefill endif if USE_PNETCDF diff --git a/nc_test/tst_elatefill.c b/nc_test/tst_elatefill.c new file mode 100644 index 000000000..4e9043ac2 --- /dev/null +++ b/nc_test/tst_elatefill.c @@ -0,0 +1,43 @@ +/* This is part of the netCDF package. Copyright 2017 University + Corporation for Atmospheric Research/Unidata See COPYRIGHT file for + conditions of use. See www.unidata.ucar.edu for more info. + + Test proper elatefill return when fillvalue is assigned outside of + the initial define. + + Contributed by wkliao, see the following for more information: + + * https://github.com/Unidata/netcdf-c/issues/384 + * https://github.com/Unidata/netcdf-c/pull/387 + * https://github.com/Unidata/netcdf-c/issues/390 +*/ + +#include "config.h" +#include +#include "err_macros.h" +#include +#include + +#define FILE_NAME "tst_elatefill.nc" + +int +main(int argc, char **argv) +{ + int ncid, dimid, varid, err; + int no_fill, fillv, buf[10]; + + err = nc_create(FILE_NAME, NC_NETCDF4, &ncid); ERR; + err = nc_def_dim(ncid, "dim", 10, &dimid); ERR; + err = nc_def_var(ncid, "var", NC_INT, 1, &dimid, &varid); ERR; + err = nc_enddef(ncid); ERR; + + err = nc_redef(ncid); ERR; + + /* try put attribute _FillValue and expect NC_ELATEFILL */ + fillv = 9; + err = nc_put_att_int(ncid, varid, _FillValue, NC_INT, 1, &fillv); + if (err != NC_ELATEFILL) + printf("line %d expecting NC_ELATEFILL but got %d\n",__LINE__,err); + err = nc_close(ncid); ERR; + return 0; +} From e5fb53f99656ebdb7873ef947638ddf81f03a427 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 11:38:59 -0600 Subject: [PATCH 08/12] Restored line that was accidentally removed. --- nc_test/tst_elatefill.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nc_test/tst_elatefill.c b/nc_test/tst_elatefill.c index 4e9043ac2..3f2099f92 100644 --- a/nc_test/tst_elatefill.c +++ b/nc_test/tst_elatefill.c @@ -20,6 +20,8 @@ #define FILE_NAME "tst_elatefill.nc" +#define ERR {if(err!=NC_NOERR)printf("Error at line %d: %s\n",__LINE__,nc_strerror(err));} + int main(int argc, char **argv) { From 4726c43b0eb5377ba3b702d30e9470fa734101d9 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 12:07:34 -0600 Subject: [PATCH 09/12] Updated release notes. --- RELEASE_NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 86ee99624..2b8262e79 100755 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -11,6 +11,7 @@ This file contains a high-level description of this package's evolution. Release ## 4.4.2 - TBD +* [Bug Fix] Corrected an issue where data loss would occur when `_FillValue` was mistakenly allowed to be redefined. See [Github #390](https://github.com/Unidata/netcdf-c/issues/390), [GitHub #387](https://github.com/Unidata/netcdf-c/pull/387) for more information. * [Enhancement] Modified netCDF4 to use ASCII for NC_CHAR. See [Github Pull request #316](https://github.com/Unidata/netcdf-c/pull/316) for more information. * [Upgrade][Bug] Corrected an issue regarding how "orphaned" DAS attributes were handled. See [GitHub #376](https://github.com/Unidata/netcdf-c/pull/376) for more information. * [Upgrade] Update utf8proc.[ch] to use the version now maintained by the Julia Language project (https://github.com/JuliaLang/utf8proc/blob/master/LICENSE.md). From 16169a27afff336e62c660f482c3002602804f81 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 15:25:38 -0600 Subject: [PATCH 10/12] Wiring in test in support of https://github.com/Unidata/netcdf-c/issues/388 --- nc_test/CMakeLists.txt | 3 ++- nc_test/Makefile.am | 5 ++-- nc_test/tst_global_fillval.c | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 nc_test/tst_global_fillval.c diff --git a/nc_test/CMakeLists.txt b/nc_test/CMakeLists.txt index af7676547..c86ed4e4a 100644 --- a/nc_test/CMakeLists.txt +++ b/nc_test/CMakeLists.txt @@ -22,7 +22,7 @@ TARGET_LINK_LIBRARIES(nc_test ) # Some extra stand-alone tests -SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type tst_elatefill) +SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type tst_global_fillval) IF(NOT HAVE_BASH) SET(TESTS ${TESTS} tst_atts3) @@ -31,6 +31,7 @@ ENDIF() IF(USE_NETCDF4) SET(TESTS ${TESTS} tst_atts) SET(TESTS ${TESTS} tst_put_vars) + SET(TESTS ${TESTS} tst_elatefill) ENDIF() IF(USE_PNETCDF) diff --git a/nc_test/Makefile.am b/nc_test/Makefile.am index e8d77cdb6..23b95c9a3 100644 --- a/nc_test/Makefile.am +++ b/nc_test/Makefile.am @@ -14,12 +14,13 @@ tst_*.nc t_nc.nc large_files.nc quick_large_files.nc \ tst_diskless.nc tst_diskless2.nc \ tst_diskless3.nc tst_diskless3_file.cdl tst_diskless3_memory.cdl \ tst_diskless4.cdl tst_diskless4.nc tst_formatx.nc nc_test_cdf5.nc \ -unlim.nc tst_inq_type.nc tst_elatefill.nc +unlim.nc tst_inq_type.nc tst_elatefill.nc tst_global_fillval.nc # These are the tests which are always run. TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm \ tst_names tst_nofill tst_nofill2 tst_nofill3 tst_atts3 \ - tst_meta tst_inq_type tst_utf8_validate tst_utf8_phrases + tst_meta tst_inq_type tst_utf8_validate tst_utf8_phrases \ + tst_global_fillval if USE_NETCDF4 TESTPROGRAMS += tst_atts tst_put_vars tst_elatefill diff --git a/nc_test/tst_global_fillval.c b/nc_test/tst_global_fillval.c new file mode 100644 index 000000000..5d15c8f44 --- /dev/null +++ b/nc_test/tst_global_fillval.c @@ -0,0 +1,45 @@ +/* This is part of the netCDF package. Copyright 2017 University + Corporation for Atmospheric Research/Unidata See COPYRIGHT file for + conditions of use. See www.unidata.ucar.edu for more info. + + Test proper elatefill return when fillvalue is assigned outside of + the initial define. + + Contributed by wkliao, see the following for more information: + + * https://github.com/Unidata/netcdf-c/issues/388 + * https://github.com/Unidata/netcdf-c/pull/389 +*/ + +#include "config.h" +#include +#include "err_macros.h" +#include +#include + +#define FILE_NAME "tst_global_fillval.nc" + +#define ERR {if(err!=NC_NOERR){printf("Error at line %d: %s\n",__LINE__,nc_strerror(err)); break;}} +int +main(int argc, char **argv) +{ + int i, ncid, cmode, err, fillv=9; + int formats[5]={0, + NC_64BIT_OFFSET, + NC_64BIT_DATA, + NC_NETCDF4, + NC_CLASSIC_MODEL | NC_NETCDF4}; + char *formatnames[5]={"CDF-1", "CDF-2", "CDF-5", "NETCDF4", "CLASSIC_MODEL"}; + + for (i=0; i<5; i++) { + cmode = NC_CLOBBER | formats[i]; + err = nc_create(FILE_NAME, cmode, &ncid); ERR + + err = nc_put_att_int(ncid, NC_GLOBAL, "_FillValue", NC_INT, 1, &fillv); + if (err != NC_EINVAL) + printf("%13s Error at line %d: expecting NC_EINVAL but got %d\n", + formatnames[i],__LINE__,err); + err = nc_close(ncid); ERR + } + return 0; +} From 92ef49d4ed446c812615cfcddb004285a78af942 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 15:43:45 -0600 Subject: [PATCH 11/12] Updated release notes. --- RELEASE_NOTES.md | 5 +---- nc_test/tst_global_fillval.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2b8262e79..26e7e0996 100755 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,12 +5,9 @@ Release Notes {#RELEASE_NOTES} This file contains a high-level description of this package's evolution. Releases are in reverse chronological order (most recent first). Note that, as of netcdf 4.2, the `netcdf-c++` and `netcdf-fortran` libraries have been separated into their own libraries. -## Important Notes - -* **The combination of netCDF-C library versions earlier than 4.4.1 and libhdf5 1.10.0+ should be avoided, as they will result in binary files not readable by systems using earlier libhdf5 versions.** - ## 4.4.2 - TBD +* [Bug Fix] `NC-EINVAL` is now properly returned when attempting to set a global `_FillValue` attribute. See [GitHub #388](https://github.com/Unidata/netcdf-c/issues/388) and [GitHub #389](https://github.com/Unidata/netcdf-c/issues/389) for more information. * [Bug Fix] Corrected an issue where data loss would occur when `_FillValue` was mistakenly allowed to be redefined. See [Github #390](https://github.com/Unidata/netcdf-c/issues/390), [GitHub #387](https://github.com/Unidata/netcdf-c/pull/387) for more information. * [Enhancement] Modified netCDF4 to use ASCII for NC_CHAR. See [Github Pull request #316](https://github.com/Unidata/netcdf-c/pull/316) for more information. * [Upgrade][Bug] Corrected an issue regarding how "orphaned" DAS attributes were handled. See [GitHub #376](https://github.com/Unidata/netcdf-c/pull/376) for more information. diff --git a/nc_test/tst_global_fillval.c b/nc_test/tst_global_fillval.c index 5d15c8f44..46ef131c4 100644 --- a/nc_test/tst_global_fillval.c +++ b/nc_test/tst_global_fillval.c @@ -13,17 +13,17 @@ #include "config.h" #include -#include "err_macros.h" #include #include #define FILE_NAME "tst_global_fillval.nc" -#define ERR {if(err!=NC_NOERR){printf("Error at line %d: %s\n",__LINE__,nc_strerror(err)); break;}} +#define ERR {if(err!=NC_NOERR){printf("Error at line %d: %s\n",__LINE__,nc_strerror(err)); toterrs++; break;}} int main(int argc, char **argv) { int i, ncid, cmode, err, fillv=9; + int toterrs = 0; int formats[5]={0, NC_64BIT_OFFSET, NC_64BIT_DATA, @@ -36,10 +36,14 @@ main(int argc, char **argv) err = nc_create(FILE_NAME, cmode, &ncid); ERR err = nc_put_att_int(ncid, NC_GLOBAL, "_FillValue", NC_INT, 1, &fillv); - if (err != NC_EINVAL) - printf("%13s Error at line %d: expecting NC_EINVAL but got %d\n", + if (err != NC_EINVAL) { + toterrs++; + printf("%13s Error at line %d: expecting NC_EINVAL but got %d\n", formatnames[i],__LINE__,err); - err = nc_close(ncid); ERR + } + err = nc_close(ncid); ERR; + } - return 0; + printf("Total errors: %d\n",toterrs); + return toterrs; } From 45e30475f6846cf9b8d45b43c3d6d46a79555c1d Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 29 Mar 2017 15:47:48 -0600 Subject: [PATCH 12/12] Updated release notes to reflect new return, modified test to check for proper expected return value. --- RELEASE_NOTES.md | 2 +- nc_test/tst_global_fillval.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 26e7e0996..75c670593 100755 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,7 +7,7 @@ This file contains a high-level description of this package's evolution. Release ## 4.4.2 - TBD -* [Bug Fix] `NC-EINVAL` is now properly returned when attempting to set a global `_FillValue` attribute. See [GitHub #388](https://github.com/Unidata/netcdf-c/issues/388) and [GitHub #389](https://github.com/Unidata/netcdf-c/issues/389) for more information. +* [Bug Fix] `NC_EGLOBAL` is now properly returned when attempting to set a global `_FillValue` attribute. See [GitHub #388](https://github.com/Unidata/netcdf-c/issues/388) and [GitHub #389](https://github.com/Unidata/netcdf-c/issues/389) for more information. * [Bug Fix] Corrected an issue where data loss would occur when `_FillValue` was mistakenly allowed to be redefined. See [Github #390](https://github.com/Unidata/netcdf-c/issues/390), [GitHub #387](https://github.com/Unidata/netcdf-c/pull/387) for more information. * [Enhancement] Modified netCDF4 to use ASCII for NC_CHAR. See [Github Pull request #316](https://github.com/Unidata/netcdf-c/pull/316) for more information. * [Upgrade][Bug] Corrected an issue regarding how "orphaned" DAS attributes were handled. See [GitHub #376](https://github.com/Unidata/netcdf-c/pull/376) for more information. diff --git a/nc_test/tst_global_fillval.c b/nc_test/tst_global_fillval.c index 46ef131c4..489931f8c 100644 --- a/nc_test/tst_global_fillval.c +++ b/nc_test/tst_global_fillval.c @@ -36,7 +36,7 @@ main(int argc, char **argv) err = nc_create(FILE_NAME, cmode, &ncid); ERR err = nc_put_att_int(ncid, NC_GLOBAL, "_FillValue", NC_INT, 1, &fillv); - if (err != NC_EINVAL) { + if (err != NC_EGLOBAL) { toterrs++; printf("%13s Error at line %d: expecting NC_EINVAL but got %d\n", formatnames[i],__LINE__,err);