mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-01-24 16:04:40 +08:00
Merge branch 'nc4-var-array' of https://github.com/gsjaardema/netcdf-c into gh328
This commit is contained in:
commit
05ceb8d471
@ -146,7 +146,6 @@ typedef struct NC_ATT_INFO
|
||||
/* This is a struct to handle the var metadata. */
|
||||
typedef struct NC_VAR_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
char *hdf5_name; /* used if different from name */
|
||||
int ndims;
|
||||
@ -262,6 +261,12 @@ typedef struct NC_TYPE_INFO
|
||||
} u; /* Union of structs, for each type/class */
|
||||
} NC_TYPE_INFO_T;
|
||||
|
||||
typedef struct NC_VAR_ARRAY_T {
|
||||
size_t nalloc; /* number allocated >= nelems */
|
||||
size_t nelems; /* length of the array */
|
||||
NC_VAR_INFO_T **value;
|
||||
} NC_VAR_ARRAY_T;
|
||||
|
||||
/* This holds information for one group. Groups reproduce with
|
||||
* parthenogenesis. */
|
||||
typedef struct NC_GRP_INFO
|
||||
@ -273,7 +278,7 @@ typedef struct NC_GRP_INFO
|
||||
struct NC_HDF5_FILE_INFO *nc4_info;
|
||||
struct NC_GRP_INFO *parent;
|
||||
struct NC_GRP_INFO *children;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_VAR_ARRAY_T vars;
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_ATT_INFO_T *att;
|
||||
NC_TYPE_INFO_T *type;
|
||||
@ -385,8 +390,8 @@ int nc4_type_free(NC_TYPE_INFO_T *type);
|
||||
|
||||
/* These list functions add and delete vars, atts. */
|
||||
int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
|
||||
int nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var);
|
||||
int nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var);
|
||||
int nc4_var_add(NC_VAR_INFO_T **var);
|
||||
int nc4_var_del(NC_VAR_INFO_T *var);
|
||||
int nc4_dim_list_add(NC_DIM_INFO_T **list, NC_DIM_INFO_T **dim);
|
||||
int nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim);
|
||||
int nc4_att_list_add(NC_ATT_INFO_T **list, NC_ATT_INFO_T **att);
|
||||
|
@ -42,7 +42,6 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int i;
|
||||
int retval = NC_NOERR;
|
||||
const char** sp;
|
||||
|
||||
if (attnum) {
|
||||
my_attnum = *attnum;
|
||||
@ -261,14 +260,12 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
attlist = &grp->att;
|
||||
else
|
||||
{
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
{
|
||||
attlist = &var->att;
|
||||
break;
|
||||
}
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = &var->att;
|
||||
assert(var->varid == varid);
|
||||
}
|
||||
|
||||
for (att = *attlist; att; att = att->l.next)
|
||||
@ -364,7 +361,6 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
|
||||
* attribute). */
|
||||
if (!strcmp(att->name, _FillValue) && varid != NC_GLOBAL)
|
||||
{
|
||||
NC_ATT_INFO_T *varatt;
|
||||
int size;
|
||||
|
||||
/* Fill value must be same type and have exactly one value */
|
||||
@ -666,14 +662,12 @@ NC4_rename_att(int ncid, int varid, const char *name,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
{
|
||||
list = var->att;
|
||||
break;
|
||||
}
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
list = var->att;
|
||||
}
|
||||
for (att = list; att; att = att->l.next)
|
||||
if (!strncmp(att->name, norm_newname, NC_MAX_NAME))
|
||||
@ -777,16 +771,12 @@ NC4_del_att(int ncid, int varid, const char *name)
|
||||
}
|
||||
else
|
||||
{
|
||||
for(var = grp->var; var; var = var->l.next)
|
||||
{
|
||||
if (var->varid == varid)
|
||||
{
|
||||
attlist = &var->att;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = &var->att;
|
||||
assert(var->varid == varid);
|
||||
if (var->created)
|
||||
locid = var->hdf_datasetid;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ COPYRIGHT file for copying and redistribution conditions.
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
extern int nc4_vararray_add(NC_GRP_INFO_T *grp,
|
||||
NC_VAR_INFO_T *var);
|
||||
|
||||
/* must be after nc4internal.h */
|
||||
#include <H5DSpublic.h>
|
||||
#include <H5Fpublic.h>
|
||||
@ -506,7 +509,6 @@ NC4_create(const char* path, int cmode, size_t initialsz, int basepe,
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
MPI_Info info = MPI_INFO_NULL;
|
||||
int res;
|
||||
NC* nc;
|
||||
|
||||
assert(nc_file && path);
|
||||
|
||||
@ -1534,7 +1536,7 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
LOG((4, "%s: obj_name %s", __func__, obj_name));
|
||||
|
||||
/* Add a variable to the end of the group's var list. */
|
||||
if ((retval = nc4_var_list_add(&grp->var, &var)))
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Fill in what we already know. */
|
||||
@ -1810,6 +1812,8 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
} /* endif not HDF5 att */
|
||||
} /* next attribute */
|
||||
|
||||
nc4_vararray_add(grp, var);
|
||||
|
||||
/* Is this a deflated variable with a chunksize greater than the
|
||||
* current cache size? */
|
||||
if ((retval = nc4_adjust_var_cache(grp, var)))
|
||||
@ -1820,7 +1824,7 @@ exit:
|
||||
{
|
||||
if (incr_id_rc && H5Idec_ref(datasetid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
if (var && nc4_var_list_del(&grp->var, var))
|
||||
if (var && nc4_var_del(var))
|
||||
BAIL2(NC_EHDFERR);
|
||||
}
|
||||
if (access_pid && H5Pclose(access_pid) < 0)
|
||||
@ -2590,14 +2594,16 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
size_t var_type_size;
|
||||
int a;
|
||||
|
||||
/* Add a variable to the end of the group's var list. */
|
||||
if ((retval = nc4_var_list_add(&grp->var, &var)))
|
||||
/* Add a variable. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
return retval;
|
||||
|
||||
var->varid = grp->nvars++;
|
||||
var->created = NC_TRUE;
|
||||
var->written_to = NC_TRUE;
|
||||
|
||||
nc4_vararray_add(grp, var);
|
||||
|
||||
/* Open this dataset in HDF4 file. */
|
||||
if ((var->sdsid = SDselect(h5->sdid, v)) == FAIL)
|
||||
return NC_EVARMETA;
|
||||
@ -3205,7 +3211,6 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_ATT_INFO_T *att;
|
||||
NC_VAR_INFO_T *var;
|
||||
int retval;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
@ -3225,9 +3230,13 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
||||
}
|
||||
if (nvarsp)
|
||||
{
|
||||
int i;
|
||||
*nvarsp = 0;
|
||||
for (var = grp->var; var; var= var->l.next)
|
||||
(*nvarsp)++;
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
if (grp->vars.value[i])
|
||||
(*nvarsp)++;
|
||||
}
|
||||
}
|
||||
if (nattsp)
|
||||
{
|
||||
|
@ -392,6 +392,7 @@ NC4_inq_varids(int ncid, int *nvars, int *varids)
|
||||
NC_VAR_INFO_T *var;
|
||||
int v, num_vars = 0;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "nc_inq_varids: ncid 0x%x", ncid));
|
||||
|
||||
@ -413,14 +414,13 @@ NC4_inq_varids(int ncid, int *nvars, int *varids)
|
||||
{
|
||||
/* This is a netCDF-4 group. Round up them doggies and count
|
||||
* 'em. The list is in correct (i.e. creation) order. */
|
||||
if (grp->var)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
{
|
||||
if (varids)
|
||||
varids[num_vars] = var->varid;
|
||||
num_vars++;
|
||||
}
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (varids)
|
||||
varids[num_vars] = var->varid;
|
||||
num_vars++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
int d;
|
||||
int d, i;
|
||||
int retval;
|
||||
|
||||
assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0);
|
||||
@ -81,7 +81,10 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
return retval;
|
||||
|
||||
/* Find any vars that use this dimension id. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
if (var->dimids[d] == dimid && !var->dimscale)
|
||||
{
|
||||
@ -94,7 +97,7 @@ rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
var->dimscale_attached[d] = NC_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -109,7 +112,7 @@ rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
int d;
|
||||
int d, i;
|
||||
int retval;
|
||||
|
||||
assert(grp && grp->name && dimid >= 0 && dimscaleid >= 0);
|
||||
@ -121,7 +124,10 @@ rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
return retval;
|
||||
|
||||
/* Find any vars that use this dimension id. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
if (var->dimids[d] == dimid && !var->dimscale)
|
||||
{
|
||||
@ -135,7 +141,7 @@ rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid)
|
||||
var->dimscale_attached[d] = NC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -146,11 +152,11 @@ nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset)
|
||||
NC_VAR_INFO_T *var;
|
||||
|
||||
/* Find the requested varid. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* Open this dataset if necessary. */
|
||||
if (!var->hdf_datasetid)
|
||||
@ -867,7 +873,7 @@ int
|
||||
nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
|
||||
{
|
||||
NC_GRP_INFO_T *grp, *g;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_DIM_INFO_T *dim;
|
||||
@ -1520,13 +1526,11 @@ 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_GRP_INFO_T *g;
|
||||
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;
|
||||
void *fillp = NULL;
|
||||
NC_DIM_INFO_T *dim = NULL;
|
||||
int dims_found = 0;
|
||||
char *name_to_use;
|
||||
int retval = NC_NOERR;
|
||||
|
||||
@ -2054,13 +2058,14 @@ attach_dimscales(NC_GRP_INFO_T *grp)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_DIM_INFO_T *dim1;
|
||||
NC_GRP_INFO_T *g;
|
||||
int d;
|
||||
int d, i;
|
||||
int retval = NC_NOERR;
|
||||
|
||||
/* Attach dimension scales. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
/* Scales themselves do not attach. But I really wish they
|
||||
* would. */
|
||||
if (var->dimscale)
|
||||
@ -2355,6 +2360,7 @@ static int
|
||||
write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
|
||||
{
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
/* If there's no dimscale dataset for this dim, create one,
|
||||
* and mark that it should be hidden from netCDF as a
|
||||
@ -2433,20 +2439,23 @@ write_dim(NC_DIM_INFO_T *dim, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
|
||||
/* Did we extend an unlimited dimension? */
|
||||
if (dim->extended)
|
||||
{
|
||||
NC_VAR_INFO_T *v1;
|
||||
NC_VAR_INFO_T *v1 = NULL;
|
||||
|
||||
assert(dim->unlimited);
|
||||
/* If this is a dimension without a variable, then update
|
||||
* the secret length information at the end of the NAME
|
||||
* attribute. */
|
||||
for (v1 = grp->var; v1; v1 = v1->l.next)
|
||||
if (!strcmp(v1->name, dim->name))
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
if (grp->vars.value[i] && !strcmp(grp->vars.value[i]->name, dim->name))
|
||||
{
|
||||
v1 = grp->vars.value[i];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (v1)
|
||||
{
|
||||
hsize_t *new_size = NULL;
|
||||
NC_DIM_INFO_T *dim1;
|
||||
int d1;
|
||||
|
||||
/* Extend the dimension scale dataset to reflect the new
|
||||
@ -2493,10 +2502,13 @@ nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, nc_bool_t *bad_coord_
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
int last_dimid = -1;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
/* Iterate over variables in this group */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
/* Only matters for dimension scale variables, with non-scalar dimensionality */
|
||||
if (var->dimscale && var->ndims)
|
||||
{
|
||||
@ -2549,10 +2561,11 @@ nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, nc_bool_t *bad_coord_
|
||||
int
|
||||
nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order)
|
||||
{
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
NC_DIM_INFO_T *dim = NULL;
|
||||
NC_VAR_INFO_T *var = NULL;
|
||||
NC_GRP_INFO_T *child_grp = NULL;
|
||||
int coord_varid = -1;
|
||||
int var_index = 0;
|
||||
|
||||
int retval;
|
||||
assert(grp && grp->name && grp->hdf_grpid);
|
||||
@ -2564,7 +2577,8 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order)
|
||||
/* Set the pointers to the beginning of the list of dims & vars in this
|
||||
* group. */
|
||||
dim = grp->dim;
|
||||
var = grp->var;
|
||||
if (var_index < grp->vars.nelems)
|
||||
var = grp->vars.value[var_index];
|
||||
|
||||
/* Because of HDF5 ordering the dims and vars have to be stored in
|
||||
* this way to ensure that the dims and coordinate vars come out in
|
||||
@ -2591,12 +2605,16 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order)
|
||||
|
||||
/* Write each var. When we get to the coord var we are waiting
|
||||
* for (if any), then we break after writing it. */
|
||||
for (wrote_coord = NC_FALSE; var && !wrote_coord; var = var->l.next)
|
||||
for (wrote_coord = NC_FALSE; var && !wrote_coord; )
|
||||
{
|
||||
if ((retval = write_var(var, grp, bad_coord_order)))
|
||||
return retval;
|
||||
if (found_coord && var->varid == coord_varid)
|
||||
wrote_coord = NC_TRUE;
|
||||
if (++var_index < grp->vars.nelems)
|
||||
var = grp->vars.value[var_index];
|
||||
else
|
||||
var = NULL;
|
||||
}
|
||||
} /* end while */
|
||||
|
||||
@ -3630,7 +3648,8 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_DIM_INFO_T *dim;
|
||||
int retval = NC_NOERR;
|
||||
|
||||
int i;
|
||||
|
||||
assert(grp && grp->name);
|
||||
LOG((4, "%s: grp->name %s", __func__, grp->name));
|
||||
|
||||
@ -3641,8 +3660,10 @@ nc4_rec_match_dimscales(NC_GRP_INFO_T *grp)
|
||||
|
||||
/* Check all the vars in this group. If they have dimscale info,
|
||||
* try and find a dimension for them. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
/* Check all vars and see if dim[i] != NULL if dimids[i] valid. */
|
||||
int ndims = var->ndims;
|
||||
int d;
|
||||
@ -3976,7 +3997,6 @@ reportopenobjectsT(int log, hid_t fid, int ntypes, unsigned int* otypes)
|
||||
idlist = (hid_t*)malloc(sizeof(hid_t)*maxobjs);
|
||||
for(t=0;t<ntypes;t++) {
|
||||
unsigned int ot = otypes[t];
|
||||
if(ot < 0) break;
|
||||
ocount = H5Fget_obj_ids(fid,ot,maxobjs,idlist);
|
||||
for(i=0;i<ocount;i++) {
|
||||
hid_t o = idlist[i];
|
||||
@ -4063,11 +4083,8 @@ done:
|
||||
static int
|
||||
NC4_get_strict_att(NC_HDF5_FILE_INFO_T* h5)
|
||||
{
|
||||
int ncstat = NC_NOERR;
|
||||
size_t size;
|
||||
hid_t grp = -1;
|
||||
hid_t attid = -1;
|
||||
herr_t herr = 0;
|
||||
|
||||
/* Get root group */
|
||||
grp = h5->root_grp->hdf_grpid; /* get root group */
|
||||
|
@ -25,7 +25,6 @@ NC4_fileinfo_init(void)
|
||||
{
|
||||
int stat = NC_NOERR;
|
||||
unsigned major,minor,release;
|
||||
int super;
|
||||
|
||||
/* Build nc properties */
|
||||
memset((void*)&globalpropinfo,0,sizeof(globalpropinfo));
|
||||
@ -145,10 +144,7 @@ int
|
||||
NC4_put_propattr(NC_HDF5_FILE_INFO_T* h5)
|
||||
{
|
||||
int ncstat = NC_NOERR;
|
||||
H5T_class_t t_class;
|
||||
size_t size;
|
||||
hid_t grp = -1;
|
||||
hid_t exists = -1;
|
||||
hid_t attid = -1;
|
||||
hid_t aspace = -1;
|
||||
hid_t atype = -1;
|
||||
|
@ -121,11 +121,11 @@ find_var_dim_max_length(NC_GRP_INFO_T *grp, int varid, int dimid, size_t *maxlen
|
||||
*maxlen = 0;
|
||||
|
||||
/* Find this var. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* If the var hasn't been created yet, its size is 0. */
|
||||
if (!var->created)
|
||||
@ -331,11 +331,9 @@ nc4_find_g_var_nc(NC *nc, int ncid, int varid,
|
||||
return NC_ENOTVAR;
|
||||
|
||||
/* Find the var info. */
|
||||
for ((*var) = (*grp)->var; (*var); (*var) = (*var)->l.next)
|
||||
if ((*var)->varid == varid)
|
||||
break;
|
||||
if (!(*var))
|
||||
if (varid < 0 || varid >= (*grp)->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
(*var) = (*grp)->vars.value[varid];
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -375,13 +373,19 @@ nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim,
|
||||
int
|
||||
nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var)
|
||||
{
|
||||
int i;
|
||||
assert(grp && var && name);
|
||||
|
||||
/* Find the var info. */
|
||||
for ((*var) = grp->var; (*var); (*var) = (*var)->l.next)
|
||||
if (0 == strcmp(name, (*var)->name))
|
||||
break;
|
||||
|
||||
*var = NULL;
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
if (0 == strcmp(name, grp->vars.value[i]->name))
|
||||
{
|
||||
*var = grp->vars.value[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -498,6 +502,7 @@ nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len)
|
||||
NC_GRP_INFO_T *g;
|
||||
NC_VAR_INFO_T *var;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
assert(grp && len);
|
||||
LOG((3, "nc4_find_dim_len: grp->name %s dimid %d", grp->name, dimid));
|
||||
@ -510,9 +515,11 @@ nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len)
|
||||
|
||||
/* For all variables in this group, find the ones that use this
|
||||
* dimension, and remember the max length. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
size_t mylen;
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
|
||||
/* Find max length of dim in this variable... */
|
||||
if ((retval = find_var_dim_max_length(grp, var->varid, dimid, &mylen)))
|
||||
@ -541,16 +548,12 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
|
||||
attlist = grp->att;
|
||||
else
|
||||
{
|
||||
for(var = grp->var; var; var = var->l.next)
|
||||
{
|
||||
if (var->varid == varid)
|
||||
{
|
||||
attlist = var->att;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = var->att;
|
||||
assert(var->varid == varid);
|
||||
}
|
||||
|
||||
/* Now find the attribute by name or number. If a name is provided,
|
||||
@ -592,16 +595,12 @@ nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
|
||||
attlist = grp->att;
|
||||
else
|
||||
{
|
||||
for(var = grp->var; var; var = var->l.next)
|
||||
{
|
||||
if (var->varid == varid)
|
||||
{
|
||||
attlist = var->att;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = var->att;
|
||||
assert(var->varid == varid);
|
||||
}
|
||||
|
||||
/* Now find the attribute by name or number. If a name is provided, ignore the attnum. */
|
||||
@ -667,10 +666,9 @@ obj_list_del(NC_LIST_NODE_T **list, NC_LIST_NODE_T *obj)
|
||||
((NC_LIST_NODE_T *)obj->next)->prev = obj->prev;
|
||||
}
|
||||
|
||||
/* Add to the end of a var list. Return a pointer to the newly
|
||||
* added var. */
|
||||
/* Return a pointer to the new var. */
|
||||
int
|
||||
nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var)
|
||||
nc4_var_add(NC_VAR_INFO_T **var)
|
||||
{
|
||||
NC_VAR_INFO_T *new_var;
|
||||
|
||||
@ -683,9 +681,6 @@ nc4_var_list_add(NC_VAR_INFO_T **list, NC_VAR_INFO_T **var)
|
||||
new_var->chunk_cache_nelems = nc4_chunk_cache_nelems;
|
||||
new_var->chunk_cache_preemption = nc4_chunk_cache_preemption;
|
||||
|
||||
/* Add object to list */
|
||||
obj_list_add((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)new_var);
|
||||
|
||||
/* Set the var pointer, if one was given */
|
||||
if (var)
|
||||
*var = new_var;
|
||||
@ -777,6 +772,7 @@ nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name)
|
||||
NC_GRP_INFO_T *g;
|
||||
NC_VAR_INFO_T *var;
|
||||
uint32_t hash;
|
||||
int i;
|
||||
|
||||
/* Any types of this name? */
|
||||
for (type = grp->type; type; type = type->l.next)
|
||||
@ -790,10 +786,13 @@ nc4_check_dup_name(NC_GRP_INFO_T *grp, char *name)
|
||||
|
||||
/* Any variables of this name? */
|
||||
hash = hash_fast(name, strlen(name));
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (var->hash == hash && !strcmp(var->name, name))
|
||||
return NC_ENAMEINUSE;
|
||||
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -1002,9 +1001,9 @@ nc4_type_free(NC_TYPE_INFO_T *type)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/* Delete a var from a var list, and free the memory. */
|
||||
/* Delete a var, and free the memory. */
|
||||
int
|
||||
nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var)
|
||||
nc4_var_del(NC_VAR_INFO_T *var)
|
||||
{
|
||||
NC_ATT_INFO_T *a, *att;
|
||||
int ret;
|
||||
@ -1012,9 +1011,6 @@ nc4_var_list_del(NC_VAR_INFO_T **list, NC_VAR_INFO_T *var)
|
||||
if(var == NULL)
|
||||
return NC_NOERR;
|
||||
|
||||
/* Remove the var from the linked list. */
|
||||
obj_list_del((NC_LIST_NODE_T **)list, (NC_LIST_NODE_T *)var);
|
||||
|
||||
/* First delete all the attributes attached to this var. */
|
||||
att = var->att;
|
||||
while (att)
|
||||
@ -1126,11 +1122,12 @@ int
|
||||
nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp)
|
||||
{
|
||||
NC_GRP_INFO_T *g, *c;
|
||||
NC_VAR_INFO_T *v, *var;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_ATT_INFO_T *a, *att;
|
||||
NC_DIM_INFO_T *d, *dim;
|
||||
NC_TYPE_INFO_T *type, *t;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
assert(grp);
|
||||
LOG((3, "%s: grp->name %s", __func__, grp->name));
|
||||
@ -1159,18 +1156,29 @@ nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp)
|
||||
}
|
||||
|
||||
/* Delete all vars. */
|
||||
var = grp->var;
|
||||
while (var)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
|
||||
LOG((4, "%s: deleting var %s", __func__, var->name));
|
||||
/* Close HDF5 dataset associated with this var, unless it's a
|
||||
* scale. */
|
||||
if (var->hdf_datasetid && H5Dclose(var->hdf_datasetid) < 0)
|
||||
return NC_EHDFERR;
|
||||
v = var->l.next;
|
||||
if ((retval = nc4_var_list_del(&grp->var, var)))
|
||||
if ((retval = nc4_var_del(var)))
|
||||
return retval;
|
||||
var = v;
|
||||
grp->vars.value[i] = NULL;
|
||||
}
|
||||
|
||||
/* Vars are all freed above. When eliminate linked-list,
|
||||
then need to iterate value and free vars from it.
|
||||
*/
|
||||
if (grp->vars.nalloc != 0) {
|
||||
assert(grp->vars.value != NULL);
|
||||
free(grp->vars.value);
|
||||
grp->vars.value = NULL;
|
||||
grp->vars.nalloc = 0;
|
||||
}
|
||||
|
||||
/* Delete all dims. */
|
||||
@ -1459,7 +1467,7 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int tab_count)
|
||||
char tabs[MAX_NESTS] = "";
|
||||
char *dims_string = NULL;
|
||||
char temp_string[10];
|
||||
int t, retval, d;
|
||||
int t, retval, d, i;
|
||||
|
||||
/* Come up with a number of tabs relative to the group. */
|
||||
for (t = 0; t < tab_count && t < MAX_NESTS; t++)
|
||||
@ -1476,8 +1484,10 @@ rec_print_metadata(NC_GRP_INFO_T *grp, int tab_count)
|
||||
LOG((2, "%s DIMENSION - dimid: %d name: %s len: %d unlimited: %d",
|
||||
tabs, dim->dimid, dim->name, dim->len, dim->unlimited));
|
||||
|
||||
for(var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if(var->ndims > 0)
|
||||
{
|
||||
dims_string = (char*)malloc(sizeof(char)*(var->ndims*4));
|
||||
|
110
libsrc4/nc4var.c
110
libsrc4/nc4var.c
@ -94,11 +94,11 @@ NC4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* Set the values. */
|
||||
var->chunk_cache_size = size;
|
||||
@ -157,11 +157,11 @@ NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* Give the user what they want. */
|
||||
if (sizep)
|
||||
@ -340,6 +340,37 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
#define NC_ARRAY_GROWBY 4
|
||||
int nc4_vararray_add(NC_GRP_INFO_T *grp,
|
||||
NC_VAR_INFO_T *var)
|
||||
{
|
||||
NC_VAR_INFO_T **vp = NULL;
|
||||
|
||||
if (grp->vars.nalloc == 0) {
|
||||
assert(grp->vars.nelems == 0);
|
||||
vp = (NC_VAR_INFO_T **) malloc(NC_ARRAY_GROWBY * sizeof(NC_VAR_INFO_T *));
|
||||
if(vp == NULL)
|
||||
return NC_ENOMEM;
|
||||
grp->vars.value = vp;
|
||||
grp->vars.nalloc = NC_ARRAY_GROWBY;
|
||||
}
|
||||
else if(grp->vars.nelems +1 > grp->vars.nalloc) {
|
||||
vp = (NC_VAR_INFO_T **) realloc(grp->vars.value,
|
||||
(grp->vars.nalloc + NC_ARRAY_GROWBY) * sizeof(NC_VAR_INFO_T *));
|
||||
if(vp == NULL)
|
||||
return NC_ENOMEM;
|
||||
grp->vars.value = vp;
|
||||
grp->vars.nalloc += NC_ARRAY_GROWBY;
|
||||
}
|
||||
|
||||
if(var != NULL) {
|
||||
assert(var->varid == grp->vars.nelems);
|
||||
grp->vars.value[grp->vars.nelems] = var;
|
||||
grp->vars.nelems++;
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/* This is called when a new netCDF-4 variable is defined. Break it
|
||||
* down! */
|
||||
static int
|
||||
@ -413,8 +444,8 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add the var to the end of the list. */
|
||||
if ((retval = nc4_var_list_add(&grp->var, &var)))
|
||||
/* Add a new var. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Now fill in the values in the var info structure. */
|
||||
@ -426,6 +457,8 @@ nc_def_var_nc4(int ncid, const char *name, nc_type xtype,
|
||||
var->ndims = ndims;
|
||||
var->is_new_var = NC_TRUE;
|
||||
|
||||
nc4_vararray_add(grp, var);
|
||||
|
||||
/* If this is a user-defined type, there is a type_info struct with
|
||||
* all the type information. For atomic types, fake up a type_info
|
||||
* struct. */
|
||||
@ -671,13 +704,11 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
}
|
||||
|
||||
/* Find the var. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
|
||||
/* Oh no! Maybe we couldn't find it (*sob*)! */
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* Copy the data to the user's data buffers. */
|
||||
if (name)
|
||||
@ -821,13 +852,11 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
|
||||
/* Oh no! Maybe we couldn't find it (*sob*)! */
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
/* Can't turn on contiguous and deflate/fletcher32/szip. */
|
||||
if (contiguous)
|
||||
@ -1129,6 +1158,7 @@ NC4_inq_varid(int ncid, const char *name, int *varidp)
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
uint32_t nn_hash;
|
||||
int i;
|
||||
|
||||
if (!name)
|
||||
return NC_EINVAL;
|
||||
@ -1148,13 +1178,16 @@ NC4_inq_varid(int ncid, const char *name, int *varidp)
|
||||
nn_hash = hash_fast(norm_name, strlen(norm_name));
|
||||
|
||||
/* Find var of this name. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (nn_hash == var->hash && !(strcmp(var->name, norm_name)))
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
*varidp = var->varid;
|
||||
return NC_NOERR;
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (nn_hash == var->hash && !(strcmp(var->name, norm_name)))
|
||||
{
|
||||
*varidp = var->varid;
|
||||
return NC_NOERR;
|
||||
}
|
||||
}
|
||||
|
||||
return NC_ENOTVAR;
|
||||
}
|
||||
|
||||
@ -1171,6 +1204,7 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
NC_VAR_INFO_T *var, *tmp_var;
|
||||
uint32_t nn_hash;
|
||||
int retval = NC_NOERR;
|
||||
int i;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x varid %d name %s",
|
||||
__func__, ncid, varid, name));
|
||||
@ -1197,8 +1231,10 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
/* Check if name is in use, and retain a pointer to the correct variable */
|
||||
nn_hash = hash_fast(name, strlen(name));
|
||||
tmp_var = NULL;
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (nn_hash == var->hash && !strncmp(var->name, name, NC_MAX_NAME))
|
||||
return NC_ENAMEINUSE;
|
||||
if (var->varid == varid)
|
||||
@ -1293,11 +1329,11 @@ NC4_var_par_access(int ncid, int varid, int par_access)
|
||||
return NC_ENOPAR;
|
||||
|
||||
/* Find the var, and set its preference. */
|
||||
for (var = grp->var; var; var = var->l.next)
|
||||
if (var->varid == varid)
|
||||
break;
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
|
||||
if (par_access)
|
||||
var->parallel_access = NC_COLLECTIVE;
|
||||
|
Loading…
Reference in New Issue
Block a user