Skip to content

Commit c844e5b

Browse files
authored
Merge pull request #1081 from NetCDF-World-Domination-Council/ejh_global_att_read
Make global atts read much, much faster
2 parents 1fec7b4 + 4a16369 commit c844e5b

File tree

9 files changed

+208
-176
lines changed

9 files changed

+208
-176
lines changed

include/nc4internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,7 @@ int nc4_rec_write_groups_types(NC_GRP_INFO_T *grp);
334334
int nc4_enddef_netcdf4_file(NC_FILE_INFO_T *h5);
335335
int nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
336336
int nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T * var);
337-
int nc4_read_grp_atts(NC_GRP_INFO_T *grp);
338-
int nc4_read_var_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
337+
int nc4_read_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
339338

340339
/* The following functions manipulate the in-memory linked list of
341340
metadata, without using HDF calls. */

libhdf5/Makefile.am

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ libnchdf5_la_SOURCES = nc4hdf.c nc4info.c hdf5file.c hdf5attr.c \
1717
hdf5dim.c hdf5grp.c hdf5type.c hdf5internal.c hdf5create.c hdf5open.c \
1818
hdf5var.c nc4mem.c nc4memcb.c
1919

20-
2120
# Package this for cmake build.
2221
EXTRA_DIST = CMakeLists.txt
2322

