Skip to content

Commit

Permalink
Merge pull request #1026 from NetCDF-World-Domination-Council/ejh_laz…
Browse files Browse the repository at this point in the history
…y_atts_2

Lazy read of attributes
  • Loading branch information
WardF authored Jun 26, 2018
2 parents f9d2c77 + 0cc348b commit b9d8468
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 50 deletions.
7 changes: 4 additions & 3 deletions include/nc4internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,7 @@ typedef struct NC_VAR_INFO
nc_bool_t written_to; /* True if variable has data written to it */
struct NC_TYPE_INFO *type_info;
hid_t hdf_datasetid;
#if 0
int natts; /* Use explicit index because there may be gaps in numbers */
#endif
int atts_not_read; /* If true, the atts have not yet been read. */
NCindex* att; /* NCindex<NC_ATT_INFO_T*> */
nc_bool_t no_fill; /* True if no fill value is defined for var */
void *fill_value;
Expand Down Expand Up @@ -281,6 +279,7 @@ typedef struct NC_GRP_INFO
hid_t hdf_grpid;
struct NC_HDF5_FILE_INFO *nc4_info;
struct NC_GRP_INFO *parent;
int atts_not_read;
NCindex* children; /* NCindex<struct NC_GRP_INFO*> */
NCindex* dim; /* NCindex<NC_DIM_INFO_T> * */
NCindex* att; /* NCindex<NC_ATT_INFO_T> * */
Expand Down Expand Up @@ -370,6 +369,8 @@ int nc4_rec_write_groups_types(NC_GRP_INFO_T *grp);
int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5);
int nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
int nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T * var);
int nc4_read_grp_atts(NC_GRP_INFO_T *grp);
int nc4_read_var_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);

/* The following functions manipulate the in-memory linked list of
metadata, without using HDF calls. */
Expand Down
74 changes: 48 additions & 26 deletions libhdf5/hdf5attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,47 @@ int nc4typelen(nc_type type);
*
* @param grp Group
* @param varid Variable ID | NC_BLOGAL
* @param varp Pointer into which to return created NC_VAR_INFO_T instance
* @param varp Pointer that gets pointer to NC_VAR_INFO_T
* instance. Ignored if NULL.
* @param attlist Pointer that gets pointer to attribute list.
*
* @return Attribute list | NULL
* @author Dennis Heimbigner
* @return NC_NOERR No error.
* @author Dennis Heimbigner, Ed Hartnett
*/
static NCindex *
getattlist(NC_GRP_INFO_T *grp, int varid, NC_VAR_INFO_T **varp)
static int
getattlist(NC_GRP_INFO_T *grp, int varid, NC_VAR_INFO_T **varp,
NCindex **attlist)
{
if (varid == NC_GLOBAL) {
if(varp) *varp = NULL;
return grp->att;
} else {
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
if (!var) return NULL;
NC_VAR_INFO_T* var;
int retval;

if (varid == NC_GLOBAL)
{
/* Do we need to read the atts? */
if (grp->atts_not_read)
if ((retval = nc4_read_grp_atts(grp)))
return retval;

if (varp)
*varp = NULL;
*attlist = grp->att;
}
else
{
if (!(var = (NC_VAR_INFO_T *)ncindexith(grp->vars, varid)))
return NC_ENOTVAR;
assert(var->hdr.id == varid);
if(varp) *varp = var;
return var->att;

/* Do we need to read the atts? */
if (var->atts_not_read)
if ((retval = nc4_read_var_atts(grp, var)))
return retval;

if (varp)
*varp = var;
*attlist = var->att;
}
return NC_NOERR;
}

/**
Expand Down Expand Up @@ -92,11 +115,11 @@ NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
if ((retval = nc4_check_name(newname, norm_newname)))
return retval;

/* Is new name in use? */
list = getattlist(grp,varid,&var);
if(list == NULL)
return NC_ENOTVAR;
/* Get the list of attributes. */
if ((retval = getattlist(grp, varid, &var, &list)))
return retval;

/* Is new name in use? */
att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_newname);
if(att != NULL)
return NC_ENAMEINUSE;
Expand Down Expand Up @@ -175,9 +198,9 @@ NC4_del_att(int ncid, int varid, const char *name)
NC_ATT_INFO_T *att;
NCindex* attlist = NULL;
hid_t locid = 0, datasetid = 0;
int retval = NC_NOERR;
int i;
size_t deletedid;
int retval;

