mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
Merge pull request #1177 from Unidata/v4.6.2-release-branch.wif
Merge v4.6.2 release branch back upstream
This commit is contained in:
commit
086801a81b
@ -1,5 +1,3 @@
|
||||
# Doxyfile 1.8.3, mixed with 1.8.6
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
#
|
||||
@ -754,6 +752,7 @@ INPUT = \
|
||||
@abs_top_srcdir@/docs/attribute_conventions.md \
|
||||
@abs_top_srcdir@/docs/file_format_specifications.md \
|
||||
@abs_top_srcdir@/docs/DAP2.dox \
|
||||
@abs_top_srcdir@/docs/DAP4.dox \
|
||||
@abs_top_srcdir@/docs/user_defined_formats.md \
|
||||
@abs_top_srcdir@/docs/filters.md \
|
||||
@abs_top_srcdir@/docs/inmemory.md \
|
||||
@ -890,7 +889,7 @@ EXAMPLE_PATH = @abs_top_srcdir@/examples/C
|
||||
# *.h) to filter out the source-files in the directories. If left blank all
|
||||
# files are included.
|
||||
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_PATTERNS =
|
||||
|
||||
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
|
||||
# searched for input files to be used with the \include or \dontinclude commands
|
||||
|
@ -60,7 +60,7 @@ typedef struct NC_HDF5_FILE_INFO
|
||||
int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid);
|
||||
int rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid);
|
||||
void reportopenobjects(int log, hid_t);
|
||||
|
||||
int nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp);
|
||||
|
||||
/* Used by NC4_set_provenance */
|
||||
int nc4_put_att(NC_GRP_INFO_T* grp, int varid, const char *name, nc_type file_type,
|
||||
|
@ -376,10 +376,8 @@ int nc4_var_list_add(NC_GRP_INFO_T* grp, const char* name, int ndims, NC_VAR_INF
|
||||
int nc4_var_list_add2(NC_GRP_INFO_T* grp, const char* name, NC_VAR_INFO_T **var);
|
||||
int nc4_var_set_ndims(NC_VAR_INFO_T *var, int ndims);
|
||||
int nc4_var_list_del(NC_GRP_INFO_T* grp, NC_VAR_INFO_T *var);
|
||||
int nc4_var_free(NC_VAR_INFO_T *var);
|
||||
int nc4_dim_list_add(NC_GRP_INFO_T* grp, const char* name, size_t len, int assignedid, NC_DIM_INFO_T **dim);
|
||||
int nc4_dim_list_del(NC_GRP_INFO_T* grp, NC_DIM_INFO_T *dim);
|
||||
int nc4_dim_free(NC_DIM_INFO_T *dim);
|
||||
int nc4_type_new(NC_GRP_INFO_T *grp, size_t size, const char *name, int assignedid, NC_TYPE_INFO_T **type);
|
||||
int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name, NC_TYPE_INFO_T **type);
|
||||
int nc4_type_list_del(NC_GRP_INFO_T* grp, NC_TYPE_INFO_T *type);
|
||||
@ -389,7 +387,6 @@ int nc4_field_list_add(NC_TYPE_INFO_T* parent, const char *name,
|
||||
nc_type xtype, int ndims, const int *dim_sizesp);
|
||||
int nc4_att_list_add(NCindex* list, const char* name, NC_ATT_INFO_T **att);
|
||||
int nc4_att_list_del(NCindex* list, NC_ATT_INFO_T *att);
|
||||
int nc4_att_free(NC_ATT_INFO_T *att);
|
||||
int nc4_grp_list_add(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *parent, char *name, NC_GRP_INFO_T **grp);
|
||||
int nc4_build_root_grp(NC_FILE_INFO_T* h5);
|
||||
int nc4_rec_grp_del(NC_GRP_INFO_T *grp);
|
||||
@ -410,7 +407,8 @@ int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name);
|
||||
int nc4_get_default_fill_value(const NC_TYPE_INFO_T *type_info, void *fill_value);
|
||||
|
||||
/* Close the file. */
|
||||
int nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio*);
|
||||
int nc4_close_hdf5_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio);
|
||||
int nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio);
|
||||
|
||||
/* HDF5 initialization/finalization */
|
||||
extern int nc4_hdf5_initialized;
|
||||
|
@ -153,9 +153,9 @@ int nc_utf8_to_utf16(const unsigned char* s8, unsigned short** utf16p, size_t* l
|
||||
goto done;
|
||||
} else { /* move to next char */
|
||||
/* Complain if top 16 bits not zero */
|
||||
if((codepoint & 0x0000FFFF) != 0) {
|
||||
ncstat = NC_EBADNAME;
|
||||
goto done;
|
||||
if((codepoint & 0xFFFF0000) != 0) {
|
||||
ncstat = NC_EBADNAME;
|
||||
goto done;
|
||||
}
|
||||
/* Truncate codepoint to 16 bits and store */
|
||||
*p16++ = (unsigned short)(codepoint & 0x0000FFFF);
|
||||
|
@ -240,7 +240,7 @@ exit: /*failure exit*/
|
||||
#endif
|
||||
if (fapl_id != H5P_DEFAULT) H5Pclose(fapl_id);
|
||||
if(!nc4_info) return retval;
|
||||
nc4_close_netcdf4_file(nc4_info,1,NULL); /* treat like abort */
|
||||
nc4_close_hdf5_file(nc4_info, 1, NULL); /* treat like abort */
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ sync_netcdf4_file(NC_FILE_INFO_T *h5)
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio* memio)
|
||||
nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio)
|
||||
{
|
||||
NC_HDF5_FILE_INFO_T *hdf5_info;
|
||||
int retval;
|
||||
@ -174,16 +174,6 @@ nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio* memio)
|
||||
/* Get HDF5 specific info. */
|
||||
hdf5_info = (NC_HDF5_FILE_INFO_T *)h5->format_file_info;
|
||||
|
||||
/* According to the docs, always end define mode on close. */
|
||||
if (h5->flags & NC_INDEF)
|
||||
h5->flags ^= NC_INDEF;
|
||||
|
||||
/* Sync the file, unless we're aborting, or this is a read-only
|
||||
* file. */
|
||||
if (!h5->no_write && !abort)
|
||||
if ((retval = sync_netcdf4_file(h5)))
|
||||
return retval;
|
||||
|
||||
/* Delete all the list contents for vars, dims, and atts, in each
|
||||
* group. */
|
||||
if ((retval = nc4_rec_grp_del(h5->root_grp)))
|
||||
@ -252,6 +242,53 @@ nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio* memio)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This function will recurse through an open HDF5 file and
|
||||
* release resources. All open HDF5 objects in the file will be
|
||||
* closed.
|
||||
*
|
||||
* @param h5 Pointer to HDF5 file info struct.
|
||||
* @param abort True if this is an abort.
|
||||
* @param memio the place to return a core image if not NULL
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EHDFERR HDF5 could not close the file.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
nc4_close_hdf5_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio)
|
||||
{
|
||||
NC_HDF5_FILE_INFO_T *hdf5_info;
|
||||
int retval;
|
||||
|
||||
assert(h5 && h5->root_grp && h5->format_file_info);
|
||||
LOG((3, "%s: h5->path %s abort %d", __func__, h5->controller->path, abort));
|
||||
|
||||
/* Get HDF5 specific info. */
|
||||
hdf5_info = (NC_HDF5_FILE_INFO_T *)h5->format_file_info;
|
||||
|
||||
/* According to the docs, always end define mode on close. */
|
||||
if (h5->flags & NC_INDEF)
|
||||
h5->flags ^= NC_INDEF;
|
||||
|
||||
/* Sync the file, unless we're aborting, or this is a read-only
|
||||
* file. */
|
||||
if (!h5->no_write && !abort)
|
||||
if ((retval = sync_netcdf4_file(h5)))
|
||||
return retval;
|
||||
|
||||
/* Close all open HDF5 objects within the file. */
|
||||
if ((retval = nc4_rec_grp_HDF5_del(h5->root_grp)))
|
||||
return retval;
|
||||
|
||||
/* Release all intarnal lists and metadata associated with this
|
||||
* file. All HDF5 objects have already been released. */
|
||||
if ((retval = nc4_close_netcdf4_file(h5, abort, memio)))
|
||||
return retval;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Output a list of still-open objects in the HDF5
|
||||
* file. This is only called if the file fails to close cleanly.
|
||||
@ -515,7 +552,7 @@ NC4_abort(int ncid)
|
||||
|
||||
/* Free any resources the netcdf-4 library has for this file's
|
||||
* metadata. */
|
||||
if ((retval = nc4_close_netcdf4_file(nc4_info, 1, NULL)))
|
||||
if ((retval = nc4_close_hdf5_file(nc4_info, 1, NULL)))
|
||||
return retval;
|
||||
|
||||
/* Delete the file, if we should. */
|
||||
@ -564,7 +601,7 @@ NC4_close(int ncid, void* params)
|
||||
}
|
||||
|
||||
/* Call the nc4 close. */
|
||||
if ((retval = nc4_close_netcdf4_file(grp->nc4_info, 0, memio)))
|
||||
if ((retval = nc4_close_hdf5_file(grp->nc4_info, 0, memio)))
|
||||
return retval;
|
||||
|
||||
return NC_NOERR;
|
||||
|
@ -478,6 +478,129 @@ exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Recursively free HDF5 objects for a group (and everything
|
||||
* it contains).
|
||||
*
|
||||
* @param grp Pointer to group info struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
nc4_rec_grp_HDF5_del(NC_GRP_INFO_T *grp)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_ATT_INFO_T *att;
|
||||
int a;
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
assert(grp);
|
||||
LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
|
||||
|
||||
/* Recursively call this function for each child, if any, stopping
|
||||
* if there is an error. */
|
||||
for (i = 0; i < ncindexsize(grp->children); i++)
|
||||
if ((retval = nc4_rec_grp_HDF5_del((NC_GRP_INFO_T *)ncindexith(grp->children,
|
||||
i))))
|
||||
return retval;
|
||||
|
||||
/* Close HDF5 resources associated with attributes. */
|
||||
for (a = 0; a < ncindexsize(grp->att); a++)
|
||||
{
|
||||
att = (NC_ATT_INFO_T *)ncindexith(grp->att, a);
|
||||
assert(att);
|
||||
|
||||
/* Close the HDF5 typeid. */
|
||||
if (att->native_hdf_typeid && H5Tclose(att->native_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
|
||||
/* Close HDF5 resources associated with vars. */
|
||||
for (i = 0; i < ncindexsize(grp->vars); i++)
|
||||
{
|
||||
var = (NC_VAR_INFO_T *)ncindexith(grp->vars, i);
|
||||
assert(var);
|
||||
|
||||
/* Close the HDF5 dataset associated with this var. */
|
||||
if (var->hdf_datasetid)
|
||||
{
|
||||
LOG((3, "closing HDF5 dataset %lld", var->hdf_datasetid));
|
||||
if (H5Dclose(var->hdf_datasetid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
|
||||
for (a = 0; a < ncindexsize(var->att); a++)
|
||||
{
|
||||
att = (NC_ATT_INFO_T *)ncindexith(var->att, a);
|
||||
assert(att);
|
||||
|
||||
/* Close the HDF5 typeid if one is open. */
|
||||
if (att->native_hdf_typeid && H5Tclose(att->native_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close HDF5 resources associated with dims. */
|
||||
for (i = 0; i < ncindexsize(grp->dim); i++)
|
||||
{
|
||||
dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
|
||||
assert(dim);
|
||||
|
||||
/* If this is a dim without a coordinate variable, then close
|
||||
* the HDF5 DIM_WITHOUT_VARIABLE dataset associated with this
|
||||
* dim. */
|
||||
if (dim->hdf_dimscaleid && H5Dclose(dim->hdf_dimscaleid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
|
||||
/* Close HDF5 resources associated with types. Set values to 0
|
||||
* after closing types. Because of type reference counters, these
|
||||
* closes can be called multiple times. */
|
||||
for (i = 0; i < ncindexsize(grp->type); i++)
|
||||
{
|
||||
NC_TYPE_INFO_T *type = (NC_TYPE_INFO_T *)ncindexith(grp->type, i);
|
||||
assert(type);
|
||||
|
||||
/* Close any open user-defined HDF5 typeids. */
|
||||
if (type->hdf_typeid && H5Tclose(type->hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
type->hdf_typeid = 0;
|
||||
if (type->native_hdf_typeid && H5Tclose(type->native_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
type->native_hdf_typeid = 0;
|
||||
|
||||
/* Class-specific cleanup. Only enums and vlens have HDF5
|
||||
* resources to close. */
|
||||
switch (type->nc_type_class)
|
||||
{
|
||||
case NC_ENUM:
|
||||
if (type->u.e.base_hdf_typeid && H5Tclose(type->u.e.base_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
type->u.e.base_hdf_typeid = 0;
|
||||
break;
|
||||
|
||||
case NC_VLEN:
|
||||
if (type->u.v.base_hdf_typeid && H5Tclose(type->u.v.base_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
type->u.v.base_hdf_typeid = 0;
|
||||
break;
|
||||
|
||||
default: /* Do nothing. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the HDF5 group. */
|
||||
LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
|
||||
if (grp->hdf_grpid && H5Gclose(grp->hdf_grpid) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
#ifdef LOGGING
|
||||
/* We will need to check against nc log level from nc4internal.c. */
|
||||
extern int nc_log_level;
|
||||
|
@ -552,7 +552,7 @@ exit:
|
||||
if (fapl_id > 0 && fapl_id != H5P_DEFAULT)
|
||||
H5Pclose(fapl_id);
|
||||
if (nc4_info)
|
||||
nc4_close_netcdf4_file(nc4_info, 1, 0); /* treat like abort*/
|
||||
nc4_close_hdf5_file(nc4_info, 1, 0); /* treat like abort*/
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1040,24 +1040,20 @@ nc4_type_free(NC_TYPE_INFO_T *type)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(type && type->rc && type->hdr.name);
|
||||
|
||||
/* Decrement the ref. count on the type */
|
||||
assert(type->rc);
|
||||
type->rc--;
|
||||
|
||||
/* Release the type, if the ref. count drops to zero */
|
||||
if (0 == type->rc)
|
||||
if (type->rc == 0)
|
||||
{
|
||||
/* Close any open user-defined HDF5 typeids. */
|
||||
if (type->hdf_typeid && H5Tclose(type->hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
if (type->native_hdf_typeid && H5Tclose(type->native_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
LOG((4, "%s: deleting type %s", __func__, type->hdr.name));
|
||||
|
||||
/* Free the name. */
|
||||
if (type->hdr.name)
|
||||
free(type->hdr.name);
|
||||
free(type->hdr.name);
|
||||
|
||||
/* Class-specific cleanup */
|
||||
/* Enums and compound types have lists of fields to clean up. */
|
||||
switch (type->nc_type_class)
|
||||
{
|
||||
case NC_COMPOUND:
|
||||
@ -1071,7 +1067,6 @@ nc4_type_free(NC_TYPE_INFO_T *type)
|
||||
field_free(field);
|
||||
}
|
||||
nclistfree(type->u.c.field);
|
||||
type->u.c.field = NULL; /* belt and suspenders */
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1087,17 +1082,9 @@ nc4_type_free(NC_TYPE_INFO_T *type)
|
||||
free(enum_member);
|
||||
}
|
||||
nclistfree(type->u.e.enum_member);
|
||||
type->u.e.enum_member = NULL; /* belt and suspenders */
|
||||
|
||||
if (H5Tclose(type->u.e.base_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case NC_VLEN:
|
||||
if (H5Tclose(type->u.v.base_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1110,48 +1097,96 @@ nc4_type_free(NC_TYPE_INFO_T *type)
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Delete a var, and free the memory.
|
||||
* @internal Free memory of an attribute object
|
||||
*
|
||||
* @param att Pointer to attribute info struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
att_free(NC_ATT_INFO_T *att)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(att);
|
||||
LOG((3, "%s: name %s ", __func__, att->hdr.name));
|
||||
|
||||
/* Free memory that was malloced to hold data for this
|
||||
* attribute. */
|
||||
if (att->data)
|
||||
free(att->data);
|
||||
|
||||
/* Free the name. */
|
||||
if (att->hdr.name)
|
||||
free(att->hdr.name);
|
||||
|
||||
/* If this is a string array attribute, delete all members of the
|
||||
* string array, then delete the array of pointers to strings. (The
|
||||
* array was filled with pointers by HDF5 when the att was read,
|
||||
* and memory for each string was allocated by HDF5. That's why I
|
||||
* use free and not nc_free, because the netCDF library didn't
|
||||
* allocate the memory that is being freed.) */
|
||||
if (att->stdata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
if(att->stdata[i])
|
||||
free(att->stdata[i]);
|
||||
free(att->stdata);
|
||||
}
|
||||
|
||||
/* If this att has vlen data, release it. */
|
||||
if (att->vldata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
nc_free_vlen(&att->vldata[i]);
|
||||
free(att->vldata);
|
||||
}
|
||||
|
||||
free(att);
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Delete a var, and free the memory. All HDF5 objects for
|
||||
* the var must be closed before this is called.
|
||||
*
|
||||
* @param var Pointer to the var info struct of var to delete.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
nc4_var_free(NC_VAR_INFO_T *var)
|
||||
static int
|
||||
var_free(NC_VAR_INFO_T *var)
|
||||
{
|
||||
NC_ATT_INFO_T *att;
|
||||
int ret = NC_NOERR;
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
if(var == NULL)
|
||||
return NC_NOERR;
|
||||
assert(var);
|
||||
LOG((4, "%s: deleting var %s", __func__, var->hdr.name));
|
||||
|
||||
/* First delete all the attributes attached to this var. */
|
||||
for(i=0;i<ncindexsize(var->att);i++) {
|
||||
att = (NC_ATT_INFO_T*)ncindexith(var->att,i);
|
||||
if(att == NULL) continue; /* might be a gap */
|
||||
if ((ret = nc4_att_free(att)))
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < ncindexsize(var->att); i++)
|
||||
if ((retval = att_free((NC_ATT_INFO_T *)ncindexith(var->att, i))))
|
||||
return retval;
|
||||
ncindexfree(var->att);
|
||||
var->att = NULL;
|
||||
|
||||
/* Free some things that may be allocated. */
|
||||
/* Free some things that may be allocated. */
|
||||
if (var->chunksizes)
|
||||
{free(var->chunksizes);var->chunksizes = NULL;}
|
||||
free(var->chunksizes);
|
||||
|
||||
if (var->hdf5_name)
|
||||
{free(var->hdf5_name); var->hdf5_name = NULL;}
|
||||
free(var->hdf5_name);
|
||||
|
||||
if (var->hdr.name)
|
||||
{free(var->hdr.name); var->hdr.name = NULL;}
|
||||
free(var->hdr.name);
|
||||
|
||||
if (var->dimids)
|
||||
{free(var->dimids); var->dimids = NULL;}
|
||||
free(var->dimids);
|
||||
|
||||
if (var->dim)
|
||||
{free(var->dim); var->dim = NULL;}
|
||||
free(var->dim);
|
||||
|
||||
/* Delete any fill value allocation. This must be done before the
|
||||
* type_info is freed. */
|
||||
@ -1168,18 +1203,12 @@ nc4_var_free(NC_VAR_INFO_T *var)
|
||||
}
|
||||
}
|
||||
free(var->fill_value);
|
||||
var->fill_value = NULL;
|
||||
}
|
||||
|
||||
/* Release type information */
|
||||
if (var->type_info)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if ((retval = nc4_type_free(var->type_info)))
|
||||
return retval;
|
||||
var->type_info = NULL;
|
||||
}
|
||||
|
||||
/* Delete any HDF5 dimscale objid information. */
|
||||
if (var->dimscale_hdf5_objids)
|
||||
@ -1222,7 +1251,7 @@ nc4_var_list_del(NC_GRP_INFO_T* grp, NC_VAR_INFO_T *var)
|
||||
if(i >= 0)
|
||||
ncindexidel(grp->vars, i);
|
||||
}
|
||||
return nc4_var_free(var);
|
||||
return var_free(var);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1233,16 +1262,17 @@ nc4_var_list_del(NC_GRP_INFO_T* grp, NC_VAR_INFO_T *var)
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett, Ward Fisher
|
||||
*/
|
||||
int
|
||||
nc4_dim_free(NC_DIM_INFO_T *dim)
|
||||
static int
|
||||
dim_free(NC_DIM_INFO_T *dim)
|
||||
{
|
||||
/* Free memory allocated for names. */
|
||||
if(dim) {
|
||||
if (dim->hdr.name)
|
||||
free(dim->hdr.name);
|
||||
assert(dim);
|
||||
LOG((4, "%s: deleting dim %s", __func__, dim->hdr.name));
|
||||
|
||||
free(dim);
|
||||
}
|
||||
/* Free memory allocated for names. */
|
||||
if (dim->hdr.name)
|
||||
free(dim->hdr.name);
|
||||
|
||||
free(dim);
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -1263,7 +1293,7 @@ nc4_dim_list_del(NC_GRP_INFO_T* grp, NC_DIM_INFO_T *dim)
|
||||
if(pos >= 0)
|
||||
ncindexidel(grp->dim,pos);
|
||||
}
|
||||
return nc4_dim_free(dim);
|
||||
return dim_free(dim);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1278,18 +1308,12 @@ nc4_dim_list_del(NC_GRP_INFO_T* grp, NC_DIM_INFO_T *dim)
|
||||
int
|
||||
nc4_rec_grp_del(NC_GRP_INFO_T *grp)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_DIM_INFO_T *dim;
|
||||
int retval;
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
assert(grp);
|
||||
LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
|
||||
|
||||
/* WARNING: for all these deletes, the nc4_xxx_del functions will
|
||||
modify the index, so we need to not assume any state about
|
||||
them. */
|
||||
|
||||
/* Recursively call this function for each child, if any, stopping
|
||||
* if there is an error. */
|
||||
for (i = 0; i < ncindexsize(grp->children); i++)
|
||||
@ -1297,68 +1321,31 @@ nc4_rec_grp_del(NC_GRP_INFO_T *grp)
|
||||
i))))
|
||||
return retval;
|
||||
ncindexfree(grp->children);
|
||||
grp->children = NULL;
|
||||
|
||||
/* Free attributes, but leave in parent list */
|
||||
for (i = 0; i < ncindexsize(grp->att); i++)
|
||||
if ((retval = nc4_att_free((NC_ATT_INFO_T *)ncindexith(grp->att, i))))
|
||||
if ((retval = att_free((NC_ATT_INFO_T *)ncindexith(grp->att, i))))
|
||||
return retval;
|
||||
ncindexfree(grp->att);
|
||||
grp->att = NULL;
|
||||
|
||||
/* Delete all vars. */
|
||||
for (i = 0; i < ncindexsize(grp->vars); i++) {
|
||||
var = (NC_VAR_INFO_T *)ncindexith(grp->vars,i);
|
||||
assert(var);
|
||||
LOG((4, "%s: deleting var %s", __func__, var->hdr.name));
|
||||
/* Close HDF5 dataset associated with this var, unless it's a
|
||||
* scale. */
|
||||
if (var->hdf_datasetid)
|
||||
{
|
||||
LOG((3, "closing dataset %lld", var->hdf_datasetid));
|
||||
if (H5Dclose(var->hdf_datasetid) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
if ((retval = nc4_var_free(var))) /* free but leave in parent list */
|
||||
for (i = 0; i < ncindexsize(grp->vars); i++)
|
||||
if ((retval = var_free((NC_VAR_INFO_T *)ncindexith(grp->vars, i))))
|
||||
return retval;
|
||||
}
|
||||
ncindexfree(grp->vars);
|
||||
|
||||
/* Delete all dims. */
|
||||
/* Delete all dims, and free the list of dims. */
|
||||
for (i = 0; i < ncindexsize(grp->dim); i++)
|
||||
{
|
||||
dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, i);
|
||||
assert(dim);
|
||||
LOG((4, "%s: deleting dim %s", __func__, dim->hdr.name));
|
||||
|
||||
/* If this is a dim without a coordinate variable, then close
|
||||
* the HDF5 DIM_WITHOUT_VARIABLE dataset associated with this
|
||||
* dim. */
|
||||
if (dim->hdf_dimscaleid && H5Dclose(dim->hdf_dimscaleid) < 0)
|
||||
return NC_EHDFERR;
|
||||
if ((retval = nc4_dim_free(dim))) /* free but leave in parent list */
|
||||
if ((retval = dim_free((NC_DIM_INFO_T *)ncindexith(grp->dim, i))))
|
||||
return retval;
|
||||
}
|
||||
ncindexfree(grp->dim);
|
||||
|
||||
/* Delete all types. */
|
||||
/* Is this code correct? I think it should do repeated passes
|
||||
over h5->alltypes using the ref count to decide what to delete */
|
||||
for (i = 0; i < ncindexsize(grp->type); i++)
|
||||
{
|
||||
NC_TYPE_INFO_T *type = (NC_TYPE_INFO_T *)ncindexith(grp->type, i);
|
||||
assert(type);
|
||||
LOG((4, "%s: deleting type %s", __func__, type->hdr.name));
|
||||
if ((retval = nc4_type_free(type))) /* free but leave in parent list */
|
||||
if ((retval = nc4_type_free((NC_TYPE_INFO_T *)ncindexith(grp->type, i))))
|
||||
return retval;
|
||||
}
|
||||
ncindexfree(grp->type);
|
||||
|
||||
/* Tell HDF5 we're closing this group. */
|
||||
LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
|
||||
if (grp->hdf_grpid && H5Gclose(grp->hdf_grpid) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Free the name. */
|
||||
free(grp->hdr.name);
|
||||
|
||||
@ -1383,63 +1370,7 @@ nc4_att_list_del(NCindex *list, NC_ATT_INFO_T *att)
|
||||
{
|
||||
assert(att && list);
|
||||
ncindexidel(list, ((NC_OBJ *)att)->id);
|
||||
return nc4_att_free(att);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Free memory of an attribute object
|
||||
*
|
||||
* @param att Pointer to attribute info struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
nc4_att_free(NC_ATT_INFO_T *att)
|
||||
{
|
||||
int i;
|
||||
|
||||
LOG((3, "%s: name %s ", __func__, att->hdr.name));
|
||||
|
||||
/* Free memory that was malloced to hold data for this
|
||||
* attribute. */
|
||||
if (att->data)
|
||||
free(att->data);
|
||||
|
||||
/* Free the name. */
|
||||
if (att->hdr.name) {
|
||||
free(att->hdr.name);
|
||||
att->hdr.name = NULL;
|
||||
}
|
||||
|
||||
/* Close the HDF5 typeid. */
|
||||
if (att->native_hdf_typeid && H5Tclose(att->native_hdf_typeid) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* If this is a string array attribute, delete all members of the
|
||||
* string array, then delete the array of pointers to strings. (The
|
||||
* array was filled with pointers by HDF5 when the att was read,
|
||||
* and memory for each string was allocated by HDF5. That's why I
|
||||
* use free and not nc_free, because the netCDF library didn't
|
||||
* allocate the memory that is being freed.) */
|
||||
if (att->stdata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
if(att->stdata[i])
|
||||
free(att->stdata[i]);
|
||||
free(att->stdata);
|
||||
}
|
||||
|
||||
/* If this att has vlen data, release it. */
|
||||
if (att->vldata)
|
||||
{
|
||||
for (i = 0; i < att->len; i++)
|
||||
nc_free_vlen(&att->vldata[i]);
|
||||
free(att->vldata);
|
||||
}
|
||||
|
||||
free(att);
|
||||
return NC_NOERR;
|
||||
return att_free(att);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,14 +78,11 @@ IF(BUILD_UTILITIES)
|
||||
add_sh_test(nc_test run_mmap)
|
||||
SET_TESTS_PROPERTIES(nc_test_run_mmap PROPERTIES RUN_SERIAL TRUE)
|
||||
ENDIF(BUILD_MMAP)
|
||||
if(USE_NETCDF4)
|
||||
IF(LARGE_FILE_TESTS)
|
||||
add_sh_test(nc_test run_diskless2)
|
||||
ENDIF(LARGE_FILE_TESTS)
|
||||
ENDIF(USE_NETCDF4)
|
||||
add_sh_test(nc_test run_diskless5)
|
||||
add_sh_test(nc_test run_inmemory)
|
||||
|
||||
IF(LARGE_FILE_TESTS)
|
||||
add_sh_test(nc_test run_diskless2)
|
||||
ENDIF()
|
||||
ENDIF(BUILD_UTILITIES)
|
||||
|
||||
# Copy some test files from current source dir to out-of-tree build dir.
|
||||
|
@ -60,7 +60,7 @@ endif
|
||||
check_PROGRAMS = $(TESTPROGRAMS)
|
||||
|
||||
# Build Diskless test helpers
|
||||
check_PROGRAMS += tst_diskless tst_diskless3 tst_diskless4 \
|
||||
check_PROGRAMS += tst_diskless tst_diskless3 tst_diskless4 \
|
||||
tst_diskless5 tst_inmemory tst_open_mem
|
||||
if USE_NETCDF4
|
||||
check_PROGRAMS += tst_diskless2
|
||||
@ -70,12 +70,10 @@ TESTS = $(TESTPROGRAMS)
|
||||
|
||||
if BUILD_UTILITIES
|
||||
TESTS += run_diskless.sh run_diskless5.sh run_inmemory.sh
|
||||
if USE_NETCDF4
|
||||
if LARGE_FILE_TESTS
|
||||
TESTS += run_diskless2.sh
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_PNETCDF
|
||||
TESTS += run_pnetcdf_test.sh
|
||||
@ -92,7 +90,7 @@ CMakeLists.txt
|
||||
# These files are created by the tests.
|
||||
CLEANFILES = nc_test_*.nc tst_*.nc t_nc.nc large_files.nc \
|
||||
quick_large_files.nc tst_diskless3_file.cdl tst_diskless3_memory.cdl \
|
||||
tst_diskless4.cdl benchmark.nc
|
||||
tst_diskless4.cdl ref_tst_diskless4.cdl benchmark.nc
|
||||
|
||||
EXTRA_DIST += bad_cdf5_begin.nc run_cdf5.sh
|
||||
if ENABLE_CDF5
|
||||
|
@ -12,48 +12,46 @@ if test "x$srcdir" = x ; then srcdir=`pwd`; fi
|
||||
CPU=`uname -p`
|
||||
OS=`uname`
|
||||
|
||||
#Constants
|
||||
# Test diskless on a reasonably large file size
|
||||
|
||||
# Try a large in-memory file
|
||||
SIZE=1000000000
|
||||
|
||||
FILE4=tst_diskless4.nc
|
||||
|
||||
# Compute the file size for tst_diskless4
|
||||
SIZE=0
|
||||
case $CPU in
|
||||
*_64*) SIZE=3000000000;;
|
||||
*) SIZE=1000000000;;
|
||||
esac
|
||||
# Uncomment to get timing
|
||||
#TIME=time
|
||||
|
||||
# Create the reference ncdump output for tst_diskless4
|
||||
rm -fr tst_diskless4.cdl
|
||||
echo "netcdf tst_diskless4 {" >>tst_diskless4.cdl
|
||||
echo "dimensions:" >>tst_diskless4.cdl
|
||||
echo " dim = 1000000000 ;" >>tst_diskless4.cdl
|
||||
echo "variables:" >>tst_diskless4.cdl
|
||||
echo " byte var0(dim) ;" >>tst_diskless4.cdl
|
||||
if test $SIZE = 3000000000 ; then
|
||||
echo " byte var1(dim) ;" >>tst_diskless4.cdl
|
||||
echo " byte var2(dim) ;" >>tst_diskless4.cdl
|
||||
fi
|
||||
echo "}" >>tst_diskless4.cdl
|
||||
rm -fr ref_tst_diskless4.cdl
|
||||
cat >ref_tst_diskless4.cdl <<EOF
|
||||
netcdf tst_diskless4 {
|
||||
dimensions:
|
||||
dim = 1000000000 ;
|
||||
variables:
|
||||
byte var0(dim) ;
|
||||
}
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
rm -f $FILE4
|
||||
time ./tst_diskless4 $SIZE create
|
||||
$TIME ./tst_diskless4 $SIZE create
|
||||
# Validate it
|
||||
${NCDUMP} -h $FILE4 |diff -w - tst_diskless4.cdl
|
||||
${NCDUMP} -h $FILE4 |diff -w - ref_tst_diskless4.cdl
|
||||
|
||||
echo ""
|
||||
rm -f $FILE4
|
||||
time ./tst_diskless4 $SIZE creatediskless
|
||||
$TIME ./tst_diskless4 $SIZE creatediskless
|
||||
# Validate it
|
||||
${NCDUMP} -h $FILE4 |diff -w - tst_diskless4.cdl
|
||||
${NCDUMP} -h $FILE4 |diff -w - ref_tst_diskless4.cdl
|
||||
|
||||
echo ""
|
||||
time ./tst_diskless4 $SIZE open
|
||||
$TIME ./tst_diskless4 $SIZE open
|
||||
|
||||
echo ""
|
||||
time ./tst_diskless4 $SIZE opendiskless
|
||||
$TIME ./tst_diskless4 $SIZE opendiskless
|
||||
|
||||
# cleanup
|
||||
rm -f $FILE4 tst_diskless4.cdl
|
||||
rm -f $FILE4 tst_diskless4.cdl ref_tst_diskless4.cdl
|
||||
|
||||
exit
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define FILE_NAME "tst_diskless4.nc"
|
||||
#define CHUNKSIZE 4096
|
||||
#define DATASIZE (CHUNKSIZE/sizeof(int))
|
||||
#define DIMMAX 1000000000
|
||||
#define DIMMAX 1000000000L
|
||||
|
||||
typedef enum Tag {Create,CreateDiskless,Open,OpenDiskless} Tag;
|
||||
|
||||
@ -58,16 +58,8 @@ main(int argc, char **argv)
|
||||
/* Get the specified var/file size */
|
||||
if(argc > 1) {
|
||||
filesize = atol(argv[1]);
|
||||
} else {
|
||||
if(sizeof(size_t) == 4)
|
||||
filesize = 1000000000L;
|
||||
else if(sizeof(size_t) == 8)
|
||||
filesize = 3000000000L;
|
||||
else {
|
||||
fprintf(stderr,"Cannot compute filesize\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else
|
||||
filesize = 1000000000L;
|
||||
|
||||
/* Test that we can malloc that much space */
|
||||
memory = malloc(filesize);
|
||||
@ -99,7 +91,7 @@ main(int argc, char **argv)
|
||||
|
||||
switch (tag) {
|
||||
case Create: cmode = NC_CLOBBER; break;
|
||||
case CreateDiskless: cmode = NC_CLOBBER|NC_DISKLESS|NC_WRITE; break;
|
||||
case CreateDiskless: cmode = NC_CLOBBER|NC_DISKLESS|NC_PERSIST|NC_WRITE; break;
|
||||
case Open: cmode = 0; break;
|
||||
case OpenDiskless: cmode = NC_DISKLESS; break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user