mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-02-23 16:59:54 +08:00
Merge pull request #1191 from Unidata/v4.6.2-release-branch.wif
V4.6.2 release branch.wif
This commit is contained in:
commit
8cb325c33c
@ -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
|
||||
|
||||
|
||||
|
33
configure.ac
33
configure.ac
@ -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],
|
||||
|
@ -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
|
||||
~~~~
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
196
libhdf5/nc4hdf.c
196
libhdf5/nc4hdf.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user