Merge branch 'master' into dap4.dmh

This commit is contained in:
Ward Fisher 2017-03-30 13:23:32 -06:00 committed by GitHub
commit c774157d05
11 changed files with 192 additions and 19 deletions

View File

@ -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
* [Upgrade] The bash based test scripts have been upgraded to use a common test_common.sh include file that isolates build specific information.
* [Enhancement] DAP4 is now included. Since dap2 is the default for urls, dap4 must be specified by
(1) using "dap4:" as the url protocol, or
@ -19,6 +16,8 @@ This file contains a high-level description of this package's evolution. Release
Note that dap4 is disabled by default until the testserver situation is resolved.
* [Enhancement] The remote testing server can now be specified with the '--with-testserver" option to ./configure.
* [Refactor] the oc2 library is no longer independent of the main netcdf-c library. For example, it now uses ncuri, nclist, and ncbytes instead of its homegrown equivalents.
* [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.
* [Upgrade] Update utf8proc.[ch] to use the version now maintained by the Julia Language project (https://github.com/JuliaLang/utf8proc/blob/master/LICENSE.md).

View File

@ -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
@ -53,6 +54,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, NC_STRING,
len, (void*)value, NC_STRING);
}
@ -87,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
@ -141,6 +146,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, NC_CHAR, len,
(void *)value, NC_CHAR);
}
@ -182,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
@ -232,6 +241,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
value, xtype);
}
@ -243,6 +255,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_BYTE);
}
@ -254,6 +269,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_UBYTE);
}
@ -265,6 +283,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_SHORT);
}
@ -276,6 +297,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_INT);
}
@ -287,6 +311,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, longtype);
}
@ -298,6 +325,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_FLOAT);
}
@ -309,6 +339,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_DOUBLE);
}
@ -320,6 +353,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_UBYTE);
}
@ -331,6 +367,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_USHORT);
}
@ -342,6 +381,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_UINT);
}
@ -354,6 +396,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_INT64);
}
@ -366,6 +411,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_EGLOBAL;
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
(void *)value, NC_UINT64);
}

View File

@ -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

View File

@ -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; i<grp->vars.nelems; i++)
grp->vars.value[i]->written_to = NC_TRUE;
exit:
/* Clean up local information on error, if anything remains */
if (retval)
@ -2984,6 +2988,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 +2997,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; i<grp->vars.nelems; i++)
grp->vars.value[i]->written_to = NC_TRUE;
return nc4_enddef_netcdf4_file(nc4_info);
}

View File

@ -523,6 +523,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

View File

@ -30,7 +30,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_global_fillval)
IF(NOT HAVE_BASH)
SET(TESTS ${TESTS} tst_atts3)
@ -39,6 +39,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)

View File

@ -16,17 +16,18 @@ 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 tst_global_fillval.nc
check_PROGRAMS =
# 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
TESTPROGRAMS += tst_atts tst_put_vars tst_elatefill
endif
if USE_PNETCDF

45
nc_test/tst_elatefill.c Normal file
View File

@ -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/384
* https://github.com/Unidata/netcdf-c/pull/387
* https://github.com/Unidata/netcdf-c/issues/390
*/
#include "config.h"
#include <nc_tests.h>
#include "err_macros.h"
#include <stdio.h>
#include <netcdf.h>
#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)
{
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;
}

View File

@ -0,0 +1,49 @@
/* 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 <nc_tests.h>
#include <stdio.h>
#include <netcdf.h>
#define FILE_NAME "tst_global_fillval.nc"
#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,
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_EGLOBAL) {
toterrs++;
printf("%13s Error at line %d: expecting NC_EINVAL but got %d\n",
formatnames[i],__LINE__,err);
}
err = nc_close(ncid); ERR;
}
printf("Total errors: %d\n",toterrs);
return toterrs;
}

View File

@ -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. */
{

View File

@ -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;