Merge pull request #1191 from Unidata/v4.6.2-release-branch.wif

V4.6.2 release branch.wif
This commit is contained in:
Ward Fisher 2018-11-12 16:55:38 -07:00 committed by GitHub
commit 8cb325c33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 505 additions and 243 deletions

View File

@ -2,11 +2,14 @@ Release Notes {#RELEASE_NOTES}
=============
\brief Release notes file for the netcdf-c package.
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.
## 4.6.2 - TBD
* [Enhancement] Lazy att read - only read atts when user requests one of them. See [GitHub #857](https://github.com/Unidata/netcdf-c/issues/857).
* [Enhancement] Fast global att read - when global atts are read, they are read much more quickly. See [GitHub #857](https://github.com/Unidata/netcdf-c/issues/857).
## 4.6.2-rc2 November 1, 2018

View File

@ -349,34 +349,15 @@ AC_ARG_ENABLE([dap],
test "x$enable_dap" = xno || enable_dap=yes
AC_MSG_RESULT($enable_dap)
# We need curl for DAP.
AC_CHECK_LIB([curl],[curl_easy_setopt],[found_curl=yes],[found_curl=no])
if test "x$enable_dap" = "xyes" ; then
AC_SEARCH_LIBS([curl_easy_setopt],[curl curl.dll], [],
[AC_MSG_ERROR([curl required for remote access. Install curl or build with --disable-dap.])])
fi
# --enable-dap => enable-dap4
enable_dap4=$enable_dap
# Curl support is required if and only if any of these flags are set:
# 1. --enable-dap
if test "x$enable_dap" = "xyes" ; then
require_curl=yes
else
require_curl=no
fi
# See if the user provided us with a curl library
# Do an initial lib test for curl, but suppress the default action
AC_CHECK_LIB([curl],[curl_easy_setopt],[found_curl=yes],[found_curl=no])
# If curl is required but there is no curl, then complain
if test $require_curl = yes ; then
if test $found_curl = no ; then
AC_MSG_NOTICE([libcurl not found; disabling remote protocol(s) support])
enable_dap=no
enable_dap4=no
elif test $found_curl = yes ; then
# Redo the check lib to actually add -lcurl
#AC_CHECK_LIB([curl], [curl_easy_setopt])
AC_SEARCH_LIBS([curl_easy_setopt],[curl curl.dll], [], [])
fi
fi
# Default is now to always do the short remote tests
AC_MSG_CHECKING([whether dap remote testing should be enabled (default on)])
AC_ARG_ENABLE([dap-remote-tests],

View File

@ -150,7 +150,7 @@ Indicate where you want to install netCDF in another shell variable, for example
~~~~{.py}
$ # Build and install netCDF-4
$ NCDIR=/usr/local
$ CPPFLAGS=-I${H5DIR}/include LDFLAGS=-L${H5DIR}/lib ./configure --prefix=${NCDIR}
$ CPPFLAGS='-I${H5DIR}/include -I${ZDIR}/include' LDFLAGS='-L${H5DIR}/lib -L${ZDIR}/lib' ./configure --prefix=${NCDIR}
$ make check
$ make install # or sudo make install
~~~~

View File

@ -56,6 +56,25 @@ typedef struct NC_HDF5_FILE_INFO
hid_t hdfid;
} NC_HDF5_FILE_INFO_T;
/* This is a struct to handle the dim metadata. */
typedef struct NC_HDF5_DIM_INFO
{
hid_t hdf_dimscaleid; /* Non-zero if a DIM_WITHOUT_VARIABLE dataset is in use (no coord var). */
HDF5_OBJID_T hdf5_objid;
} NC_HDF5_DIM_INFO_T;
/** Strut to hold HDF5-specific info for attributes. */
typedef struct NC_HDF5_ATT_INFO
{
hid_t native_hdf_typeid; /* Native HDF5 datatype for attribute's data */
} NC_HDF5_ATT_INFO_T;
/* Struct to hold HDF5-specific info for a group. */
typedef struct NC_HDF5_GRP_INFO
{
hid_t hdf_grpid;
} NC_HDF5_GRP_INFO_T;
/* 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);

View File

@ -112,25 +112,24 @@ typedef struct NC_OBJ {
typedef struct NC_DIM_INFO
{
NC_OBJ hdr;
struct NC_GRP_INFO* container; /* containing group */
struct NC_GRP_INFO *container; /* containing group */
size_t len;
nc_bool_t unlimited; /* True if the dimension is unlimited */
nc_bool_t extended; /* True if the dimension needs to be extended */
nc_bool_t too_long; /* True if len is too big to fit in local size_t. */
hid_t hdf_dimscaleid; /* Non-zero if a DIM_WITHOUT_VARIABLE dataset is in use (no coord var). */
HDF5_OBJID_T hdf5_objid;
void *format_dim_info; /* Pointer to format-specific dim info. */
struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */
} NC_DIM_INFO_T;
typedef struct NC_ATT_INFO
{
NC_OBJ hdr;
struct NC_OBJ* container; /* containing group|var */
struct NC_OBJ *container; /* containing group|var */
int len;
nc_bool_t dirty; /* True if attribute modified */
nc_bool_t created; /* True if attribute already created */
nc_type nc_typeid; /* netCDF type of attribute's data */
hid_t native_hdf_typeid; /* Native HDF5 datatype for attribute's data */
void *format_att_info;
void *data;
nc_vlen_t *vldata; /* only used for vlen */
char **stdata; /* only for string type. */
@ -250,7 +249,7 @@ typedef struct NC_TYPE_INFO
typedef struct NC_GRP_INFO
{
NC_OBJ hdr;
hid_t hdf_grpid;
void *format_grp_info;
struct NC_FILE_INFO *nc4_info;
struct NC_GRP_INFO *parent;
int atts_not_read;

View File

@ -367,9 +367,12 @@ rclocate(const char* key, const char* hostport)
if(hostport == NULL) hostport = "";
for(found=0,i=0;i<nclistlength(rc);i++) {
triple = (NCTriple*)nclistget(rc,i);
size_t hplen = (triple->host == NULL ? 0 : strlen(triple->host));
int t;
int t;
size_t hplen;
triple = (NCTriple*)nclistget(rc,i);
hplen = (triple->host == NULL ? 0 : strlen(triple->host));
if(strcmp(key,triple->key) != 0) continue; /* keys do not match */
/* If the triple entry has no url, then use it
(because we have checked all other cases)*/

View File

@ -108,7 +108,7 @@ rehash(NC_hashmap* hm)
/* Locate where given object is or should be placed in indexp.
if fail to find spot return 0 else 1.
If deletok then a deleted slot is ok to return;
return invariant: return == 0 || *indexp is defined
return invariant: return == 0 || *indexp is defined
*/
static int
locate(NC_hashmap* hash, unsigned int hashkey, const char* key, size_t keysize, size_t* indexp, int deletedok)
@ -118,15 +118,15 @@ locate(NC_hashmap* hash, unsigned int hashkey, const char* key, size_t keysize,
size_t step = 1; /* simple linear probe */
int deletefound = 0;
size_t deletedindex = 0; /* first deleted entry encountered */
NC_hentry* entry;
TRACE("locate");
/* Compute starting point */
index = (size_t)(hashkey % hash->alloc);
/* Search table using linear probing */
for (i = 0; i < hash->alloc; i++) {
NC_hentry* entry = &hash->table[index];
if(entry->flags & ACTIVE) {
entry = &hash->table[index];
if(entry->flags & ACTIVE) {
if(indexp) *indexp = index; /* assume a match */
if(entry->hashkey == hashkey && entry->keysize == keysize) {
/* Check content */
@ -148,7 +148,7 @@ locate(NC_hashmap* hash, unsigned int hashkey, const char* key, size_t keysize,
index = (index + step) % hash->alloc;
}
if(deletedok && deletefound) {
if(indexp) *indexp = deletedindex;
if(indexp) *indexp = deletedindex;
return 1;
}
return 0;
@ -187,12 +187,13 @@ NC_hashmapnew(size_t startsize)
int
NC_hashmapadd(NC_hashmap* hash, uintptr_t data, const char* key, size_t keysize)
{
unsigned int hashkey;
NC_hentry* entry;
unsigned int hashkey;
TRACE("NC_hashmapadd");
if(key == NULL || keysize == 0)
return 0;
return 0;
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
if(hash->alloc*3/4 <= hash->active)
@ -203,7 +204,7 @@ NC_hashmapadd(NC_hashmap* hash, uintptr_t data, const char* key, size_t keysize)
rehash(hash);
continue; /* try on larger table */
}
NC_hentry* entry = &hash->table[index];
entry = &hash->table[index];
if(entry->flags & ACTIVE) {
/* key already exists in table => overwrite data */
entry->data = data;
@ -264,13 +265,13 @@ NC_hashmapget(NC_hashmap* hash, const char* key, size_t keysize, uintptr_t* data
return 0;
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
if(hash->active) {
size_t index;
NC_hentry* h;
if(!locate(hash,hashkey,key,keysize,&index,0))
size_t index;
NC_hentry* h;
if(!locate(hash,hashkey,key,keysize,&index,0))
return 0; /* not present */
h = &hash->table[index];
h = &hash->table[index];
if(h->flags & ACTIVE) {
if(datap) *datap = h->data;
if(datap) *datap = h->data;
return 1;
} else /* Not found */
return 0;
@ -300,7 +301,7 @@ NC_hashmapsetdata(NC_hashmap* hash, const char* key, size_t keysize, uintptr_t n
h = &hash->table[index];
assert((h->flags & ACTIVE) == ACTIVE);
h->data = newdata;
return 1;
return 1;
}
size_t
@ -339,7 +340,7 @@ Allows a hack by ncindex.
int
NC_hashmapdeactivate(NC_hashmap* map, uintptr_t data)
{
size_t i;
size_t i;
NC_hentry* h;
for(h=map->table,i=0;i<map->alloc;i++,h++) {
if((h->flags & ACTIVE) && h->data == data) {
@ -370,21 +371,23 @@ findPrimeGreaterThan(size_t val)
int L = 1; /* skip leading flag number */
int R = (n - 2); /* skip trailing flag */
unsigned int v = 0;
int m;
if(val >= 0xFFFFFFFF)
return 0; /* Too big */
return 0; /* Too big */
v = (unsigned int)val;
for(;;) {
if(L >= R) break;
int m = (L + R) / 2;
/* is this an acceptable prime? */
if(NC_primes[m-1] < v && NC_primes[m] >= v)
return NC_primes[m]; /* acceptable*/
else if(NC_primes[m-1] >= v)
R = m;
else if(NC_primes[m] < v)
L = m;
if(L >= R) break;
m = (L + R) / 2;
/* is this an acceptable prime? */
if(NC_primes[m-1] < v && NC_primes[m] >= v)
return NC_primes[m]; /* acceptable*/
else if(NC_primes[m-1] >= v)
R = m;
else if(NC_primes[m] < v)
L = m;
}
return 0;
}
@ -2046,6 +2049,7 @@ static unsigned int NC_nprimes = (sizeof(NC_primes) / sizeof(unsigned int));
void
printhashmapstats(NC_hashmap* hm)
{
size_t n,i;
size_t step = 1;
size_t maxchain = 0;
@ -2061,7 +2065,7 @@ printhashmapstats(NC_hashmap* hm)
default: /* empty slot, stop walking */
if(chainlen > maxchain) maxchain = chainlen;
goto next;
}
}
/* linear probe */
index = (index + step) % hm->alloc;
}

View File

@ -143,7 +143,8 @@ NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
{
if (varid == NC_GLOBAL)
{
if (H5Adelete(grp->hdf_grpid, att->hdr.name) < 0)
if (H5Adelete(((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid,
att->hdr.name) < 0)
return NC_EHDFERR;
}
else
@ -237,7 +238,7 @@ NC4_del_att(int ncid, int varid, const char *name)
/* Determine the location id in the HDF5 file. */
if (varid == NC_GLOBAL)
locid = grp->hdf_grpid;
locid = ((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid;
else if (var->created)
locid = var->hdf_datasetid;
@ -451,7 +452,11 @@ nc4_put_att(NC_GRP_INFO_T* grp, int varid, const char *name, nc_type file_type,
{
LOG((3, "adding attribute %s to the list...", norm_name));
if ((ret = nc4_att_list_add(attlist, norm_name, &att)))
BAIL (ret);
BAIL(ret);
/* Allocate storage for the HDF5 specific att info. */
if (!(att->format_att_info = calloc(1, sizeof(NC_HDF5_ATT_INFO_T))))
BAIL(NC_ENOMEM);
}
/* Now fill in the metadata. */

View File

@ -48,6 +48,7 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
int retval = NC_NOERR;
NC_FILE_INFO_T* nc4_info = NULL;
NC_HDF5_FILE_INFO_T *hdf5_info;
NC_HDF5_GRP_INFO_T *hdf5_grp;
#ifdef USE_PARALLEL4
NC_MPI_INFO *mpiinfo = NULL;
@ -71,6 +72,11 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
BAIL(NC_ENOMEM);
hdf5_info = (NC_HDF5_FILE_INFO_T *)nc4_info->format_file_info;
/* Add struct to hold HDF5-specific group info. */
if (!(nc4_info->root_grp->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T))))
return NC_ENOMEM;
hdf5_grp = (NC_HDF5_GRP_INFO_T *)nc4_info->root_grp->format_grp_info;
nc4_info->mem.inmemory = (cmode & NC_INMEMORY) == NC_INMEMORY;
nc4_info->mem.diskless = (cmode & NC_DISKLESS) == NC_DISKLESS;
nc4_info->mem.persist = (cmode & NC_PERSIST) == NC_PERSIST;
@ -216,8 +222,7 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
}
/* Open the root group. */
if ((nc4_info->root_grp->hdf_grpid = H5Gopen2(hdf5_info->hdfid, "/",
H5P_DEFAULT)) < 0)
if ((hdf5_grp->hdf_grpid = H5Gopen2(hdf5_info->hdfid, "/", H5P_DEFAULT)) < 0)
BAIL(NC_EFILEMETA);
/* Release the property lists. */

View File

@ -104,6 +104,10 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
if ((retval = nc4_dim_list_add(grp, norm_name, len, -1, &dim)))
return retval;
/* Create struct for HDF5-specific dim info. */
if (!(dim->format_dim_info = calloc(1, sizeof(NC_HDF5_DIM_INFO_T))))
return NC_ENOMEM;
/* Pass back the dimid. */
if (idp)
*idp = dim->hdr.id;
@ -204,7 +208,8 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
{
NC *nc;
NC_GRP_INFO_T *grp;
NC_DIM_INFO_T *dim, *tmpdim;
NC_DIM_INFO_T *dim;
NC_HDF5_DIM_INFO_T *hdf5_dim;
NC_FILE_INFO_T *h5;
char norm_name[NC_MAX_NAME + 1];
int retval;
@ -229,21 +234,19 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
if ((retval = nc4_check_name(name, norm_name)))
return retval;
/* Get the original dim */
if((retval=nc4_find_dim(grp,dimid,&dim,NULL)) != NC_NOERR)
return retval;
if(dim == NULL) /* No such dim */
return NC_EBADDIM;
/* Get the original dim. */
if ((retval = nc4_find_dim(grp, dimid, &dim, NULL)))
return retval;
assert(dim && dim->format_dim_info);
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
/* Check if new name is in use */
tmpdim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,norm_name);
if(tmpdim != NULL)
return NC_ENAMEINUSE;
/* Check if new name is in use. */
if (ncindexlookup(grp->dim, norm_name))
return NC_ENAMEINUSE;
/* Check for renaming dimension w/o variable */
if (dim->hdf_dimscaleid)
/* Check for renaming dimension w/o variable. */
if (hdf5_dim->hdf_dimscaleid)
{
/* Sanity check */
assert(!dim->coord_var);
LOG((3, "dim %s is a dim without variable", dim->hdr.name));
@ -261,14 +264,14 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
LOG((3, "dim is now named %s", dim->hdr.name));
dim->hdr.hashkey = NC_hashmapkey(dim->hdr.name,strlen(dim->hdr.name)); /* Fix hash key */
if(!ncindexrebuild(grp->dim))
return NC_EINTERNAL;
if (!ncindexrebuild(grp->dim))
return NC_EINTERNAL;
/* Check if dimension was a coordinate variable, but names are
* different now */
* different now. */
if (dim->coord_var && strcmp(dim->hdr.name, dim->coord_var->hdr.name))
{
/* Break up the coordinate variable */
/* Break up the coordinate variable. */
if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim)))
return retval;
}

View File

@ -258,15 +258,11 @@ nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio)
int
nc4_close_hdf5_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio)
{
NC_HDF5_FILE_INFO_T *hdf5_info;
int retval;
assert(h5 && h5->root_grp && h5->format_file_info);
LOG((3, "%s: h5->path %s abort %d", __func__, h5->controller->path, abort));
/* Get HDF5 specific info. */
hdf5_info = (NC_HDF5_FILE_INFO_T *)h5->format_file_info;
/* According to the docs, always end define mode on close. */
if (h5->flags & NC_INDEF)
h5->flags ^= NC_INDEF;

View File

@ -65,6 +65,8 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
* sync. */
if ((retval = nc4_grp_list_add(h5, grp, norm_name, &g)))
return retval;
if (!(g->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T))))
return NC_ENOMEM;
if (new_ncid)
*new_ncid = grp->nc4_info->controller->ext_ncid | g->hdr.id;
@ -89,7 +91,8 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
int
NC4_rename_grp(int grpid, const char *name)
{
NC_GRP_INFO_T *grp, *parent;
NC_GRP_INFO_T *grp;
NC_HDF5_GRP_INFO_T *hdf5_grp;
NC_FILE_INFO_T *h5;
char norm_name[NC_MAX_NAME + 1];
int retval;
@ -99,7 +102,10 @@ NC4_rename_grp(int grpid, const char *name)
/* Find info for this file and group, and set pointer to each. */
if ((retval = nc4_find_grp_h5(grpid, &grp, &h5)))
return retval;
assert(h5);
assert(h5 && grp && grp->format_grp_info);
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
if (h5->no_write)
return NC_EPERM; /* attempt to write to a read-only file */
@ -107,7 +113,6 @@ NC4_rename_grp(int grpid, const char *name)
/* Do not allow renaming the root group */
if (grp->parent == NULL)
return NC_EBADGRPID;
parent = grp->parent;
/* Check and normalize the name. */
if ((retval = nc4_check_name(name, norm_name)))
@ -115,7 +120,7 @@ NC4_rename_grp(int grpid, const char *name)
/* Check that this name is not in use as a var, grp, or type in the
* parent group (i.e. the group that grp is in). */
if ((retval = nc4_check_dup_name(parent, norm_name)))
if ((retval = nc4_check_dup_name(grp->parent, norm_name)))
return retval;
/* If it's not in define mode, switch to define mode. */
@ -124,22 +129,26 @@ NC4_rename_grp(int grpid, const char *name)
return retval;
/* Rename the group, if it exists in the file */
if (grp->hdf_grpid)
if (hdf5_grp->hdf_grpid)
{
NC_HDF5_GRP_INFO_T *parent_hdf5_grp;
parent_hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->parent->format_grp_info;
/* Close the group */
if (H5Gclose(grp->hdf_grpid) < 0)
if (H5Gclose(hdf5_grp->hdf_grpid) < 0)
return NC_EHDFERR;
grp->hdf_grpid = 0;
hdf5_grp->hdf_grpid = 0;
/* Attempt to rename & re-open the group, if the parent group is open */
if (grp->parent->hdf_grpid)
if (parent_hdf5_grp->hdf_grpid)
{
/* Rename the group */
if (H5Gmove(parent->hdf_grpid, grp->hdr.name, name) < 0)
if (H5Gmove(parent_hdf5_grp->hdf_grpid, grp->hdr.name, name) < 0)
return NC_EHDFERR;
/* Reopen the group, with the new name */
if ((grp->hdf_grpid = H5Gopen2(parent->hdf_grpid, name, H5P_DEFAULT)) < 0)
if ((hdf5_grp->hdf_grpid = H5Gopen2(parent_hdf5_grp->hdf_grpid, name,
H5P_DEFAULT)) < 0)
return NC_EHDFERR;
}
}
@ -151,7 +160,7 @@ NC4_rename_grp(int grpid, const char *name)
return NC_ENOMEM;
grp->hdr.hashkey = NC_hashmapkey(grp->hdr.name,strlen(grp->hdr.name)); /* Fix hash key */
if(!ncindexrebuild(parent->children))
if(!ncindexrebuild(grp->parent->children))
return NC_EINTERNAL;
return NC_NOERR;

View File

@ -279,7 +279,7 @@ nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T
/* Sanity checks */
assert(grp && coord_var && dim && dim->coord_var == coord_var &&
coord_var->dim[0] == dim && coord_var->dimids[0] == dim->hdr.id &&
!dim->hdf_dimscaleid);
!((NC_HDF5_DIM_INFO_T *)(dim->format_dim_info))->hdf_dimscaleid);
LOG((3, "%s dim %s was associated with var %s, but now has different name",
__func__, dim->hdr.name, coord_var->hdr.name));
@ -341,23 +341,29 @@ nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T
int
delete_existing_dimscale_dataset(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T *dim)
{
NC_HDF5_DIM_INFO_T *hdf5_dim;
NC_HDF5_GRP_INFO_T *hdf5_grp;
int retval;
assert(grp && dim);
assert(grp && grp->format_grp_info && dim && dim->format_dim_info);
LOG((2, "%s: deleting dimscale dataset %s dimid %d", __func__, dim->hdr.name,
dimid));
/* Get HDF5 specific grp and dim info. */
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Detach dimscale from any variables using it */
if ((retval = rec_detach_scales(grp, dimid, dim->hdf_dimscaleid)) < 0)
if ((retval = rec_detach_scales(grp, dimid, hdf5_dim->hdf_dimscaleid)) < 0)
return retval;
/* Close the HDF5 dataset */
if (H5Dclose(dim->hdf_dimscaleid) < 0)
if (H5Dclose(hdf5_dim->hdf_dimscaleid) < 0)
return NC_EHDFERR;
dim->hdf_dimscaleid = 0;
hdf5_dim->hdf_dimscaleid = 0;
/* Now delete the dataset. */
if (H5Gunlink(grp->hdf_grpid, dim->hdr.name) < 0)
if (H5Gunlink(hdf5_grp->hdf_grpid, dim->hdr.name) < 0)
return NC_EHDFERR;
return NC_NOERR;
@ -377,14 +383,21 @@ delete_existing_dimscale_dataset(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T *d
int
nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
{
NC_HDF5_DIM_INFO_T *hdf5_dim;
NC_HDF5_GRP_INFO_T *hdf5_grp;
int need_to_reattach_scales = 0;
int retval = NC_NOERR;
assert(grp && var && dim);
LOG((3, "%s: dim->hdr.name %s var->hdr.name %s", __func__, dim->hdr.name, var->hdr.name));
assert(grp && grp->format_grp_info && var && dim && dim->format_dim_info);
LOG((3, "%s: dim->hdr.name %s var->hdr.name %s", __func__, dim->hdr.name,
var->hdr.name));
/* Get HDF5-specific dim and group info. */
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Detach dimscales from the [new] coordinate variable */
if(var->dimscale_attached)
if (var->dimscale_attached)
{
int dims_detached = 0;
int finished = 0;
@ -394,7 +407,7 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
for (d = 0; d < var->ndims && !finished; d++)
{
/* Is there a dimscale attached to this axis? */
if(var->dimscale_attached[d])
if (var->dimscale_attached[d])
{
NC_GRP_INFO_T *g;
int k;
@ -402,9 +415,14 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
for (g = grp; g && !finished; g = g->parent)
{
NC_DIM_INFO_T *dim1;
for(k=0;k<ncindexsize(g->dim);k++)
NC_HDF5_DIM_INFO_T *hdf5_dim1;
for (k = 0; k < ncindexsize(g->dim); k++)
{
if((dim1 = (NC_DIM_INFO_T*)ncindexith(g->dim,k)) == NULL) continue;
dim1 = (NC_DIM_INFO_T *)ncindexith(g->dim, k);
assert(dim1 && dim1->format_dim_info);
hdf5_dim1 = (NC_HDF5_DIM_INFO_T *)dim1->format_dim_info;
if (var->dimids[d] == dim1->hdr.id)
{
hid_t dim_datasetid; /* Dataset ID for dimension */
@ -413,7 +431,7 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
if (dim1->coord_var)
dim_datasetid = dim1->coord_var->hdf_datasetid;
else
dim_datasetid = dim1->hdf_dimscaleid;
dim_datasetid = hdf5_dim1->hdf_dimscaleid;
/* dim_datasetid may be 0 in some cases when
* renames of dims and vars are happening. In
@ -441,16 +459,16 @@ nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, NC_DIM_INFO_T *dim)
}
/* Use variable's dataset ID for the dimscale ID. */
if (dim->hdf_dimscaleid && grp != NULL)
if (hdf5_dim->hdf_dimscaleid && grp != NULL)
{
LOG((3, "closing and unlinking dimscale dataset %s", dim->hdr.name));
if (H5Dclose(dim->hdf_dimscaleid) < 0)
if (H5Dclose(hdf5_dim->hdf_dimscaleid) < 0)
BAIL(NC_EHDFERR);
dim->hdf_dimscaleid = 0;
hdf5_dim->hdf_dimscaleid = 0;
/* Now delete the dimscale's dataset
(it will be recreated later, if necessary) */
if (H5Gunlink(grp->hdf_grpid, dim->hdr.name) < 0)
if (H5Gunlink(hdf5_grp->hdf_grpid, dim->hdr.name) < 0)
return NC_EDIMMETA;
}
@ -493,13 +511,16 @@ nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
NC_VAR_INFO_T *var;
NC_DIM_INFO_T *dim;
NC_ATT_INFO_T *att;
NC_HDF5_GRP_INFO_T *hdf5_grp;
int a;
int i;
int retval;
assert(grp);
assert(grp && grp->format_grp_info);
LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Recursively call this function for each child, if any, stopping
* if there is an error. */
for (i = 0; i < ncindexsize(grp->children); i++)
@ -507,14 +528,18 @@ nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
i))))
return retval;
/* Close HDF5 resources associated with attributes. */
/* Close HDF5 resources associated with global attributes. */
for (a = 0; a < ncindexsize(grp->att); a++)
{
NC_HDF5_ATT_INFO_T *hdf5_att;
att = (NC_ATT_INFO_T *)ncindexith(grp->att, a);
assert(att);
assert(att && att->format_att_info);
hdf5_att = (NC_HDF5_ATT_INFO_T *)att->format_att_info;
/* Close the HDF5 typeid. */
if (att->native_hdf_typeid && H5Tclose(att->native_hdf_typeid) < 0)
if (hdf5_att->native_hdf_typeid &&
H5Tclose(hdf5_att->native_hdf_typeid) < 0)
return NC_EHDFERR;
}
@ -534,11 +559,14 @@ nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
for (a = 0; a < ncindexsize(var->att); a++)
{
NC_HDF5_ATT_INFO_T *hdf5_att;
att = (NC_ATT_INFO_T *)ncindexith(var->att, a);
assert(att);
assert(att && att->format_att_info);
hdf5_att = (NC_HDF5_ATT_INFO_T *)att->format_att_info;
/* Close the HDF5 typeid if one is open. */
if (att->native_hdf_typeid && H5Tclose(att->native_hdf_typeid) < 0)
if (hdf5_att->native_hdf_typeid &&
H5Tclose(hdf5_att->native_hdf_typeid) < 0)
return NC_EHDFERR;
}
}
@ -546,13 +574,16 @@ nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
/* Close HDF5 resources associated with dims. */
for (i = 0; i < ncindexsize(grp->dim); i++)
{
NC_HDF5_DIM_INFO_T *hdf5_dim;
dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
assert(dim);
assert(dim && dim->format_dim_info);
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
/* If this is a dim without a coordinate variable, then close
* the HDF5 DIM_WITHOUT_VARIABLE dataset associated with this
* dim. */
if (dim->hdf_dimscaleid && H5Dclose(dim->hdf_dimscaleid) < 0)
if (hdf5_dim->hdf_dimscaleid && H5Dclose(hdf5_dim->hdf_dimscaleid) < 0)
return NC_EHDFERR;
}
@ -595,7 +626,7 @@ nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
/* Close the HDF5 group. */
LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
if (grp->hdf_grpid && H5Gclose(grp->hdf_grpid) < 0)
if (hdf5_grp->hdf_grpid && H5Gclose(hdf5_grp->hdf_grpid) < 0)
return NC_EHDFERR;
return NC_NOERR;

View File

@ -332,13 +332,18 @@ static int
check_for_classic_model(NC_GRP_INFO_T *root_grp, int *is_classic)
{
htri_t attr_exists = -1;
hid_t grpid;
/* Check inputs. */
assert(!root_grp->parent && is_classic);
assert(root_grp && root_grp->format_grp_info && !root_grp->parent
&& is_classic);
/* Get the HDF5 group id. */
grpid = ((NC_HDF5_GRP_INFO_T *)(root_grp->format_grp_info))->hdf_grpid;
/* If this attribute exists in the root group, then classic model
* is in effect. */
if ((attr_exists = H5Aexists(root_grp->hdf_grpid, NC3_STRICT_ATT_NAME)) < 0)
if ((attr_exists = H5Aexists(grpid, NC3_STRICT_ATT_NAME)) < 0)
return NC_EHDFERR;
*is_classic = attr_exists ? 1 : 0;
@ -388,6 +393,10 @@ nc4_open_file(const char *path, int mode, void* parameters, NC *nc)
if (!(nc4_info->format_file_info = calloc(1, sizeof(NC_HDF5_FILE_INFO_T))))
BAIL(NC_ENOMEM);
/* Add struct to hold HDF5-specific group info. */
if (!(nc4_info->root_grp->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T))))
return NC_ENOMEM;
nc4_info->mem.inmemory = ((mode & NC_INMEMORY) == NC_INMEMORY);
nc4_info->mem.diskless = ((mode & NC_DISKLESS) == NC_DISKLESS);
nc4_info->mem.persist = ((mode & NC_PERSIST) == NC_PERSIST);
@ -1033,36 +1042,40 @@ get_netcdf_type(NC_FILE_INFO_T *h5, hid_t native_typeid,
static int
read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
{
NC_HDF5_ATT_INFO_T *hdf5_att;
hid_t spaceid = 0, file_typeid = 0;
hsize_t dims[1] = {0}; /* netcdf attributes always 1-D. */
int retval = NC_NOERR;
size_t type_size;
int att_ndims;
hssize_t att_npoints;
H5T_class_t att_class;
int fixed_len_string = 0;
size_t fixed_size = 0;
int retval = NC_NOERR;
assert(att->hdr.name);
assert(att && att->hdr.name && att->format_att_info);
LOG((5, "%s: att->hdr.id %d att->hdr.name %s att->nc_typeid %d att->len %d",
__func__, att->hdr.id, att->hdr.name, (int)att->nc_typeid, att->len));
/* Get HDF5-sepecific info stuct for this attribute. */
hdf5_att = (NC_HDF5_ATT_INFO_T *)att->format_att_info;
/* Get type of attribute in file. */
if ((file_typeid = H5Aget_type(attid)) < 0)
return NC_EATTMETA;
if ((att->native_hdf_typeid = H5Tget_native_type(file_typeid,
if ((hdf5_att->native_hdf_typeid = H5Tget_native_type(file_typeid,
H5T_DIR_DEFAULT)) < 0)
BAIL(NC_EHDFERR);
if ((att_class = H5Tget_class(att->native_hdf_typeid)) < 0)
if ((att_class = H5Tget_class(hdf5_att->native_hdf_typeid)) < 0)
BAIL(NC_EATTMETA);
if (att_class == H5T_STRING &&
!H5Tis_variable_str(att->native_hdf_typeid))
!H5Tis_variable_str(hdf5_att->native_hdf_typeid))
{
fixed_len_string++;
if (!(fixed_size = H5Tget_size(att->native_hdf_typeid)))
if (!(fixed_size = H5Tget_size(hdf5_att->native_hdf_typeid)))
BAIL(NC_EATTMETA);
}
if ((retval = get_netcdf_type(grp->nc4_info, att->native_hdf_typeid,
if ((retval = get_netcdf_type(grp->nc4_info, hdf5_att->native_hdf_typeid,
&(att->nc_typeid))))
BAIL(retval);
@ -1139,7 +1152,7 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
{
if (!(att->vldata = malloc((unsigned int)(att->len * sizeof(hvl_t)))))
BAIL(NC_ENOMEM);
if (H5Aread(attid, att->native_hdf_typeid, att->vldata) < 0)
if (H5Aread(attid, hdf5_att->native_hdf_typeid, att->vldata) < 0)
BAIL(NC_EATTMETA);
}
else if (att->nc_typeid == NC_STRING)
@ -1167,7 +1180,7 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
BAIL(NC_ENOMEM);
/* Read the fixed-len strings as one big block. */
if (H5Aread(attid, att->native_hdf_typeid, contig_buf) < 0) {
if (H5Aread(attid, hdf5_att->native_hdf_typeid, contig_buf) < 0) {
free(contig_buf);
BAIL(NC_EATTMETA);
}
@ -1192,7 +1205,7 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
else
{
/* Read variable-length string atts. */
if (H5Aread(attid, att->native_hdf_typeid, att->stdata) < 0)
if (H5Aread(attid, hdf5_att->native_hdf_typeid, att->stdata) < 0)
BAIL(NC_EATTMETA);
}
}
@ -1200,7 +1213,7 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
{
if (!(att->data = malloc((unsigned int)(att->len * type_size))))
BAIL(NC_ENOMEM);
if (H5Aread(attid, att->native_hdf_typeid, att->data) < 0)
if (H5Aread(attid, hdf5_att->native_hdf_typeid, att->data) < 0)
BAIL(NC_EATTMETA);
}
}
@ -1593,6 +1606,10 @@ att_read_callbk(hid_t loc_id, const char *att_name, const H5A_info_t *ainfo,
if ((retval = nc4_att_list_add(list, att_name, &att)))
BAIL(-1);
/* Allocate storage for the HDF5 specific att info. */
if (!(att->format_att_info = calloc(1, sizeof(NC_HDF5_ATT_INFO_T))))
BAIL(-1);
/* Open the att by name. */
if ((attid = H5Aopen(loc_id, att_name, H5P_DEFAULT)) < 0)
BAIL(-1);
@ -1649,7 +1666,8 @@ nc4_read_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
att_info.grp = grp;
/* Determine where to read from in the HDF5 file. */
locid = var ? var->hdf_datasetid : grp->hdf_grpid;
locid = var ? var->hdf_datasetid :
((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid;
/* Now read all the attributes at this location, ignoring special
* netCDF hidden attributes. */
@ -1691,6 +1709,7 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
NC_DIM_INFO_T **dim)
{
NC_DIM_INFO_T *new_dim; /* Dimension added to group */
NC_HDF5_DIM_INFO_T *new_hdf5_dim; /* HDF5-specific dim info. */
char dimscale_name_att[NC_MAX_NAME + 1] = ""; /* Dimscale name, for checking if dim without var */
htri_t attr_exists = -1; /* Flag indicating hidden attribute exists */
hid_t attid = -1; /* ID of hidden attribute (to store dim ID) */
@ -1730,14 +1749,19 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
if ((retval = nc4_dim_list_add(grp, obj_name, len, assigned_id, &new_dim)))
BAIL(retval);
/* Create struct for HDF5-specific dim info. */
if (!(new_dim->format_dim_info = calloc(1, sizeof(NC_HDF5_DIM_INFO_T))))
BAIL(NC_ENOMEM);
new_hdf5_dim = (NC_HDF5_DIM_INFO_T *)new_dim->format_dim_info;
new_dim->too_long = too_long;
dimscale_created++;
new_dim->hdf5_objid.fileno[0] = statbuf->fileno[0];
new_dim->hdf5_objid.fileno[1] = statbuf->fileno[1];
new_dim->hdf5_objid.objno[0] = statbuf->objno[0];
new_dim->hdf5_objid.objno[1] = statbuf->objno[1];
new_hdf5_dim->hdf5_objid.fileno[0] = statbuf->fileno[0];
new_hdf5_dim->hdf5_objid.fileno[1] = statbuf->fileno[1];
new_hdf5_dim->hdf5_objid.objno[0] = statbuf->objno[0];
new_hdf5_dim->hdf5_objid.objno[1] = statbuf->objno[1];
/* If the dimscale has an unlimited dimension, then this dimension
* is unlimited. */
@ -1763,8 +1787,8 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
/* Hold open the dataset, since the dimension doesn't have a
* coordinate variable */
new_dim->hdf_dimscaleid = datasetid;
H5Iinc_ref(new_dim->hdf_dimscaleid); /* Increment number of objects using ID */
new_hdf5_dim->hdf_dimscaleid = datasetid;
H5Iinc_ref(new_hdf5_dim->hdf_dimscaleid); /* Increment number of objects using ID */
}
}
@ -1810,6 +1834,7 @@ read_dataset(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
const H5G_stat_t *statbuf)
{
NC_DIM_INFO_T *dim = NULL; /* Dimension created for scales */
NC_HDF5_DIM_INFO_T *hdf5_dim;
hid_t spaceid = 0;
int ndims;
htri_t is_scale;
@ -1837,12 +1862,13 @@ read_dataset(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
if ((retval = read_scale(grp, datasetid, obj_name, statbuf, dims[0],
max_dims[0], &dim)))
BAIL(retval);
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
}
/* 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 (NULL == dim || (dim && !dim->hdf_dimscaleid))
if (!dim || (dim && !hdf5_dim->hdf_dimscaleid))
if ((retval = read_var(grp, datasetid, obj_name, ndims, dim)))
BAIL(retval);
@ -1991,28 +2017,35 @@ exit:
static int
nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
NC4_rec_read_metadata_ud_t udata; /* User data for iteration */
NC4_rec_read_metadata_obj_info_t *oinfo; /* Pointer to info for object */
hsize_t idx=0;
hsize_t idx = 0;
hid_t pid = 0;
unsigned crt_order_flags = 0;
H5_index_t iter_index;
int i, retval = NC_NOERR; /* everything worked! */
assert(grp && grp->hdr.name);
assert(grp && grp->hdr.name && grp->format_grp_info);
LOG((3, "%s: grp->hdr.name %s", __func__, grp->hdr.name));
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Portably initialize user data for later */
memset(&udata, 0, sizeof(udata));
/* 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 (!hdf5_grp->hdf_grpid)
{
if (grp->parent)
{
if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid,
grp->hdr.name, H5P_DEFAULT)) < 0)
NC_HDF5_GRP_INFO_T *parent_hdf5_grp;
parent_hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->parent->format_grp_info;
if ((hdf5_grp->hdf_grpid = H5Gopen2(parent_hdf5_grp->hdf_grpid,
grp->hdr.name, H5P_DEFAULT)) < 0)
BAIL(NC_EHDFERR);
}
else
@ -2020,15 +2053,15 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
NC_HDF5_FILE_INFO_T *hdf5_info;
hdf5_info = (NC_HDF5_FILE_INFO_T *)grp->nc4_info->format_file_info;
if ((grp->hdf_grpid = H5Gopen2(hdf5_info->hdfid, "/",
H5P_DEFAULT)) < 0)
if ((hdf5_grp->hdf_grpid = H5Gopen2(hdf5_info->hdfid, "/",
H5P_DEFAULT)) < 0)
BAIL(NC_EHDFERR);
}
}
assert(grp->hdf_grpid > 0);
assert(hdf5_grp->hdf_grpid > 0);
/* Get the group creation flags, to check for creation ordering */
pid = H5Gget_create_plist(grp->hdf_grpid);
pid = H5Gget_create_plist(hdf5_grp->hdf_grpid);
H5Pget_link_creation_order(pid, &crt_order_flags);
if (H5Pclose(pid) < 0)
BAIL(NC_EHDFERR);
@ -2053,23 +2086,27 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
/* Iterate over links in this group, building lists for the types,
* datasets and groups encountered. */
if (H5Literate(grp->hdf_grpid, iter_index, H5_ITER_INC, &idx,
if (H5Literate(hdf5_grp->hdf_grpid, iter_index, H5_ITER_INC, &idx,
nc4_rec_read_metadata_cb, (void *)&udata) < 0)
BAIL(NC_EHDFERR);
/* Process the child groups found. (Deferred until now, so that the
* types in the current group get processed and are available for
* vars in the child group(s).) */
for(i=0;i<nclistlength(udata.grps);i++)
for (i = 0; i < nclistlength(udata.grps); i++)
{
NC_GRP_INFO_T *child_grp;
oinfo = (NC4_rec_read_metadata_obj_info_t*)nclistget(udata.grps,i);
oinfo = (NC4_rec_read_metadata_obj_info_t*)nclistget(udata.grps, i);
/* Add group to file's hierarchy */
if ((retval = nc4_grp_list_add(grp->nc4_info, grp, oinfo->oname,
&child_grp)))
BAIL(retval);
/* Allocate storage for HDF5-specific group info. */
if (!(child_grp->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T))))
return NC_ENOMEM;
/* Recursively read the child group's metadata */
if ((retval = nc4_rec_read_metadata(child_grp)))
BAIL(retval);
@ -2083,15 +2120,16 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
grp->atts_not_read = 1;
/* when exiting define mode, mark all variable written */
for (i=0; i<ncindexsize(grp->vars); i++) {
for (i = 0; i < ncindexsize(grp->vars); i++)
{
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
if(var == NULL) continue;
assert(var);
var->written_to = NC_TRUE;
}
exit:
/* Clean up local information, if anything remains */
for(i=0;i<nclistlength(udata.grps);i++)
for (i = 0; i < nclistlength(udata.grps); i++)
{
oinfo = (NC4_rec_read_metadata_obj_info_t*)nclistget(udata.grps,i);
if (retval)

View File

@ -30,9 +30,16 @@ int
nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
{
hid_t access_pid;
hid_t grpid;
assert(var && grp && grp->format_grp_info);
if (var->hdf_datasetid)
{
/* Get the HDF5 group id. */
grpid = ((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid;
if ((access_pid = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
return NC_EHDFERR;
if (H5Pset_chunk_cache(access_pid, var->chunk_cache_nelems,
@ -41,8 +48,7 @@ nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
return NC_EHDFERR;
if (H5Dclose(var->hdf_datasetid) < 0)
return NC_EHDFERR;
if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdr.name,
access_pid)) < 0)
if ((var->hdf_datasetid = H5Dopen2(grpid, var->hdr.name, access_pid)) < 0)
return NC_EHDFERR;
if (H5Pclose(access_pid) < 0)
return NC_EHDFERR;
@ -250,6 +256,7 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
NC_DIM_INFO_T *dim;
NC_FILE_INFO_T *h5;
NC_TYPE_INFO_T *type_info = NULL;
NC_HDF5_GRP_INFO_T *hdf5_grp;
char norm_name[NC_MAX_NAME + 1];
int d;
int retval;
@ -257,7 +264,10 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
/* Find info for this file and group, and set pointer to each. */
if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
BAIL(retval);
assert(grp && h5);
assert(grp && grp->format_grp_info && h5);
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* HDF5 allows maximum of 32 dimensions. */
if (ndims > H5S_MAX_RANK)
@ -404,10 +414,13 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
for (d = 0; d < ndims; d++)
{
NC_GRP_INFO_T *dim_grp;
NC_HDF5_DIM_INFO_T *hdf5_dim;
/* Look up each dimension */
if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, &dim_grp)))
BAIL(retval);
assert(dim && dim->format_dim_info);
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
/* Check for dim index 0 having the same name, in the same group */
if (d == 0 && dim_grp == grp && strcmp(dim->hdr.name, norm_name) == 0)
@ -418,20 +431,21 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
/* Use variable's dataset ID for the dimscale ID. So delete
* the HDF5 DIM_WITHOUT_VARIABLE dataset that was created for
* this dim. */
if (dim->hdf_dimscaleid)
if (hdf5_dim->hdf_dimscaleid)
{
/* Detach dimscale from any variables using it */
if ((retval = rec_detach_scales(grp, dimidsp[d], dim->hdf_dimscaleid)) < 0)
if ((retval = rec_detach_scales(grp, dimidsp[d],
hdf5_dim->hdf_dimscaleid)) < 0)
BAIL(retval);
/* Close the HDF5 DIM_WITHOUT_VARIABLE dataset. */
if (H5Dclose(dim->hdf_dimscaleid) < 0)
if (H5Dclose(hdf5_dim->hdf_dimscaleid) < 0)
BAIL(NC_EHDFERR);
dim->hdf_dimscaleid = 0;
hdf5_dim->hdf_dimscaleid = 0;
/* Now delete the DIM_WITHOUT_VARIABLE dataset (it will be
* recreated later, if necessary). */
if (H5Gunlink(grp->hdf_grpid, dim->hdr.name) < 0)
if (H5Gunlink(hdf5_grp->hdf_grpid, dim->hdr.name) < 0)
BAIL(NC_EDIMMETA);
}
}
@ -1007,6 +1021,7 @@ NC4_rename_var(int ncid, int varid, const char *name)
{
NC *nc;
NC_GRP_INFO_T *grp;
NC_HDF5_GRP_INFO_T *hdf5_grp;
NC_FILE_INFO_T *h5;
NC_VAR_INFO_T *var, *tmpvar;
int retval = NC_NOERR;
@ -1020,7 +1035,10 @@ NC4_rename_var(int ncid, int varid, const char *name)
/* Find info for this file and group, and set pointer to each. */
if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
return retval;
assert(h5 && grp && h5);
assert(h5 && grp && grp->format_grp_info && h5);
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Is the new name too long? */
if (strlen(name) > NC_MAX_NAME)
@ -1053,20 +1071,26 @@ NC4_rename_var(int ncid, int varid, const char *name)
return NC_ENOTINDEFINE;
/* Change the HDF5 file, if this var has already been created
there. Should we check here to ensure there is not already a
dimscale dataset of name name??? */
there. */
if (var->created)
{
/* Is there an existing dimscale-only dataset of this name? If
* so, it must be deleted. */
if (var->ndims && var->dim[0]->hdf_dimscaleid)
if (var->ndims)
{
if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->hdr.id, var->dim[0])))
return retval;
NC_HDF5_DIM_INFO_T *hdf5_d0;
hdf5_d0 = (NC_HDF5_DIM_INFO_T *)var->dim[0]->format_dim_info;
/* Is there an existing dimscale-only dataset of this name? If
* so, it must be deleted. */
if (hdf5_d0->hdf_dimscaleid)
{
if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->hdr.id,
var->dim[0])))
return retval;
}
}
LOG((3, "Moving dataset %s to %s", var->hdr.name, name));
if (H5Gmove(grp->hdf_grpid, var->hdr.name, name) < 0)
if (H5Gmove(hdf5_grp->hdf_grpid, var->hdr.name, name) < 0)
BAIL(NC_EHDFERR);
}

View File

@ -180,6 +180,8 @@ nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset)
{
NC_VAR_INFO_T *var;
assert(grp && grp->format_grp_info && dataset);
/* Find the requested varid. */
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
if (!var) return NC_ENOTVAR;
@ -187,9 +189,14 @@ nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset)
/* Open this dataset if necessary. */
if (!var->hdf_datasetid)
if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdr.name,
H5P_DEFAULT)) < 0)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
if ((var->hdf_datasetid = H5Dopen2(hdf5_grp->hdf_grpid,
var->hdr.name, H5P_DEFAULT)) < 0)
return NC_ENOTVAR;
}
*dataset = var->hdf_datasetid;
@ -542,6 +549,7 @@ exit:
static int
put_att_grpa(NC_GRP_INFO_T *grp, int varid, NC_ATT_INFO_T *att)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
hid_t datasetid = 0, locid;
hid_t attid = 0, spaceid = 0, file_typeid = 0;
hid_t existing_att_typeid = 0, existing_attid = 0, existing_spaceid = 0;
@ -552,18 +560,21 @@ put_att_grpa(NC_GRP_INFO_T *grp, int varid, NC_ATT_INFO_T *att)
int phoney_data = 99;
int retval = NC_NOERR;
assert(att->hdr.name);
assert(att->hdr.name && grp && grp->format_grp_info);
LOG((3, "%s: varid %d att->hdr.id %d att->hdr.name %s att->nc_typeid %d "
"att->len %d", __func__, varid, att->hdr.id, att->hdr.name,
att->nc_typeid, att->len));
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* If the file is read-only, return an error. */
if (grp->nc4_info->no_write)
BAIL(NC_EPERM);
/* Get the hid to attach the attribute to, or read it from. */
if (varid == NC_GLOBAL)
locid = grp->hdf_grpid;
locid = hdf5_grp->hdf_grpid;
else
{
if ((retval = nc4_open_var_grp2(grp, varid, &datasetid)))
@ -827,6 +838,7 @@ write_netcdf4_dimid(hid_t datasetid, int dimid)
static int
var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, nc_bool_t write_dimid)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
hid_t plistid = 0, access_plistid = 0, typeid = 0, spaceid = 0;
hsize_t chunksize[H5S_MAX_RANK], dimsize[H5S_MAX_RANK], maxdimsize[H5S_MAX_RANK];
int d;
@ -835,8 +847,13 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, nc_bool_t write_dimid
char *name_to_use;
int retval;
assert(grp && grp->format_grp_info && var);
LOG((3, "%s:: name %s", __func__, var->hdr.name));
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Scalar or not, we need a creation property list. */
if ((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0)
BAIL(NC_EHDFERR);
@ -1024,7 +1041,7 @@ var_create_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, nc_bool_t write_dimid
name_to_use = var->hdf5_name ? var->hdf5_name : var->hdr.name;
LOG((4, "%s: about to H5Dcreate2 dataset %s of type 0x%x", __func__,
name_to_use, typeid));
if ((var->hdf_datasetid = H5Dcreate2(grp->hdf_grpid, name_to_use, typeid,
if ((var->hdf_datasetid = H5Dcreate2(hdf5_grp->hdf_grpid, name_to_use, typeid,
spaceid, H5P_DEFAULT, plistid, access_plistid)) < 0)
BAIL(NC_EHDFERR);
var->created = NC_TRUE;
@ -1142,9 +1159,13 @@ nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
static int
commit_type(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
int retval;
assert(grp && type);
assert(grp && grp->format_grp_info && type);
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Did we already record this type? */
if (type->committed)
@ -1247,7 +1268,7 @@ commit_type(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type)
}
/* Commit the type. */
if (H5Tcommit(grp->hdf_grpid, type->hdr.name, type->hdf_typeid) < 0)
if (H5Tcommit(hdf5_grp->hdf_grpid, type->hdr.name, type->hdf_typeid) < 0)
return NC_EHDFERR;
type->committed = NC_TRUE;
LOG((4, "just committed type %s, HDF typeid: 0x%x", type->hdr.name,
@ -1321,10 +1342,17 @@ exit:
static int
create_group(NC_GRP_INFO_T *grp)
{
NC_HDF5_GRP_INFO_T *hdf5_grp, *parent_hdf5_grp;
hid_t gcpl_id = -1;
int retval = NC_NOERR;;
assert(grp && grp->parent && grp->parent->hdf_grpid);
assert(grp && grp->format_grp_info && grp->parent &&
grp->parent->format_grp_info);
/* Get HDF5 specific group info for group and parent. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
parent_hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->parent->format_grp_info;
assert(parent_hdf5_grp->hdf_grpid);
/* Create group, with link_creation_order set in the group
* creation property list. */
@ -1344,15 +1372,15 @@ create_group(NC_GRP_INFO_T *grp)
BAIL(NC_EHDFERR);
/* Create the group. */
if ((grp->hdf_grpid = H5Gcreate2(grp->parent->hdf_grpid, grp->hdr.name,
H5P_DEFAULT, gcpl_id, H5P_DEFAULT)) < 0)
if ((hdf5_grp->hdf_grpid = H5Gcreate2(parent_hdf5_grp->hdf_grpid, grp->hdr.name,
H5P_DEFAULT, gcpl_id, H5P_DEFAULT)) < 0)
BAIL(NC_EHDFERR);
exit:
if (gcpl_id > -1 && H5Pclose(gcpl_id) < 0)
BAIL2(NC_EHDFERR);
if (retval)
if (grp->hdf_grpid > 0 && H5Gclose(grp->hdf_grpid) < 0)
if (hdf5_grp->hdf_grpid > 0 && H5Gclose(hdf5_grp->hdf_grpid) < 0)
BAIL2(NC_EHDFERR);
return retval;
}
@ -1399,9 +1427,11 @@ attach_dimscales(NC_GRP_INFO_T *grp)
{
if (!var->dimscale_attached[d])
{
NC_HDF5_DIM_INFO_T *hdf5_dim1;
hid_t dim_datasetid; /* Dataset ID for dimension */
dim1 = var->dim[d];
assert(dim1 && dim1->hdr.id == var->dimids[d]);
assert(dim1 && dim1->hdr.id == var->dimids[d] && dim1->format_dim_info);
hdf5_dim1 = (NC_HDF5_DIM_INFO_T *)dim1->format_dim_info;
LOG((2, "%s: attaching scale for dimid %d to var %s",
__func__, var->dimids[d], var->hdr.name));
@ -1410,7 +1440,7 @@ attach_dimscales(NC_GRP_INFO_T *grp)
if (dim1->coord_var)
dim_datasetid = dim1->coord_var->hdf_datasetid;
else
dim_datasetid = dim1->hdf_dimscaleid;
dim_datasetid = hdf5_dim1->hdf_dimscaleid;
if(!(dim_datasetid > 0))
assert(dim_datasetid > 0);
if (H5DSattach_scale(var->hdf_datasetid, dim_datasetid, d) < 0)
@ -1535,11 +1565,17 @@ remove_coord_atts(hid_t hdf_datasetid)
static int
write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
nc_bool_t replace_existing_var = NC_FALSE;
int retval;
assert(var && grp && grp->format_grp_info);
LOG((4, "%s: writing var %s", __func__, var->hdr.name));
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* If the variable has already been created & the fill value changed,
* indicate that the existing variable should be replaced. */
if (var->created && var->fill_val_changed)
@ -1566,13 +1602,15 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
NC_DIM_INFO_T *d1;
int i;
for(i=0;i<ncindexsize(grp->dim);i++) {
if((d1 = (NC_DIM_INFO_T*)ncindexith(grp->dim,i)) == NULL) continue;
for (i = 0; i < ncindexsize(grp->dim); i++)
{
d1 = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
assert(d1);
if (!strcmp(d1->hdr.name, var->hdr.name))
{
nc_bool_t exists;
if ((retval = var_exists(grp->hdf_grpid, var->hdr.name, &exists)))
if ((retval = var_exists(hdf5_grp->hdf_grpid, var->hdr.name, &exists)))
return retval;
if (exists)
{
@ -1585,25 +1623,33 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
}
}
/* Check dims if the variable will be replaced, so that the dimensions
* will be de-attached and re-attached correctly. */
/* (Note: There's a temptation to merge this loop over the dimensions with
* the prior loop over dimensions, but that blurs the line over the
* purpose of them, so they are currently separate. If performance
* becomes an issue here, it would be possible to merge them. -QAK)
/* Check dims if the variable will be replaced, so that the
* dimensions will be de-attached and re-attached correctly. (Note:
* There's a temptation to merge this loop over the dimensions with
* the prior loop over dimensions, but that blurs the line over the
* purpose of them, so they are currently separate. If performance
* becomes an issue here, it would be possible to merge them. -QAK)
*/
if (replace_existing_var)
{
NC_DIM_INFO_T *d1;
int i;
for(i=0;i<ncindexsize(grp->dim);i++) {
if((d1 = (NC_DIM_INFO_T*)ncindexith(grp->dim,i)) == NULL) continue;
for (i = 0; i < ncindexsize(grp->dim); i++)
{
NC_DIM_INFO_T *d1;
NC_HDF5_DIM_INFO_T *hdf5_d1;
/* Get info about the dim, including HDF5-specific info. */
d1 = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
assert(d1 && d1->format_dim_info && d1->hdr.name);
hdf5_d1 = (NC_HDF5_DIM_INFO_T *)d1->format_dim_info;
if (!strcmp(d1->hdr.name, var->hdr.name))
{
nc_bool_t exists;
if ((retval = var_exists(grp->hdf_grpid, var->hdr.name, &exists)))
if ((retval = var_exists(hdf5_grp->hdf_grpid, var->hdr.name,
&exists)))
return retval;
if (exists)
{
@ -1613,7 +1659,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
if (d1->coord_var)
dim_datasetid = d1->coord_var->hdf_datasetid;
else
dim_datasetid = d1->hdf_dimscaleid;
dim_datasetid = hdf5_d1->hdf_dimscaleid;
assert(dim_datasetid > 0);
/* If we're replacing an existing dimscale dataset, go to
@ -1647,23 +1693,27 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
/* If this is a regular var, detach all its dim scales. */
for (d = 0; d < var->ndims; d++)
{
if (var->dimscale_attached[d])
{
hid_t dim_datasetid; /* Dataset ID for dimension */
NC_DIM_INFO_T *dim1 = var->dim[d];
assert(dim1 && dim1->hdr.id == var->dimids[d]);
NC_HDF5_DIM_INFO_T *hdf5_dim1;
assert(dim1 && dim1->hdr.id == var->dimids[d] && dim1->format_dim_info);
hdf5_dim1 = (NC_HDF5_DIM_INFO_T *)dim1->format_dim_info;
/* Find dataset ID for dimension */
if (dim1->coord_var)
dim_datasetid = dim1->coord_var->hdf_datasetid;
else
dim_datasetid = dim1->hdf_dimscaleid;
dim_datasetid = hdf5_dim1->hdf_dimscaleid;
assert(dim_datasetid > 0);
if (H5DSdetach_scale(var->hdf_datasetid, dim_datasetid, d) < 0)
BAIL(NC_EHDFERR);
var->dimscale_attached[d] = NC_FALSE;
}
}
}
}
@ -1676,7 +1726,7 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
var->hdf_datasetid = 0;
/* Now delete the variable. */
if (H5Gunlink(grp->hdf_grpid, var->hdr.name) < 0)
if (H5Gunlink(hdf5_grp->hdf_grpid, var->hdr.name) < 0)
return NC_EDIMMETA;
}
@ -1745,13 +1795,21 @@ exit:
static int
write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
{
NC_HDF5_GRP_INFO_T *hdf5_grp;
NC_HDF5_DIM_INFO_T *hdf5_dim;
int retval;
assert(dim && dim->format_dim_info && grp && grp->format_grp_info);
/* Get HDF5-specific dim and group info. */
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* 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 (!dim->hdf_dimscaleid)
if (!hdf5_dim->hdf_dimscaleid)
{
hid_t spaceid, create_propid;
hsize_t dims[1], max_dims[1], chunk_dims[1] = {1};
@ -1791,8 +1849,8 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
/* Create the dataset that will be the dimension scale. */
LOG((4, "%s: about to H5Dcreate1 a dimscale dataset %s", __func__, dim->hdr.name));
if ((dim->hdf_dimscaleid = H5Dcreate1(grp->hdf_grpid, dim->hdr.name, H5T_IEEE_F32BE,
spaceid, create_propid)) < 0)
if ((hdf5_dim->hdf_dimscaleid = H5Dcreate1(hdf5_grp->hdf_grpid, dim->hdr.name, H5T_IEEE_F32BE,
spaceid, create_propid)) < 0)
BAIL(NC_EHDFERR);
/* Close the spaceid and create_propid. */
@ -1805,7 +1863,7 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
* 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)
if (H5DSset_scale(hdf5_dim->hdf_dimscaleid, dimscale_wo_var) < 0)
BAIL(NC_EHDFERR);
}
@ -1845,8 +1903,8 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
* 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->hdr.id)))
if (write_dimid && hdf5_dim->hdf_dimscaleid)
if ((retval = write_netcdf4_dimid(hdf5_dim->hdf_dimscaleid, dim->hdr.id)))
BAIL(retval);
return NC_NOERR;
@ -1957,7 +2015,8 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order)
int retval;
int i;
assert(grp && grp->hdr.name && grp->hdf_grpid);
assert(grp && grp->hdr.name &&
((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid);
LOG((3, "%s: grp->hdr.name %s, bad_coord_order %d", __func__, grp->hdr.name,
bad_coord_order));
@ -2033,22 +2092,26 @@ int
nc4_rec_write_groups_types(NC_GRP_INFO_T *grp)
{
NC_GRP_INFO_T *child_grp;
NC_HDF5_GRP_INFO_T *hdf5_grp;
NC_TYPE_INFO_T *type;
int retval;
int i;
assert(grp && grp->hdr.name);
assert(grp && grp->hdr.name && grp->format_grp_info);
LOG((3, "%s: grp->hdr.name %s", __func__, grp->hdr.name));
/* Get HDF5-specific group info. */
hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info;
/* Create the group in the HDF5 file if it doesn't exist. */
if (!grp->hdf_grpid)
if (!hdf5_grp->hdf_grpid)
if ((retval = create_group(grp)))
return retval;
/* If this is the root group of a file with strict NC3 rules, write
* an attribute. But don't leave the attribute open. */
if (!grp->parent && (grp->nc4_info->cmode & NC_CLASSIC_MODEL))
if ((retval = write_nc3_strict_att(grp->hdf_grpid)))
if ((retval = write_nc3_strict_att(hdf5_grp->hdf_grpid)))
return retval;
/* If there are any user-defined types, write them now. */
@ -2891,6 +2954,7 @@ nc4_convert_type(const void *src, void *dest, const nc_type src_type,
*
* @returns NC_NOERR No error.
* @returns NC_EHDFERR HDF5 returned an error.
* @returns NC_ENOMEM Out of memory.
* @author Ed Hartnett
*/
int
@ -2954,22 +3018,29 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
for (d = 0; d < var->ndims; d++)
{
nc_bool_t finished = NC_FALSE;
LOG((5, "%s: var %s has dimscale info...", __func__, var->hdr.name));
/* Look at all the dims in this group to see if they
* match. */
/* Check this and parent groups. */
for (g = grp; g && !finished; g = g->parent)
{
for(j=0;j<ncindexsize(g->dim);j++)
/* Check all dims in this group. */
for (j = 0; j < ncindexsize(g->dim); j++)
{
if((dim = (NC_DIM_INFO_T*)ncindexith(g->dim,j)) == NULL) continue;
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])
/* Get the HDF5 specific dim info. */
NC_HDF5_DIM_INFO_T *hdf5_dim;
dim = (NC_DIM_INFO_T *)ncindexith(g->dim, j);
assert(dim && dim->format_dim_info);
hdf5_dim = (NC_HDF5_DIM_INFO_T *)dim->format_dim_info;
/* Check for exact match of fileno/objid arrays
* to find identical objects in HDF5 file. */
if (var->dimscale_hdf5_objids[d].fileno[0] == hdf5_dim->hdf5_objid.fileno[0] &&
var->dimscale_hdf5_objids[d].objno[0] == hdf5_dim->hdf5_objid.objno[0] &&
var->dimscale_hdf5_objids[d].fileno[1] == hdf5_dim->hdf5_objid.fileno[1] &&
var->dimscale_hdf5_objids[d].objno[1] == hdf5_dim->hdf5_objid.objno[1])
{
LOG((4, "%s: for dimension %d, found dim %s",
__func__, d, dim->hdr.name));
LOG((4, "%s: for dimension %d, found dim %s", __func__,
d, dim->hdr.name));
var->dimids[d] = dim->hdr.id;
var->dim[d] = dim;
finished = NC_TRUE;
@ -2977,7 +3048,8 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
}
} /* next dim */
} /* next grp */
LOG((5, "%s: dimid for this dimscale is %d", __func__, var->type_info->hdr.id));
LOG((5, "%s: dimid for this dimscale is %d", __func__,
var->type_info->hdr.id));
} /* next var->dim */
}
/* No dimscales for this var! Invent phony dimensions. */
@ -3049,11 +3121,15 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
char phony_dim_name[NC_MAX_NAME + 1];
sprintf(phony_dim_name, "phony_dim_%d", grp->nc4_info->next_dimid);
LOG((3, "%s: creating phony dim for var %s", __func__, var->hdr.name));
if ((retval = nc4_dim_list_add(grp, phony_dim_name, h5dimlen[d], -1, &dim))) {
if ((retval = nc4_dim_list_add(grp, phony_dim_name, h5dimlen[d], -1, &dim)))
{
free(h5dimlenmax);
free(h5dimlen);
return retval;
}
/* Create struct for HDF5-specific dim info. */
if (!(dim->format_dim_info = calloc(1, sizeof(NC_HDF5_DIM_INFO_T))))
return NC_ENOMEM;
if (h5dimlenmax[d] == H5S_UNLIMITED)
dim->unlimited = NC_TRUE;
}
@ -3447,7 +3523,8 @@ NC4_isnetcdf4(struct NC_FILE_INFO* h5)
/* attribute did not exist */
/* => last resort: walk the HDF5 file looking for markers */
count = 0;
stat = NC4_walk(h5->root_grp->hdf_grpid, &count);
stat = NC4_walk(((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid,
&count);
if(stat != NC_NOERR)
isnc4 = 0;
else /* Threshold is at least two matches */
@ -3466,15 +3543,16 @@ done:
* @author Dennis Heimbigner.
*/
static int
NC4_get_strict_att(NC_FILE_INFO_T* h5)
NC4_get_strict_att(NC_FILE_INFO_T *h5)
{
hid_t grp = -1;
hid_t grpid = -1;
hid_t attid = -1;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
/* Get root group ID. */
grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
/* Try to extract the NC3_STRICT_ATT_NAME attribute */
attid = H5Aopen_name(grp, NC3_STRICT_ATT_NAME);
attid = H5Aopen_name(grpid, NC3_STRICT_ATT_NAME);
H5Aclose(attid);
return attid;
}

View File

@ -307,7 +307,7 @@ NC4_put_ncproperties(NC_FILE_INFO_T* file)
char* text = NULL;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
grp = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
/* See if the NCPROPS attribute exists */
if(H5Aexists(grp,NCPROPS) <= 0) { /* Does not exist */
ncstat = NC4_buildpropinfo(&h5->fileinfo->propattr,&text);
@ -514,7 +514,7 @@ NC4_read_ncproperties(NC_FILE_INFO_T* h5)
H5T_class_t t_class;
hsize_t size;
hdf5grpid = h5->root_grp->hdf_grpid;
hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
if(H5Aexists(hdf5grpid,NCPROPS) <= 0) { /* Does not exist */
/* File did not contain a _NCProperties attribute */
@ -578,7 +578,7 @@ NC4_write_ncproperties(NC_FILE_INFO_T* h5)
if (h5->no_write)
{retval = NC_EPERM; goto done;}
hdf5grpid = h5->root_grp->hdf_grpid;
hdf5grpid = ((NC_HDF5_GRP_INFO_T *)(h5->root_grp->format_grp_info))->hdf_grpid;
if(H5Aexists(hdf5grpid,NCPROPS) > 0) /* Already exists, no overwrite */
goto done;

View File

@ -92,12 +92,14 @@ nc4_check_name(const char *name, char *norm_name)
* @param mode The mode flag.
*
* @return ::NC_NOERR No error.
* @return ::NC_ENOMEM Out of memory.
* @author Ed Hartnett, Dennis Heimbigner
*/
int
nc4_nc4f_list_add(NC *nc, const char *path, int mode)
{
NC_FILE_INFO_T *h5;
int retval;
assert(nc && !NC4_DATA(nc) && path);
@ -123,7 +125,10 @@ nc4_nc4f_list_add(NC *nc, const char *path, int mode)
/* There's always at least one open group - the root
* group. Allocate space for one group's worth of information. Set
* its hdf id, name, and a pointer to it's file structure. */
return nc4_grp_list_add(h5, NULL, NC_GROUP_NAME, &h5->root_grp);
if ((retval = nc4_grp_list_add(h5, NULL, NC_GROUP_NAME, &h5->root_grp)))
return retval;
return NC_NOERR;
}
/**
@ -1143,6 +1148,11 @@ att_free(NC_ATT_INFO_T *att)
free(att->vldata);
}
/* Free any format-sepecific info. Some formats use this (ex. HDF5)
* and some don't (ex. HDF4). So it may be NULL. */
if (att->format_att_info)
free(att->format_att_info);
free(att);
return NC_NOERR;
}
@ -1272,6 +1282,10 @@ dim_free(NC_DIM_INFO_T *dim)
if (dim->hdr.name)
free(dim->hdr.name);
/* Release any format-specific information. */
if (dim->format_dim_info)
free(dim->format_dim_info);
free(dim);
return NC_NOERR;
}
@ -1349,6 +1363,10 @@ nc4_rec_grp_del(NC_GRP_INFO_T *grp)
/* Free the name. */
free(grp->hdr.name);
/* Release any format-specific information about this group. */
if (grp->format_grp_info)
free(grp->format_grp_info);
/* Free up this group */
free(grp);

View File

@ -242,10 +242,19 @@ varchunkspec_parse(int igrp, const char *spec0)
if(p == NULL)
{ret = NC_EINVAL; goto done;}
*p++ = '\0';
/* Lookup the variable by name */
ret = nc_inq_varid2(igrp, spec, &chunkspec->ivarid, &chunkspec->igrpid);
if(ret != NC_NOERR) goto done;
if(*p == '\0') {/* we have -c var: => do not chunk var */
chunkspec->omit = 1;
/* add the chunkspec to our list */
listpush(varchunkspecs,chunkspec);
chunkspec = NULL;
goto done;
}
/* Iterate over dimension sizes */
while(*p) {
unsigned long dimsize;

View File

@ -179,7 +179,8 @@ syntax: \fI var:n1,n2,...,nn \fP. This assumes that the variable named
variable is specified by the values of n1 through nn. This second
form of chunking specification can be repeated multiple times to specify
the exact chunking for different variables.
If the variable is specified but no chunk sizes are specified (i.e. \fI -d var: \fP)
If the variable is specified but no chunk sizes are specified
(i.e. \fI -c var: \fP)
then chunking is disabled for that variable.
If the same variable is specified
more than once, the second and later specifications are ignored.

View File

@ -11,6 +11,7 @@ T1=1
T2=1
T3=1
T4=1
T5=1
# For a netCDF-4 build, test nccopy chunking rules
@ -38,6 +39,16 @@ checkfvar() {
fi
}
# usage: checkivar <file>
checkivar() {
# Make sure that ivar was not chunked
C5IVAR=`sed -e '/ivar:_ChunkSizes/p' -e d <$1`
if test "x$C5IVAR" != x ; then
echo "***Fail: ivar was chunked"
exit 1
fi
}
# usage: verifychunkline line1 line2
verifychunkline() {
# trim leading whitespace
@ -53,12 +64,14 @@ verifychunkline() {
cleanup() {
rm -f tmp_nc5.nc tmp_nc5a.nc
rm -f tmp_nc5.cdl tmp_nc5a.cdl tmp_nc5b.cdl
rm -f tmp_nc5_omit.nc tmp_nc5_omit.cdl
}
# remove all created files
reset() {
cleanup
rm -fr tst_nc5.nc tst_nc5.cdl
rm -f tst_nc5_omit.nc tst_nc5_omit.cdl
}
reset
@ -159,6 +172,29 @@ checkfvar tmp_nc5.cdl
fi # T4
if test "x$T5" = x1 ; then
echo "*** Test nccopy -c fvar: to suppress chunking; classic ->enhanced"
reset
./tst_chunking tst_nc5_omit.nc
${NCDUMP} -n tst_nc5_omit tst_nc5_omit.nc > tst_nc5_omit.cdl
${NCCOPY} -c ivar:7,1,2,1,5,1,9 -c fvar: tst_nc5_omit.nc tmp_nc5_omit.nc
${NCDUMP} -n tst_nc5_omit tmp_nc5_omit.nc > tmp_nc5_omit.cdl
diff tst_nc5_omit.cdl tmp_nc5_omit.cdl
# Verify chunking of ivar
${NCDUMP} -hs -n tst_nc5_omit tmp_nc5_omit.nc > tmp_nc5_omit.cdl
# extract the chunking line
TESTLINE=`sed -e '/ivar:_ChunkSizes/p' -e d <tmp_nc5_omit.cdl`
# track line to match
BASELINE=' ivar:_ChunkSizes = 7, 1, 2, 1, 5, 1, 9 ; '
verifychunkline "$TESTLINE" "$BASELINE"
# Make sure that fvar was not chunked
checkfvar tmp_nc5_omit.cdl
fi # T5
# Cleanup all created files
reset