if (!name)
return NC_EINVAL;
Expand All @@ -204,11 +227,11 @@ NC4_del_att(int ncid, int varid, const char *name)
BAIL(retval);
}

/* Get either the global or a variable attribute list. Also figure
out the HDF5 location it's attached to. */
attlist = getattlist(grp,varid,&var);
if(attlist == NULL)
return NC_ENOTVAR;
/* Get either the global or a variable attribute list. */
if ((retval = getattlist(grp, varid, &var, &attlist)))
return retval;

/* Determine the location id in the HDF5 file. */
if (varid == NC_GLOBAL)
locid = grp->hdf_grpid;
else if (var->created)
Expand Down Expand Up @@ -297,9 +320,8 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,

/* Find att, if it exists. (Must check varid first or nc_test will
* break.) */
attlist = getattlist(grp,varid,&var);
if(attlist == NULL)
return NC_ENOTVAR;
if ((ret = getattlist(grp, varid, &var, &attlist)))
return ret;

/* The length needs to be positive (cast needed for braindead
systems with signed size_t). */
Expand Down
102 changes: 86 additions & 16 deletions libhdf5/hdf5file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,39 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
return retval;
}

/**
* @internal This function reads all the attributes of a variable.
*
* @param grp Pointer to the group info.
* @param var Pointer to the var info.
*
* @return NC_NOERR No error.
* @author Ed Hartnett
*/
int
nc4_read_var_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
{
att_iter_info att_info; /* Custom iteration information */

/* Check inputs. */
assert(grp && var);

/* Assign var and grp in struct. */
att_info.var = var;
att_info.grp = grp;

/* Now read all the attributes of this variable, ignoring the
ones that hold HDF5 dimension scale information. */
if ((H5Aiterate2(var->hdf_datasetid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL,
att_read_var_callbk, &att_info)) < 0)
return NC_EATTMETA;

/* Remember that we have read the atts for this var. */
var->atts_not_read = 0;

return NC_NOERR;
}

/**
* @internal This function is called by read_dataset(), (which is called
* by nc4_rec_read_metadata()) when a netCDF variable is found in the
Expand All @@ -1825,7 +1858,6 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
hid_t access_pid = 0;
int incr_id_rc = 0; /* Whether the dataset ID's ref count has been incremented */
int d;
att_iter_info att_info; /* Custom iteration information */
H5Z_filter_t filter;
int num_filters;
unsigned int cd_values_zip[CD_NELEMS_ZLIB];
Expand Down Expand Up @@ -2040,15 +2072,10 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
}
}

/* Now read all the attributes of this variable, ignoring the
ones that hold HDF5 dimension scale information. */

att_info.var = var;
att_info.grp = grp;

if ((H5Aiterate2(var->hdf_datasetid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL,
att_read_var_callbk, &att_info)) < 0)
BAIL(NC_EATTMETA);
/* Read variable attributes. */
var->atts_not_read = 1;
/* if ((retval = nc4_read_var_atts(grp, var))) */
/* BAIL(retval); */

/* Is this a deflated variable with a chunksize greater than the
* current cache size? */
Expand Down Expand Up @@ -2083,8 +2110,8 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
* @return ::NC_EHDFERR HDF5 returned error.
* @author Ed Hartnett
*/
static int
read_grp_atts(NC_GRP_INFO_T *grp)
int
nc4_read_grp_atts(NC_GRP_INFO_T *grp)
{
hid_t attid = -1;
hsize_t num_obj, i;
Expand Down Expand Up @@ -2138,6 +2165,9 @@ read_grp_atts(NC_GRP_INFO_T *grp)
attid = -1;
}

/* Remember that we have read the atts for this group. */
grp->atts_not_read = 0;

exit:
if (attid > 0) {
if(H5Aclose(attid) < 0)
Expand Down Expand Up @@ -2435,9 +2465,10 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
BAIL(NC_EHDFERR);
}

/* Scan the group for global (i.e. group-level) attributes. */
if ((retval = read_grp_atts(grp)))
BAIL(retval);
/* Defer the reading of global atts until someone asks for one. */
grp->atts_not_read = 1;
/* if ((retval = nc4_read_grp_atts(grp))) */
/* return retval; */

/* when exiting define mode, mark all variable written */
for (i=0; i<ncindexsize(grp->vars); i++) {
Expand Down Expand Up @@ -2465,6 +2496,33 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
return retval;
}

