mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
Merged latest trunk changes into my branch.
This commit is contained in:
commit
4b3ea48bbd
@ -5,6 +5,9 @@ VERSION COMMENTS
|
||||
------- --------
|
||||
4.1.2-beta2 2010-08-08
|
||||
|
||||
Refactor of HDF5 file metadata scan for large speedup
|
||||
in opening files, especially large files.
|
||||
|
||||
Complete rewrite of the handling of character datalist
|
||||
constants. The heuristics are documented in ncgen.1.
|
||||
|
||||
|
@ -17,7 +17,7 @@ AC_REVISION([$Id: configure.ac,v 1.450 2010/05/28 19:42:47 dmh Exp $])
|
||||
AC_PREREQ([2.59])
|
||||
|
||||
# Initialize with name, version, and support email address.
|
||||
AC_INIT([netCDF], [4.1.2-beta1], [support-netcdf@unidata.ucar.edu])
|
||||
AC_INIT([netCDF], [4.1.2-beta2], [support-netcdf@unidata.ucar.edu])
|
||||
|
||||
# Create the VERSION file, which contains the package version from
|
||||
# AC_INIT.
|
||||
|
@ -40,17 +40,17 @@ if BUILD_V2
|
||||
LDADD += ${top_builddir}/libdispatch/libnetcdf2.la
|
||||
endif
|
||||
|
||||
NC4_TESTS = tst_h_files tst_h_files2 tst_h_atts tst_h_atts3 tst_h_vars \
|
||||
tst_h_vars2 tst_h_vars3 tst_h_grps tst_h_compounds tst_h_compounds2 \
|
||||
tst_h_wrt_cmp tst_h_rd_cmp tst_h_vl tst_h_opaques tst_h_strings \
|
||||
tst_h_strings1 tst_h_dimscales tst_h_dimscales1 tst_h_dimscales2 \
|
||||
tst_h_dimscales3 tst_h_enums tst_dims tst_dims2 tst_dims3 tst_files \
|
||||
tst_files4 tst_vars tst_varms tst_unlim_vars tst_converts \
|
||||
tst_converts2 tst_grps tst_compounds tst_compounds2 tst_compounds3 \
|
||||
tst_opaques tst_strings tst_interops tst_interops4 tst_interops5 \
|
||||
tst_interops6 tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3 \
|
||||
tst_chunks tst_utf8 tst_fills tst_fillbug tst_xplatform tst_xplatform2 \
|
||||
tst_h_atts2 tst_endian_fill
|
||||
NC4_TESTS = tst_h_files tst_h_files2 tst_h_files4 tst_h_atts \
|
||||
tst_h_atts3 tst_h_vars tst_h_vars2 tst_h_vars3 tst_h_grps \
|
||||
tst_h_compounds tst_h_compounds2 tst_h_wrt_cmp tst_h_rd_cmp tst_h_vl \
|
||||
tst_h_opaques tst_h_strings tst_h_strings1 tst_h_dimscales \
|
||||
tst_h_dimscales1 tst_h_dimscales2 tst_h_dimscales3 tst_h_enums \
|
||||
tst_dims tst_dims2 tst_dims3 tst_files tst_files4 tst_vars tst_varms \
|
||||
tst_unlim_vars tst_converts tst_converts2 tst_grps tst_compounds \
|
||||
tst_compounds2 tst_compounds3 tst_opaques tst_strings tst_interops \
|
||||
tst_interops4 tst_interops5 tst_interops6 tst_enums tst_coords \
|
||||
tst_coords2 tst_coords3 tst_vars3 tst_chunks tst_utf8 tst_fills \
|
||||
tst_fillbug tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill
|
||||
|
||||
check_PROGRAMS = $(NC4_TESTS)
|
||||
if LARGE_FILE_TESTS
|
||||
|
@ -1680,53 +1680,145 @@ read_dataset(NC_GRP_INFO_T *grp, char *obj_name)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Given index, get the HDF5 name of an object. This function will try
|
||||
* to use creation ordering, but if that fails (which causes a HDF5
|
||||
* error message to be printed) then it will use default
|
||||
/* Given index, get the HDF5 name of an object and the class of the
|
||||
* object (group, type, dataset, etc.). This function will try to use
|
||||
* creation ordering, but if that fails it will use default
|
||||
* (i.e. alphabetical) ordering. (This is necessary to read existing
|
||||
* HDF5 archives without creation ordering). */
|
||||
static int
|
||||
get_name_by_idx(NC_HDF5_FILE_INFO_T *h5, hid_t hdf_grpid, int i,
|
||||
int *obj_class, char *obj_name)
|
||||
{
|
||||
H5O_info_t obj_info;
|
||||
H5_index_t idx_field = H5_INDEX_CRT_ORDER;
|
||||
ssize_t size;
|
||||
herr_t res;
|
||||
/* static int */
|
||||
/* get_name_by_idx(NC_HDF5_FILE_INFO_T *h5, hid_t hdf_grpid, int i, */
|
||||
/* int *obj_class, char *obj_name) */
|
||||
/* { */
|
||||
/* H5O_info_t obj_info; */
|
||||
/* H5_index_t idx_field = H5_INDEX_CRT_ORDER; */
|
||||
/* ssize_t size; */
|
||||
/* herr_t res; */
|
||||
|
||||
/* These HDF5 macros prevent an HDF5 error message when a
|
||||
* non-creation-ordered HDF5 file is opened. */
|
||||
H5E_BEGIN_TRY {
|
||||
res = H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,
|
||||
i, &obj_info, H5P_DEFAULT);
|
||||
} H5E_END_TRY;
|
||||
/* /\* These HDF5 macros prevent an HDF5 error message when a */
|
||||
/* * non-creation-ordered HDF5 file is opened. *\/ */
|
||||
/* H5E_BEGIN_TRY { */
|
||||
/* res = H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, */
|
||||
/* i, &obj_info, H5P_DEFAULT); */
|
||||
/* } H5E_END_TRY; */
|
||||
|
||||
/* Creation ordering not available, so make sure this file is
|
||||
* opened for read-only access. This is a plain old HDF5 file being
|
||||
* read by netCDF-4. */
|
||||
if (res < 0)
|
||||
/* /\* Creation ordering not available, so make sure this file is */
|
||||
/* * opened for read-only access. This is a plain old HDF5 file being */
|
||||
/* * read by netCDF-4. *\/ */
|
||||
/* if (res < 0) */
|
||||
/* { */
|
||||
/* if (H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_NAME, H5_ITER_INC, */
|
||||
/* i, &obj_info, H5P_DEFAULT) < 0) */
|
||||
/* return NC_EHDFERR; */
|
||||
/* if (!h5->no_write) */
|
||||
/* return NC_ECANTWRITE; */
|
||||
/* h5->ignore_creationorder = 1; */
|
||||
/* idx_field = H5_INDEX_NAME; */
|
||||
/* } */
|
||||
|
||||
/* *obj_class = obj_info.type; */
|
||||
/* if ((size = H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i, */
|
||||
/* NULL, 0, H5P_DEFAULT)) < 0) */
|
||||
/* return NC_EHDFERR; */
|
||||
/* if (size > NC_MAX_NAME) */
|
||||
/* return NC_EMAXNAME; */
|
||||
/* if (H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i, */
|
||||
/* obj_name, size+1, H5P_DEFAULT) < 0) */
|
||||
/* return NC_EHDFERR; */
|
||||
|
||||
/* LOG((4, "get_name_by_idx: encountered HDF5 object obj_name %s", obj_name)); */
|
||||
|
||||
/* return NC_NOERR; */
|
||||
/* } */
|
||||
|
||||
/* This struct is used to pass information back from the callback
|
||||
* function used with H5Literate. */
|
||||
struct nc_hdf5_link_info
|
||||
{
|
||||
char name[NC_MAX_NAME + 1];
|
||||
H5I_type_t obj_type;
|
||||
};
|
||||
|
||||
/* This is a callback function for H5Literate().
|
||||
|
||||
The parameters of this callback function have the following values or
|
||||
meanings:
|
||||
|
||||
g_id Group that serves as root of the iteration; same value as the
|
||||
H5Lvisit group_id parameter
|
||||
|
||||
name Name of link, relative to g_id, being examined at current step of
|
||||
the iteration
|
||||
|
||||
info H5L_info_t struct containing information regarding that link
|
||||
|
||||
op_data User-defined pointer to data required by the application in
|
||||
processing the link; a pass-through of the op_data pointer provided
|
||||
with the H5Lvisit function call
|
||||
|
||||
*/
|
||||
static herr_t
|
||||
visit_link(hid_t g_id, const char *name, const H5L_info_t *info,
|
||||
void *op_data)
|
||||
{
|
||||
/* A positive return value causes the visit iterator to immediately
|
||||
* return that positive value, indicating short-circuit
|
||||
* success. The iterator can be restarted at the next group
|
||||
* member. */
|
||||
int ret = 1;
|
||||
hid_t id;
|
||||
|
||||
/* Get the name, truncating at NC_MAX_NAME. */
|
||||
strncpy(((struct nc_hdf5_link_info *)op_data)->name, name,
|
||||
NC_MAX_NAME);
|
||||
|
||||
/* Open this critter. */
|
||||
if ((id = H5Oopen_by_addr(g_id, info->u.address)) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Is this critter a group, type, data, attribute, or what? */
|
||||
if ((((struct nc_hdf5_link_info *)op_data)->obj_type = H5Iget_type(id)) < 0)
|
||||
ret = NC_EHDFERR;
|
||||
|
||||
/* Close the critter to release resouces. */
|
||||
if (H5Oclose(id) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Iterate over one link in the group at a time, returning
|
||||
* link_info. The creation_ordering and idx pointers keep track of
|
||||
* whether creation ordering works and the most recently examined
|
||||
* link. */
|
||||
static int
|
||||
nc4_iterate_link(int *ordering_checked, int *creation_ordering,
|
||||
hid_t grpid, hsize_t *idx, struct nc_hdf5_link_info *link_info)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (*creation_ordering)
|
||||
{
|
||||
if (H5Oget_info_by_idx(hdf_grpid, ".", H5_INDEX_NAME, H5_ITER_INC,
|
||||
i, &obj_info, H5P_DEFAULT) < 0)
|
||||
return NC_EHDFERR;
|
||||
if (!h5->no_write)
|
||||
return NC_ECANTWRITE;
|
||||
h5->ignore_creationorder = 1;
|
||||
idx_field = H5_INDEX_NAME;
|
||||
/* These HDF5 macros prevent an HDF5 error message when a
|
||||
* non-creation-ordered HDF5 file is opened. */
|
||||
H5E_BEGIN_TRY {
|
||||
res = H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC,
|
||||
idx, visit_link, (void *)link_info);
|
||||
if (res < 0 && *ordering_checked)
|
||||
return NC_EHDFERR;
|
||||
} H5E_END_TRY;
|
||||
}
|
||||
|
||||
*obj_class = obj_info.type;
|
||||
if ((size = H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i,
|
||||
NULL, 0, H5P_DEFAULT)) < 0)
|
||||
return NC_EHDFERR;
|
||||
if (size > NC_MAX_NAME)
|
||||
return NC_EMAXNAME;
|
||||
if (H5Lget_name_by_idx(hdf_grpid, ".", idx_field, H5_ITER_INC, i,
|
||||
obj_name, size+1, H5P_DEFAULT) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
LOG((4, "get_name_by_idx: encountered HDF5 object obj_name %s", obj_name));
|
||||
|
||||
if (!*creation_ordering || res < 0)
|
||||
{
|
||||
if (H5Literate(grpid, H5_INDEX_NAME, H5_ITER_INC, idx,
|
||||
visit_link, link_info) != 1)
|
||||
return NC_EHDFERR;
|
||||
/* If it didn't work with creation ordering, but did without,
|
||||
* then we don't have creation ordering. */
|
||||
*creation_ordering = 0;
|
||||
}
|
||||
|
||||
*ordering_checked = 1;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -1735,10 +1827,12 @@ int
|
||||
nc4_rec_read_types(NC_GRP_INFO_T *grp)
|
||||
{
|
||||
hsize_t num_obj, i;
|
||||
int obj_class;
|
||||
char obj_name[NC_MAX_HDF5_NAME + 1];
|
||||
NC_HDF5_FILE_INFO_T *h5 = grp->file->nc4_info;
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
hsize_t idx = 0;
|
||||
struct nc_hdf5_link_info link_info;
|
||||
int ordering_checked = 0;
|
||||
int creation_ordering = 1; /* Assume we have it. */
|
||||
int retval = NC_NOERR;
|
||||
|
||||
assert(grp && grp->name);
|
||||
@ -1770,23 +1864,28 @@ nc4_rec_read_types(NC_GRP_INFO_T *grp)
|
||||
/* For each object in the group... */
|
||||
for (i = 0; i < num_obj; i++)
|
||||
{
|
||||
if ((retval = get_name_by_idx(h5, grp->hdf_grpid, i, &obj_class, obj_name)))
|
||||
if ((retval = nc4_iterate_link(&ordering_checked, &creation_ordering,
|
||||
grp->hdf_grpid, &idx, &link_info)))
|
||||
return retval;
|
||||
|
||||
/* Without creation ordering, file must be read-only. */
|
||||
if (!i && !creation_ordering && !h5->no_write)
|
||||
return NC_ECANTWRITE;
|
||||
|
||||
/* Deal with groups and types; ignore the rest. */
|
||||
if (obj_class == H5O_TYPE_GROUP)
|
||||
if (link_info.obj_type == H5I_GROUP)
|
||||
{
|
||||
LOG((3, "found group %s", obj_name));
|
||||
LOG((3, "found group %s", link_info.name));
|
||||
if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++,
|
||||
grp, grp->file, obj_name, &child_grp)))
|
||||
grp, grp->file, link_info.name, &child_grp)))
|
||||
return retval;
|
||||
if ((retval = nc4_rec_read_types(child_grp)))
|
||||
return retval;
|
||||
}
|
||||
else if (obj_class == H5O_TYPE_NAMED_DATATYPE)
|
||||
else if (link_info.obj_type == H5I_DATATYPE)
|
||||
{
|
||||
LOG((3, "found datatype %s", obj_name));
|
||||
if ((retval = read_type(grp, obj_name)))
|
||||
LOG((3, "found datatype %s", link_info.name));
|
||||
if ((retval = read_type(grp, link_info.name)))
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@ -1801,10 +1900,11 @@ int
|
||||
nc4_rec_read_vars(NC_GRP_INFO_T *grp)
|
||||
{
|
||||
hsize_t num_obj, i;
|
||||
int obj_class;
|
||||
char obj_name[NC_MAX_HDF5_NAME + 1];
|
||||
NC_HDF5_FILE_INFO_T *h5 = grp->file->nc4_info;
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
struct nc_hdf5_link_info link_info;
|
||||
hsize_t idx = 0;
|
||||
int ordering_checked = 0;
|
||||
int creation_ordering = 1; /* Assume we have it. */
|
||||
int retval = NC_NOERR;
|
||||
|
||||
assert(grp && grp->name && grp->hdf_grpid > 0);
|
||||
@ -1817,18 +1917,19 @@ nc4_rec_read_vars(NC_GRP_INFO_T *grp)
|
||||
/* For each object in the group... */
|
||||
for (i = 0; i < num_obj; i++)
|
||||
{
|
||||
if ((retval = get_name_by_idx(h5, grp->hdf_grpid, i, &obj_class, obj_name)))
|
||||
if ((retval = nc4_iterate_link(&ordering_checked, &creation_ordering,
|
||||
grp->hdf_grpid, &idx, &link_info)))
|
||||
return retval;
|
||||
|
||||
|
||||
/* Deal with datasets. */
|
||||
switch(obj_class)
|
||||
switch(link_info.obj_type)
|
||||
{
|
||||
case H5O_TYPE_GROUP:
|
||||
LOG((3, "re-encountering group %s", obj_name));
|
||||
case H5I_GROUP:
|
||||
LOG((3, "re-encountering group %s", link_info.name));
|
||||
|
||||
/* The NC_GROUP_INFO_T for this group already exists. Find it. */
|
||||
for (child_grp = grp->children; child_grp; child_grp = child_grp->next)
|
||||
if (!strcmp(child_grp->name, obj_name))
|
||||
if (!strcmp(child_grp->name, link_info.name))
|
||||
break;
|
||||
if (!child_grp)
|
||||
return NC_EHDFERR;
|
||||
@ -1837,25 +1938,20 @@ nc4_rec_read_vars(NC_GRP_INFO_T *grp)
|
||||
if ((retval = nc4_rec_read_vars(child_grp)))
|
||||
return retval;
|
||||
break;
|
||||
case H5O_TYPE_DATASET:
|
||||
LOG((3, "found dataset %s", obj_name));
|
||||
case H5I_DATASET:
|
||||
LOG((3, "found dataset %s", link_info.name));
|
||||
|
||||
/* Learn all about this dataset, which may be a dimscale
|
||||
* (i.e. dimension metadata), or real data. */
|
||||
if ((retval = read_dataset(grp, obj_name)))
|
||||
if ((retval = read_dataset(grp, link_info.name)))
|
||||
return retval;
|
||||
break;
|
||||
case H5O_TYPE_NAMED_DATATYPE:
|
||||
LOG((3, "already handled type %s", obj_name));
|
||||
break;
|
||||
case H5G_LINK:
|
||||
/* Since I don't know what to do with linkes, I'll just
|
||||
* ignore them. */
|
||||
LOG((3, "This is a link object. Have a nice day."));
|
||||
case H5I_DATATYPE:
|
||||
LOG((3, "already handled type %s", link_info.name));
|
||||
break;
|
||||
default:
|
||||
LOG((0, "Unknown object class %d in nc4_rec_read_vars!",
|
||||
obj_class));
|
||||
link_info.obj_type));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1929,9 +2025,6 @@ nc4_open_file(const char *path, int mode, MPI_Comm comm,
|
||||
nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption));
|
||||
#endif /* USE_PARALLEL */
|
||||
|
||||
/*if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
|
||||
BAIL(NC_EHDFERR);*/
|
||||
|
||||
/* The NetCDF-3.x prototype contains an mode option NC_SHARE for
|
||||
multiple processes accessing the dataset concurrently. As there
|
||||
is no HDF5 equivalent, NC_SHARE is treated as NC_NOWRITE. */
|
||||
@ -2698,16 +2791,9 @@ NC4_close(int ncid)
|
||||
nc4_file_list_del(nc);
|
||||
}
|
||||
|
||||
/* Reset the ncid numbers if there are no more files open. */
|
||||
if(count_NCList() == 0)
|
||||
{
|
||||
/* If all files have been closed, close he HDF5 library. This will
|
||||
* clean up some stuff that HDF5 is leaving open. */
|
||||
/* if ((retval = H5close()) < 0)
|
||||
return NC_EHDFERR;*/
|
||||
|
||||
/* Reset the ncid numbers. */
|
||||
nc4_file_list_free();
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp)
|
||||
|
||||
/* If we can't find it, the grp id part of ncid is bad. */
|
||||
if (!(*grp = nc4_rec_find_grp(f->nc4_info->root_grp, (ncid & GRP_ID_MASK))))
|
||||
return NC_EBADGRPID;
|
||||
return NC_EBADID;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_HDF5_FILE_INFO_T **h5)
|
||||
assert(f->nc4_info->root_grp);
|
||||
/* If we can't find it, the grp id part of ncid is bad. */
|
||||
if (!(*grp = nc4_rec_find_grp(f->nc4_info->root_grp, (ncid & GRP_ID_MASK))))
|
||||
return NC_EBADGRPID;
|
||||
return NC_EBADID;
|
||||
*h5 = (*grp)->file->nc4_info;
|
||||
assert(*h5);
|
||||
} else {
|
||||
@ -264,7 +264,7 @@ nc4_find_nc_grp_h5(int ncid, NC_FILE_INFO_T **nc, NC_GRP_INFO_T **grp,
|
||||
assert(f->nc4_info->root_grp);
|
||||
/* If we can't find it, the grp id part of ncid is bad. */
|
||||
if (!(*grp = nc4_rec_find_grp(f->nc4_info->root_grp, (ncid & GRP_ID_MASK))))
|
||||
return NC_EBADGRPID;
|
||||
return NC_EBADID;
|
||||
|
||||
*h5 = (*grp)->file->nc4_info;
|
||||
assert(*h5);
|
||||
|
@ -924,12 +924,13 @@ nc_inq_var_chunking_ints(int ncid, int varid, int *contiguousp, int *chunksizesp
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Copy to size_t array. */
|
||||
for (i = 0; i < var->ndims; i++)
|
||||
{
|
||||
chunksizesp[i] = cs[i];
|
||||
if (cs[i] > NC_MAX_INT)
|
||||
retval = NC_ERANGE;
|
||||
}
|
||||
if (*contiguousp == NC_CHUNKED)
|
||||
for (i = 0; i < var->ndims; i++)
|
||||
{
|
||||
chunksizesp[i] = cs[i];
|
||||
if (cs[i] > NC_MAX_INT)
|
||||
retval = NC_ERANGE;
|
||||
}
|
||||
|
||||
if (var->ndims)
|
||||
free(cs);
|
||||
|
@ -223,61 +223,6 @@ main()
|
||||
ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
printf("*** Creating HDF5 file in the canonical netCDF-4 way...");
|
||||
{
|
||||
hid_t fapl_id, fcpl_id, fileid, grpid, fileid2;
|
||||
hsize_t num_obj;
|
||||
|
||||
/* Create file access and create property lists. */
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
|
||||
|
||||
/* Set latest_format in access propertly list. This ensures that
|
||||
* the latest, greatest, HDF5 versions are used in the file. */
|
||||
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;
|
||||
|
||||
/* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
|
||||
* turns on HDF5 creation ordering in the file. */
|
||||
if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
||||
H5P_CRT_ORDER_INDEXED)) < 0) ERR;
|
||||
if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
||||
H5P_CRT_ORDER_INDEXED)) < 0) ERR;
|
||||
|
||||
/* Set close degree. */
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
|
||||
/* Create the file. */
|
||||
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;
|
||||
|
||||
/* Open the root group. */
|
||||
if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
/* Close up. */
|
||||
if (H5Pclose(fapl_id) < 0 ||
|
||||
H5Pclose(fcpl_id) < 0 ||
|
||||
H5Gclose(grpid) < 0 ||
|
||||
H5Fclose(fileid) < 0)
|
||||
ERR;
|
||||
|
||||
/* Reopen the file and check it. */
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
|
||||
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, fapl_id)) < 0) ERR;
|
||||
if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
|
||||
if (num_obj) ERR;
|
||||
|
||||
/* Open another copy of the same file. Must use the same file
|
||||
* access degree or HDF5 will not open the file. */
|
||||
if ((fileid2 = H5Fopen(FILE_NAME, H5F_ACC_RDWR, fapl_id)) < 0) ERR;
|
||||
|
||||
if (H5Fclose(fileid) < 0) ERR;
|
||||
if (H5Fclose(fileid2) < 0) ERR;
|
||||
if (H5Pclose(fapl_id) < 0) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
#ifdef LARGE_FILE_TESTS
|
||||
|
||||
#define NDIMS2 2
|
||||
|
204
libsrc4/tst_h_files4.c
Normal file
204
libsrc4/tst_h_files4.c
Normal file
@ -0,0 +1,204 @@
|
||||
/* This is part of the netCDF package.
|
||||
Copyright 2005 University Corporation for Atmospheric Research/Unidata
|
||||
See COPYRIGHT file for conditions of use.
|
||||
|
||||
Test HDF5 file code. These are not intended to be exhaustive tests,
|
||||
but they use HDF5 the same way that netCDF-4 does, so if these
|
||||
tests don't work, than netCDF-4 won't work either.
|
||||
|
||||
$Id$
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <nc_tests.h>
|
||||
#include "netcdf.h"
|
||||
#include <nc4internal.h>
|
||||
#include <H5DSpublic.h>
|
||||
|
||||
#define FILE_NAME "tst_h_files4.h5"
|
||||
/* Heavy duty test file...*/
|
||||
/*#define FILE_NAME "/machine/downloads/T159_1978110112.nc4"*/
|
||||
|
||||
herr_t
|
||||
obj_iter(hid_t o_id, const char *name, const H5O_info_t *object_info,
|
||||
void *op_data)
|
||||
{
|
||||
*(int *)op_data = object_info->type;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is a callback function for H5Literate().
|
||||
|
||||
The parameters of this callback function have the following values or
|
||||
meanings:
|
||||
|
||||
g_id Group that serves as root of the iteration; same value as the
|
||||
H5Lvisit group_id parameter
|
||||
|
||||
name Name of link, relative to g_id, being examined at current step of
|
||||
the iteration
|
||||
|
||||
info H5L_info_t struct containing information regarding that link
|
||||
|
||||
op_data User-defined pointer to data required by the application in
|
||||
processing the link; a pass-through of the op_data pointer provided
|
||||
with the H5Lvisit function call
|
||||
|
||||
*/
|
||||
herr_t
|
||||
op_func (hid_t g_id, const char *name, const H5L_info_t *info,
|
||||
void *op_data)
|
||||
{
|
||||
hid_t id;
|
||||
H5I_type_t obj_type;
|
||||
|
||||
strcpy((char *)op_data, name);
|
||||
if ((id = H5Oopen_by_addr(g_id, info->u.address)) < 0) ERR;
|
||||
|
||||
/* Using H5Ovisit is really slow. Use H5Iget_type for a fast
|
||||
* answer. */
|
||||
/* if (H5Ovisit(id, H5_INDEX_CRT_ORDER, H5_ITER_INC, obj_iter, */
|
||||
/* (void *)&obj_class) != 1) ERR; */
|
||||
|
||||
if ((obj_type = H5Iget_type(id)) < 0) ERR;
|
||||
if (H5Oclose(id) < 0) ERR;
|
||||
|
||||
/* Turn this on to learn what type of object you've opened. */
|
||||
/* switch (obj_type) */
|
||||
/* { */
|
||||
/* case H5I_GROUP: */
|
||||
/* printf("group %s\n", name); */
|
||||
/* break; */
|
||||
/* case H5I_DATATYPE: */
|
||||
/* printf("type %s\n", name); */
|
||||
/* break; */
|
||||
/* case H5I_DATASET: */
|
||||
/* printf("data %s\n", name); */
|
||||
/* break; */
|
||||
/* default: */
|
||||
/* printf("unknown class\n"); */
|
||||
/* } */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
printf("\n*** Checking HDF5 file functions.\n");
|
||||
printf("*** Creating HDF5 file in the canonical netCDF-4 way...");
|
||||
{
|
||||
hid_t fapl_id, fcpl_id, fileid, grpid, fileid2;
|
||||
hsize_t num_obj;
|
||||
|
||||
/* Create file access and create property lists. */
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
|
||||
|
||||
/* Set latest_format in access propertly list. This ensures that
|
||||
* the latest, greatest, HDF5 versions are used in the file. */
|
||||
/* if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST,
|
||||
H5F_LIBVER_LATEST) < 0) ERR;*/
|
||||
|
||||
/* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
|
||||
* turns on HDF5 creation ordering in the file. */
|
||||
if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
||||
H5P_CRT_ORDER_INDEXED)) < 0) ERR;
|
||||
if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
||||
H5P_CRT_ORDER_INDEXED)) < 0) ERR;
|
||||
|
||||
/* Set close degree. */
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
|
||||
/* Create the file. */
|
||||
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;
|
||||
|
||||
/* Open the root group. */
|
||||
if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
/* Close up. */
|
||||
if (H5Pclose(fapl_id) < 0 ||
|
||||
H5Pclose(fcpl_id) < 0 ||
|
||||
H5Gclose(grpid) < 0 ||
|
||||
H5Fclose(fileid) < 0)
|
||||
ERR;
|
||||
|
||||
/* Reopen the file and check it. */
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
|
||||
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, fapl_id)) < 0) ERR;
|
||||
if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
|
||||
if (num_obj) ERR;
|
||||
|
||||
/* Open another copy of the same file. Must use the same file
|
||||
* access degree or HDF5 will not open the file. */
|
||||
if ((fileid2 = H5Fopen(FILE_NAME, H5F_ACC_RDWR, fapl_id)) < 0) ERR;
|
||||
|
||||
if (H5Fclose(fileid) < 0) ERR;
|
||||
if (H5Fclose(fileid2) < 0) ERR;
|
||||
if (H5Pclose(fapl_id) < 0) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
printf("*** Opening a HDF5 file with H5Literate...");
|
||||
{
|
||||
hid_t fapl_id, fileid, grpid;
|
||||
hsize_t idx = 0;
|
||||
char obj_name[NC_MAX_NAME + 1];
|
||||
hsize_t num_obj;
|
||||
int i;
|
||||
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
if (H5Pset_cache(fapl_id, 0, CHUNK_CACHE_NELEMS, CHUNK_CACHE_SIZE,
|
||||
CHUNK_CACHE_PREEMPTION) < 0) ERR;
|
||||
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, fapl_id)) < 0) ERR;
|
||||
if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
||||
for (i = 0; i < num_obj; i++)
|
||||
{
|
||||
if (H5Literate(grpid, H5_INDEX_CRT_ORDER, H5_ITER_INC, &idx, op_func,
|
||||
(void *)obj_name) != 1) ERR;
|
||||
printf("encountered object %s\n", obj_name);
|
||||
}
|
||||
|
||||
if (H5Gclose(grpid) < 0) ERR;
|
||||
if (H5Fclose(fileid) < 0) ERR;
|
||||
if (H5Pclose(fapl_id) < 0) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
printf("*** Opening a HDF5 file in the canonical netCDF-4 way...");
|
||||
{
|
||||
hid_t fapl_id, fileid, grpid;
|
||||
H5_index_t idx_field = H5_INDEX_CRT_ORDER;
|
||||
H5O_info_t obj_info;
|
||||
hsize_t num_obj;
|
||||
ssize_t size;
|
||||
char obj_name[NC_MAX_NAME + 1];
|
||||
int i;
|
||||
|
||||
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
|
||||
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
|
||||
if (H5Pset_cache(fapl_id, 0, CHUNK_CACHE_NELEMS, CHUNK_CACHE_SIZE,
|
||||
CHUNK_CACHE_PREEMPTION) < 0) ERR;
|
||||
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, fapl_id)) < 0) ERR;
|
||||
if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
/* How many objects in this group? */
|
||||
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
||||
for (i = 0; i < num_obj; i++)
|
||||
{
|
||||
if (H5Oget_info_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,
|
||||
i, &obj_info, H5P_DEFAULT)) ERR;
|
||||
if ((size = H5Lget_name_by_idx(grpid, ".", idx_field, H5_ITER_INC, i,
|
||||
NULL, 0, H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Lget_name_by_idx(grpid, ".", idx_field, H5_ITER_INC, i,
|
||||
obj_name, size+1, H5P_DEFAULT) < 0) ERR;
|
||||
}
|
||||
|
||||
if (H5Gclose(grpid) < 0) ERR;
|
||||
if (H5Fclose(fileid) < 0) ERR;
|
||||
if (H5Pclose(fapl_id) < 0) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
FINAL_RESULTS;
|
||||
}
|
@ -200,6 +200,7 @@ main()
|
||||
dims[0] = DIM1_LEN;
|
||||
if ((propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
|
||||
if (H5Pset_layout(propid, H5D_CHUNKED)) ERR;
|
||||
if (H5Pset_chunk(propid, 1, dims)) ERR;
|
||||
if (H5Pset_deflate(propid, DEFLATE_LEVEL)) ERR;
|
||||
if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
|
||||
if ((datasetid = H5Dcreate(grpid, VAR_BOOL_NAME, H5T_NATIVE_HBOOL,
|
||||
@ -258,6 +259,7 @@ main()
|
||||
dims[0] = DIM1_LEN;
|
||||
if ((propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
|
||||
if (H5Pset_layout(propid, H5D_CHUNKED)) ERR;
|
||||
if (H5Pset_chunk(propid, 1, dims)) ERR;
|
||||
if (H5Pset_shuffle(propid)) ERR;
|
||||
if (H5Pset_deflate(propid, DEFLATE_LEVEL)) ERR;
|
||||
if (H5Pset_fletcher32(propid)) ERR;
|
||||
|
@ -80,21 +80,21 @@ program f90tst_vars_vlen
|
||||
! if (retval .ne. nf_noerr) call handle_err(retval)
|
||||
! if (num_types .ne. max_types) stop 2
|
||||
|
||||
! ! Use nf_inq_user_type to confirm this is an vlen type, with base
|
||||
! ! size 4, base type NF_INT.
|
||||
! ! Use nf_inq_user_type to confirm this is an vlen type, with vlen
|
||||
! ! size 16, base type NF_INT.
|
||||
! retval = nf_inq_user_type(ncid, typeids(1), type_name, type_size, &
|
||||
! base_type, nfields, class)
|
||||
! if (retval .ne. nf_noerr) call handle_err(retval)
|
||||
! if (type_name(1:len(vlen_type_name)) .ne. vlen_type_name .or. &
|
||||
! type_size .ne. 4 .or. base_type .ne. nf_int .or. &
|
||||
! nfields .ne. 0 .or. class .ne. nf_vlen) stop 2
|
||||
! type_size .ne. 16 .or. base_type .ne. nf_int .or. &
|
||||
! nfields .ne. 0 .or. class .ne. nf_vlen) stop 3
|
||||
|
||||
! ! Use nf_inq_vlen and make sure we get the same answers as we did
|
||||
! ! with nf_inq_user_type.
|
||||
! retval = nf_inq_vlen(ncid, typeids(1), type_name, base_size, base_type)
|
||||
! if (retval .ne. nf_noerr) call handle_err(retval)
|
||||
! if (type_name(1:len(vlen_type_name)) .ne. vlen_type_name .or. &
|
||||
! base_type .ne. nf_int .or. base_size .ne. 4) stop 2
|
||||
! base_type .ne. nf_int .or. base_size .ne. 16) stop 4
|
||||
|
||||
! ! Read the vlen attribute.
|
||||
! retval = nf_get_att(ncid, NF_GLOBAL, 'att1', vlen_in)
|
||||
@ -104,29 +104,29 @@ program f90tst_vars_vlen
|
||||
! retval = nf_get_vlen_element(ncid, vlen_typeid, vlen_in, &
|
||||
! vlen_len_in, data1_in)
|
||||
! if (retval .ne. nf_noerr) call handle_err(retval)
|
||||
! if (vlen_len_in .ne. vlen_len) stop 2
|
||||
! if (vlen_len_in .ne. vlen_len) stop 5
|
||||
|
||||
! ! Check the data
|
||||
! do x = 1, vlen_len
|
||||
! if (data1(x) .ne. data1_in(x)) stop 2
|
||||
! if (data1(x) .ne. data1_in(x)) stop 6
|
||||
! end do
|
||||
|
||||
! ! Close the file.
|
||||
! retval = nf_close(ncid)
|
||||
! if (retval .ne. nf_noerr) call handle_err(retval)
|
||||
|
||||
print *,'*** SUCCESS!'
|
||||
contains
|
||||
! This subroutine handles errors by printing an error message and
|
||||
! exiting with a non-zero status.
|
||||
subroutine handle_err(errcode)
|
||||
use netcdf
|
||||
implicit none
|
||||
integer, intent(in) :: errcode
|
||||
! print *,'*** SUCCESS!'
|
||||
! contains
|
||||
! ! This subroutine handles errors by printing an error message and
|
||||
! ! exiting with a non-zero status.
|
||||
! subroutine handle_err(errcode)
|
||||
! use netcdf
|
||||
! implicit none
|
||||
! integer, intent(in) :: errcode
|
||||
|
||||
if(errcode /= nf90_noerr) then
|
||||
print *, 'Error: ', trim(nf90_strerror(errcode))
|
||||
stop 2
|
||||
endif
|
||||
end subroutine handle_err
|
||||
! if(errcode /= nf90_noerr) then
|
||||
! print *, 'Error: ', trim(nf90_strerror(errcode))
|
||||
! stop 1
|
||||
! endif
|
||||
! end subroutine handle_err
|
||||
end program f90tst_vars_vlen
|
||||
|
1
oc/dap.y
1
oc/dap.y
@ -115,6 +115,7 @@ array_decls:
|
||||
array_decl:
|
||||
'[' SCAN_WORD ']' {$$=dap_arraydecl(parsestate,null,$2);}
|
||||
| '[' name '=' SCAN_WORD ']' {$$=dap_arraydecl(parsestate,$2,$4);}
|
||||
| '[' '=' SCAN_WORD ']' {$$=dap_arraydecl(parsestate,null,$3);}
|
||||
| error
|
||||
{daperror(parsestate,"Illegal dimension declaration"); YYABORT;}
|
||||
;
|
||||
|
@ -22,11 +22,12 @@
|
||||
|
||||
/* Note: TMPPATH must end in '/' */
|
||||
#ifdef __CYGWIN__
|
||||
/*#define TMPPATH "c:/temp/"*/
|
||||
#define TMPPATH1 "c:/temp/"
|
||||
#define TMPPATH2 "./"
|
||||
#else
|
||||
/*#define TMPPATH "/tmp/"*/
|
||||
#define TMPPATH1 "/tmp/"
|
||||
#define TMPPATH2 "./"
|
||||
#endif
|
||||
#define TMPPATH "./"
|
||||
|
||||
/* Define default rc files */
|
||||
#define DODSRC ".dodsrc"
|
||||
@ -36,6 +37,7 @@ static int ocextractdds(OCstate*,OCtree*);
|
||||
static char* constraintescape(const char* url);
|
||||
#ifdef OC_DISK_STORAGE
|
||||
static OCerror createtempfile(OCstate*,OCtree*);
|
||||
static int createtempfile1(char*,char*);
|
||||
#endif
|
||||
|
||||
static void ocsetcurlproperties(OCstate*);
|
||||
@ -455,12 +457,36 @@ ocextractdds(OCstate* state, OCtree* tree)
|
||||
static OCerror
|
||||
createtempfile(OCstate* state, OCtree* tree)
|
||||
{
|
||||
int fd,c,slen = strlen(TMPPATH) + strlen("datadds") + strlen("XXXXXX");
|
||||
char* name = (char*)ocmalloc(slen+1);
|
||||
char* p;
|
||||
int fd,slen;
|
||||
char* name;
|
||||
slen = strlen(TMPPATH1);
|
||||
if(slen < strlen(TMPPATH2)) slen = strlen(TMPPATH2);
|
||||
slen += strlen("datadds") + strlen("XXXXXX");
|
||||
name = (char*)ocmalloc(slen+1);
|
||||
MEMCHECK(name,OC_ENOMEM);
|
||||
strcpy(name,TMPPATH);
|
||||
strcpy(name,"datadds");
|
||||
fd = createtempfile1(name, TMPPATH1);
|
||||
if(fd < 0)
|
||||
fd = createtempfile1(name, TMPPATH2);
|
||||
if(fd < 0) {
|
||||
oc_log(LOGERR,"oc_open: attempt to open tmp file %s failed",name);
|
||||
return errno;
|
||||
}
|
||||
oc_log(LOGNOTE,"oc_open: using tmp file: %s",name);
|
||||
tree->data.filename = name; /* remember our tmp file name */
|
||||
tree->data.file = fdopen(fd,"w+");
|
||||
if(tree->data.file == NULL) return OC_EOPEN;
|
||||
/* unlink the temp file so it will automatically be reclaimed */
|
||||
if(ocdebug == 0) unlink(tree->data.filename);
|
||||
return OC_NOERR;
|
||||
}
|
||||
|
||||
int
|
||||
createtempfile1(char* name, char* tmppath)
|
||||
{
|
||||
char* p;
|
||||
int c,fd;
|
||||
strcpy(name,tmppath);
|
||||
strcat(name,"datadds");
|
||||
strcat(name,"XXXXXX");
|
||||
p = name + strlen("datadds");
|
||||
/* \', and '/' to '_' and '.' to '-'*/
|
||||
@ -471,16 +497,7 @@ createtempfile(OCstate* state, OCtree* tree)
|
||||
/* Note Potential problem: old versions of this function
|
||||
leave the file in mode 0666 instead of 0600 */
|
||||
fd = mkstemp(name);
|
||||
if(fd < 0) {
|
||||
oc_log(LOGERR,"oc_open: attempt to open tmp file %s failed",name);
|
||||
return errno;
|
||||
}
|
||||
tree->data.filename = name; /* remember our tmp file name */
|
||||
tree->data.file = fdopen(fd,"w+");
|
||||
if(tree->data.file == NULL) return OC_EOPEN;
|
||||
/* unlink the temp file so it will automatically be reclaimed */
|
||||
if(ocdebug == 0) unlink(tree->data.filename);
|
||||
return OC_NOERR;
|
||||
return fd;
|
||||
}
|
||||
#endif /*OC_DISK_STORAGE*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user