libhdf5/hdf5attr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ getattlist(NC_GRP_INFO_T *grp, int varid, NC_VAR_INFO_T **varp,
3939
{
4040
/* Do we need to read the atts? */
4141
if (grp->atts_not_read)
42-
if ((retval = nc4_read_grp_atts(grp)))
42+
if ((retval = nc4_read_atts(grp, NULL)))
4343
return retval;
4444

4545
if (varp)
@@ -54,7 +54,7 @@ getattlist(NC_GRP_INFO_T *grp, int varid, NC_VAR_INFO_T **varp,
5454

5555
/* Do we need to read the atts? */
5656
if (var->atts_not_read)
57-
if ((retval = nc4_read_var_atts(grp, var)))
57+
if ((retval = nc4_read_atts(grp, var)))
5858
return retval;
5959

6060
if (varp)

libhdf5/hdf5file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
703703
{
704704
/* Do we need to read the atts? */
705705
if (grp->atts_not_read)
706-
if ((retval = nc4_read_grp_atts(grp)))
706+
if ((retval = nc4_read_atts(grp, NULL)))
707707
return retval;
708708

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

libhdf5/hdf5open.c

Lines changed: 69 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/**
55
* @file
66
* @internal This file contains functions that are used in file
7-
* opens, both fast and slow.
7+
* opens.
88
*
99
* @author Ed Hartnett
1010
*/
@@ -228,6 +228,7 @@ get_type_info2(NC_FILE_INFO_T *h5, hid_t datasetid,
228228

229229
return NC_EBADTYPID;
230230
}
231+
231232
/**
232233
* @internal This function reads the hacked in coordinates attribute I
233234
* use for multi-dimensional coordinates.
@@ -985,7 +986,8 @@ get_netcdf_type(NC_FILE_INFO_T *h5, hid_t native_typeid,
985986
}
986987

987988
/**
988-
* @internal Read an attribute. This is called by att_read_var_callbk().
989+
* @internal Read an attribute. This is called by
990+
* att_read_callbk().
989991
*
990992
* @param grp Pointer to group info struct.
991993
* @param attid Attribute ID.
@@ -1185,83 +1187,6 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
11851187
return retval;
11861188
}
11871189

1188-
/**
1189-
* @internal This function is called by nc4_rec_read_metadata to read
1190-
* all the group level attributes (the NC_GLOBAL atts for this
1191-
* group).
1192-
*
1193-
* @param grp Pointer to group info struct.
1194-
*
1195-
* @return ::NC_NOERR No error.
1196-
* @return ::NC_EHDFERR HDF5 returned error.
1197-
* @author Ed Hartnett
1198-
*/
1199-
int
1200-
nc4_read_grp_atts(NC_GRP_INFO_T *grp)
1201-
{
1202-
hid_t attid = -1;
1203-
hsize_t num_obj, i;
1204-
NC_ATT_INFO_T *att;
1205-
NC_TYPE_INFO_T *type;
1206-
char obj_name[NC_MAX_HDF5_NAME + 1];
1207-
int retval = NC_NOERR;
1208-
int hidden = 0;
1209-
1210-
num_obj = H5Aget_num_attrs(grp->hdf_grpid);
1211-
for (i = 0; i < num_obj; i++)
1212-
{
1213-
if ((attid = H5Aopen_idx(grp->hdf_grpid, (unsigned int)i)) < 0)
1214-
BAIL(NC_EATTMETA);
1215-
if (H5Aget_name(attid, NC_MAX_NAME + 1, obj_name) < 0)
1216-
BAIL(NC_EATTMETA);
1217-
LOG((3, "reading attribute of _netCDF group, named %s", obj_name));
1218-
1219-
/* See if this a hidden, global attribute */
1220-
hidden = 0; /* default */
1221-
if(grp->nc4_info->root_grp == grp) {
1222-
const NC_reservedatt* ra = NC_findreserved(obj_name);
1223-
if(ra != NULL && (ra->flags & NAMEONLYFLAG))
1224-
hidden = 1;
1225-
}
1226-
1227-
/* This may be an attribute telling us that strict netcdf-3
1228-
* rules are in effect. If so, we will make note of the fact,
1229-
* but not add this attribute to the metadata. It's not a user
1230-
* attribute, but an internal netcdf-4 one. */
1231-
if(strcmp(obj_name, NC3_STRICT_ATT_NAME)==0)
1232-
grp->nc4_info->cmode |= NC_CLASSIC_MODEL;
1233-
else if(!hidden) {
1234-
/* Add an att struct at the end of the list, and then go to it. */
1235-
if ((retval = nc4_att_list_add(grp->att, obj_name, &att)))
1236-
BAIL(retval);
1237-
retval = read_hdf5_att(grp, attid, att);
1238-
if(retval == NC_EBADTYPID) {
1239-
if((retval = nc4_att_list_del(grp->att, att)))
1240-
BAIL(retval);
1241-
} else if(retval) {
1242-
BAIL(retval);
1243-
} else {
1244-
att->created = NC_TRUE;
1245-
if ((retval = nc4_find_type(grp->nc4_info, att->nc_typeid, &type)))
1246-
BAIL(retval);
1247-
}
1248-
}
1249-
/* Unconditionally close the open attribute */
1250-
(void)H5Aclose(attid);
1251-
attid = -1;
1252-
}
1253-
1254-
/* Remember that we have read the atts for this group. */
1255-
grp->atts_not_read = 0;
1256-
1257-
exit:
1258-
if (attid > 0) {
1259-
if(H5Aclose(attid) < 0)
1260-
BAIL2(NC_EHDFERR);
1261-
}
1262-
return retval;
1263-
}
1264-
12651190
/**
12661191
* @internal Wrap HDF5 allocated memory free operations
12671192
*
@@ -1587,41 +1512,57 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
15871512
}
15881513

15891514
/**
1590-
* @internal Callback function for reading attributes. This is used by
1591-
* read_var().
1515+
* @internal Callback function for reading attributes. This is used
1516+
* for both global and variable attributes.
15921517
*
15931518
* @param loc_id HDF5 attribute ID.
15941519
* @param att_name Name of the attrigute.
15951520
* @param ainfo HDF5 info struct for attribute.
1596-
* @param att_data The attribute data.
1521+
* @param att_data Pointer to an att_iter_info struct, which contains
1522+
* pointers to the NC_GRP_INFO_T and (for variable attributes) the
1523+
* NC_VAR_INFO_T. For global atts the var pointer is NULL.
15971524
*
1598-
* @return ::NC_NOERR No error.
1599-
* @return ::NC_EHDFERR HDF5 returned error.
1600-
* @return ::NC_ENOMEM Out of memory.
1601-
* @return ::NC_EATTMETA HDF5 can't open attribute.
1602-
* @return ::NC_EBADTYPID Can't read attribute type.
1525+
* @return ::NC_NOERR No error. Iteration continues.
1526+
* @return ::-1 Error. Stop iteration.
1527+
* @author Ed Hartnett
16031528
*/
16041529
static herr_t
1605-
att_read_var_callbk(hid_t loc_id, const char *att_name,
1606-
const H5A_info_t *ainfo, void *att_data)
1530+
att_read_callbk(hid_t loc_id, const char *att_name, const H5A_info_t *ainfo,
1531+
void *att_data)
16071532
{
16081533

16091534
hid_t attid = 0;
1610-
int retval = NC_NOERR;
16111535
NC_ATT_INFO_T *att;
1536+
NCindex *list;
16121537
att_iter_info *att_info = (att_iter_info *)att_data;
1538+
int retval = NC_NOERR;
1539+
1540+
/* Determin what list is being added to. */
1541+
list = att_info->var ? att_info->var->att : att_info->grp->att;
1542+
1543+
/* This may be an attribute telling us that strict netcdf-3 rules
1544+
* are in effect. If so, we will make note of the fact, but not add
1545+
* this attribute to the metadata. It's not a user attribute, but
1546+
* an internal netcdf-4 one. */
1547+
if (!strcmp(att_name, NC3_STRICT_ATT_NAME))
1548+
{
1549+
/* Only relevant for groups, not vars. */
1550+
if (!att_info->var)
1551+
att_info->grp->nc4_info->cmode |= NC_CLASSIC_MODEL;
1552+
return NC_NOERR;
1553+
}
16131554

16141555
/* Should we ignore this attribute? */
1615-
const NC_reservedatt* ra = NC_findreserved(att_name);
1616-
if(ra != NULL) goto exit; /* ignore */
1556+
if (NC_findreserved(att_name))
1557+
return NC_NOERR;
16171558

16181559
/* Add to the end of the list of atts for this var. */
1619-
if ((retval = nc4_att_list_add(att_info->var->att, att_name, &att)))
1620-
BAIL(retval);
1560+
if ((retval = nc4_att_list_add(list, att_name, &att)))
1561+
BAIL(-1);
16211562

16221563
/* Open the att by name. */
16231564
if ((attid = H5Aopen(loc_id, att_name, H5P_DEFAULT)) < 0)
1624-
BAIL(NC_EATTMETA);
1565+
BAIL(-1);
16251566
LOG((4, "%s:: att_name %s", __func__, att_name));
16261567

16271568
/* Read the rest of the info about the att,
@@ -1632,54 +1573,62 @@ att_read_var_callbk(hid_t loc_id, const char *att_name,
16321573
if (att)
16331574
att->created = NC_TRUE;
16341575

1635-
if (attid > 0 && H5Aclose(attid) < 0)
1636-
BAIL2(NC_EHDFERR);
1637-
1638-
return NC_NOERR;
1639-
16401576
exit:
1641-
if(retval) {
1642-
if (retval == NC_EBADTYPID) {
1643-
/* NC_EBADTYPID will be normally converted to NC_NOERR so that
1644-
the parent iterator does not fail. */
1645-
retval = nc4_att_list_del(att_info->var->att,att);
1646-
att = NULL;
1647-
}
1577+
if (retval == NC_EBADTYPID)
1578+
{
1579+
/* NC_EBADTYPID will be normally converted to NC_NOERR so that
1580+
the parent iterator does not fail. */
1581+
retval = nc4_att_list_del(list, att);
1582+
att = NULL;
16481583
}
16491584
if (attid > 0 && H5Aclose(attid) < 0)
1650-
retval = NC_EHDFERR;
1585+
retval = -1;
1586+
1587+
/* Since this is a HDF5 iterator callback, return -1 for any error
1588+
* to stop iteration. */
1589+
if (retval)
1590+
retval = -1;
16511591
return retval;
16521592
}
16531593

16541594
/**
1655-
* @internal This function reads all the attributes of a variable.
1595+
* @internal This function reads all the attributes of a variable or
1596+
* the global attributes of a group.
16561597
*
16571598
* @param grp Pointer to the group info.
1658-
* @param var Pointer to the var info.
1599+
* @param var Pointer to the var info. NULL for global att reads.
16591600
*
1660-
* @return NC_NOERR No error.
1601+
* @return ::NC_NOERR No error.
1602+
* @return ::NC_EATTMETA Some error occured reading attributes.
16611603
* @author Ed Hartnett
16621604
*/
16631605
int
1664-
nc4_read_var_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
1606+
nc4_read_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
16651607
{
16661608
att_iter_info att_info; /* Custom iteration information */
1609+
hid_t locid; /* HDF5 location to read atts from. */
16671610

16681611
/* Check inputs. */
1669-
assert(grp && var);
1612+
assert(grp);
16701613

1671-
/* Assign var and grp in struct. */
1614+
/* Assign var and grp in struct. (var may be NULL). */
16721615
att_info.var = var;
16731616
att_info.grp = grp;
16741617

1675-
/* Now read all the attributes of this variable, ignoring the
1676-
ones that hold HDF5 dimension scale information. */
1677-
if ((H5Aiterate2(var->hdf_datasetid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL,
1678-
att_read_var_callbk, &att_info)) < 0)
1618+
/* Determine where to read from in the HDF5 file. */
1619+
locid = var ? var->hdf_datasetid : grp->hdf_grpid;
1620+
1621+
/* Now read all the attributes at this location, ignoring special
1622+
* netCDF hidden attributes. */
1623+
if ((H5Aiterate2(locid, H5_INDEX_CRT_ORDER, H5_ITER_INC, NULL,
1624+
att_read_callbk, &att_info)) < 0)
16791625
return NC_EATTMETA;
16801626

1681-
/* Remember that we have read the atts for this var. */
1682-
var->atts_not_read = 0;
1627+
/* Remember that we have read the atts for this var or group. */
1628+
if (var)
1629+
var->atts_not_read = 0;
1630+
else
1631+
grp->atts_not_read = 0;
16831632

16841633
return NC_NOERR;
16851634
}

libsrc4/nc4attr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
156156
if (varid == NC_GLOBAL)
157157
{
158158
if (grp->atts_not_read)
159-
if ((retval = nc4_read_grp_atts(grp)))
159+
if ((retval = nc4_read_atts(grp, NULL)))
160160
return retval;
161161
}
162162
else
163163
{
164164
if (var->atts_not_read)
165-
if ((retval = nc4_read_var_atts(grp, var)))
165+
if ((retval = nc4_read_atts(grp, var)))
166166
return retval;
167167
}
168168

libsrc4/nc4internal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
473473

474474
/* Do we need to read the atts? */
475475
if (grp->atts_not_read)
476-
if ((retval = nc4_read_grp_atts(grp)))
476+
if ((retval = nc4_read_atts(grp, NULL)))
477477
return retval;
478478
}
479479
else
@@ -483,7 +483,7 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
483483

484484
/* Do we need to read the var attributes? */
485485
if (var->atts_not_read)
486-
if ((retval = nc4_read_var_atts(grp, var)))
486+
if ((retval = nc4_read_atts(grp, var)))
487487
return retval;
488488

489489
attlist = var->att;

libsrc4/nc4var.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
261261
{
262262
/* Do we need to read the atts? */
263263
if (grp->atts_not_read)
264-
if ((retval = nc4_read_grp_atts(grp)))
264+
if ((retval = nc4_read_atts(grp, NULL)))
265265
return retval;
266266

267267
*nattsp = ncindexcount(grp->att);
@@ -288,7 +288,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
288288
if (nattsp)
289289
{
290290
if (var->atts_not_read)
291-
if ((retval = nc4_read_var_atts(grp, var)))
291+
if ((retval = nc4_read_atts(grp, var)))
292292
return retval;
293293
*nattsp = ncindexcount(var->att);
294294
}

0 commit comments

Comments
 (0)