/**
* @internal Check for the attribute that indicates that netcdf
* classic model is in use.
*
* @param root_grp pointer to the group info for the root group of the
* file.
*
* @return NC_NOERR No error.
* @author Ed Hartnett
*/
static int
check_for_classic_model(NC_GRP_INFO_T *root_grp, int *is_classic)
{
htri_t attr_exists = -1;

/* Check inputs. */
assert(!root_grp->parent && is_classic);

/* 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)
return NC_EHDFERR;
*is_classic = attr_exists ? 1 : 0;

return NC_NOERR;
}

/**
* @internal Open a netcdf-4 file. Things have already been kicked off
* in ncfunc.c in nc_open, but here the netCDF-4 part of opening a
Expand All @@ -2484,7 +2542,8 @@ nc4_open_file(const char *path, int mode, void* parameters, NC *nc)
hid_t fapl_id = H5P_DEFAULT;
int retval;
unsigned flags;
NC_HDF5_FILE_INFO_T* nc4_info = NULL;
NC_HDF5_FILE_INFO_T *nc4_info = NULL;
int is_classic;

#ifdef USE_PARALLEL4
NC_MPI_INFO* mpiinfo = NULL;
Expand Down Expand Up @@ -2612,6 +2671,12 @@ nc4_open_file(const char *path, int mode, void* parameters, NC *nc)
if ((retval = nc4_rec_read_metadata(nc4_info->root_grp)))
BAIL(retval);

/* Check for classic model attribute. */
if ((retval = check_for_classic_model(nc4_info->root_grp, &is_classic)))
BAIL(retval);
if (is_classic)
nc4_info->cmode |= NC_CLASSIC_MODEL;

/* Now figure out which netCDF dims are indicated by the dimscale
* information. */
if ((retval = nc4_rec_match_dimscales(nc4_info->root_grp)))
Expand Down Expand Up @@ -3016,6 +3081,11 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
}
if (nattsp)
{
/* Do we need to read the atts? */
if (grp->atts_not_read)
if ((retval = nc4_read_grp_atts(grp)))
return retval;

*nattsp = ncindexcount(grp->att);
}

Expand Down
21 changes: 18 additions & 3 deletions libsrc4/nc4attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
NC_GRP_INFO_T *grp;
NC_HDF5_FILE_INFO_T *h5;
NC_ATT_INFO_T *att = NULL;
NC_VAR_INFO_T *var;
int my_attnum = -1;
int need_to_convert = 0;
int range_error = NC_NOERR;
Expand All @@ -136,9 +137,9 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
return retval;

/* Check varid */
if (varid != NC_GLOBAL) {
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
if(var == NULL)
if (varid != NC_GLOBAL)
{
if (!(var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid)))
return NC_ENOTVAR;
assert(var->hdr.id == varid);
}
Expand All @@ -150,6 +151,20 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
if ((retval = nc4_normalize_name(name, norm_name)))
BAIL(retval);

/* Read the atts for this group/var, if they have not been read. */
if (varid == NC_GLOBAL)
{
if (grp->atts_not_read)
if ((retval = nc4_read_grp_atts(grp)))
return retval;
}
else
{
if (var->atts_not_read)
if ((retval = nc4_read_var_atts(grp, var)))
return retval;
}

/* If this is one of the reserved atts, use nc_get_att_special. */
if (nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const NC_reservedatt* ra = NC_findreserved(norm_name);
Expand Down
14 changes: 14 additions & 0 deletions libsrc4/nc4internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,18 +460,32 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
{
NC_VAR_INFO_T *var;
NCindex* attlist = NULL;
int retval;

assert(grp && grp->hdr.name);
LOG((4, "nc4_find_grp_att: grp->name %s varid %d name %s attnum %d",
grp->hdr.name, varid, name, attnum));

/* Get either the global or a variable attribute list. */
if (varid == NC_GLOBAL)
{
attlist = grp->att;

/* Do we need to read the atts? */
if (grp->atts_not_read)
if ((retval = nc4_read_grp_atts(grp)))
return retval;
}
else
{
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
if (!var) return NC_ENOTVAR;

/* Do we need to read the var attributes? */
if (var->atts_not_read)
if ((retval = nc4_read_var_atts(grp, var)))
return retval;

attlist = var->att;
assert(var->hdr.id == varid);
}
Expand Down
Loading

0 comments on commit b9d8468

Please sign in to comment.