mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-21 08:39:46 +08:00
d85bb6fe20
disengagement of enable-netcdf4 from enable-hdf5. That is, with the advent of nczarr, it is possible to turn off hdf5 but still need netcdf-4 enabled because nczarr uses libsrc4, but not libhdf5. This change involves a bunch of things: 1. Modify configure.ac and CMakelist to make enable_hdf5 control if hdf5 support is provided. For back compatibility, disable-netcdf4 is treated as disable-hdf5. But internally, netcdf4 support is controlled only by the enabling of formats that require it. 2. In support of #1, modify .travis.yml to use enable/disable-hdf5 instead of enable/disable-netcdf4. 3. test_common.in is modified to track selected features, including enable-hdf5 and enable-s3-tests. This is used in selected tests that mix netcdf-3 and netcdf4 tests. 4. The conflation of USE_HDF5 and USE_NETCDF4 is common in code, tests, and build files, so all of those had to be weeded out. 5. It turns out that some of the NC4_dim functions really are HDF5 specific, but are not treated as such. So they are moved from nc4dim.c to hdf5dim.c or hdf5dispatch.c 6. Some generic functions in libhdf5 can be (and were) moved to libsrc4.
251 lines
7.6 KiB
C
251 lines
7.6 KiB
C
/* Copyright 2003-2018, University Corporation for Atmospheric
|
|
* Research. See the COPYRIGHT file for copying and redistribution
|
|
* conditions.
|
|
*/
|
|
/**
|
|
* @file @internal Internal functions for filters
|
|
*
|
|
* This file contains functions internal to the netcdf4 library. None of
|
|
* the functions in this file are exposed in the exetnal API. These
|
|
* functions all relate to the manipulation of netcdf-4 filters
|
|
*
|
|
* @author Dennis Heimbigner
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include "zincludes.h"
|
|
|
|
/* Mnemonic */
|
|
#define FILTERACTIVE 1
|
|
|
|
/* WARNING: GLOBAL VARIABLE */
|
|
|
|
#ifdef ENABLE_CLIENTSIDE_FILTERS
|
|
/* Define list of registered filters */
|
|
static NClist* NCZ_registeredfilters = NULL; /** List<NC_FILTER_CLIENT_ZARR*> */
|
|
|
|
/**************************************************/
|
|
/* Filter registration support */
|
|
|
|
static int
|
|
filterlookup(conbst char* id)
|
|
{
|
|
int i;
|
|
if(NCZ_registeredfilters == NULL)
|
|
NCZ_registeredfilters = nclistnew();
|
|
for(i=0;i<nclistlength(NCZ_registeredfilters);i++) {
|
|
NCX_FILTER_CLIENT* x = nclistget(NCZ_registeredfilters,i);
|
|
if(x != NULL && x->id == id) return i; /* return position */
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void
|
|
reclaiminfo(NCX_FILTER_CLIENT* info)
|
|
{
|
|
nullfree(info);
|
|
}
|
|
|
|
static int
|
|
filterremove(int pos)
|
|
{
|
|
NCX_FILTER_CLIENT* info = NULL;
|
|
if(NCZ_registeredfilters == NULL)
|
|
return THROW(NC_EINVAL);
|
|
if(pos < 0 || pos >= nclistlength(NCZ_registeredfilters))
|
|
return THROW(NC_EINVAL);
|
|
info = nclistget(NCZ_registeredfilters,pos);
|
|
reclaiminfo(info);
|
|
nclistremove(NCZ_registeredfilters,pos);
|
|
return NC_NOERR;
|
|
}
|
|
|
|
static NCX_FILTER_CLIENT*
|
|
dupfilterinfo(NCX_FILTER_CLIENT* info)
|
|
{
|
|
NCX_FILTER_CLIENT* dup = NULL;
|
|
if(info == NULL) goto fail;
|
|
if((dup = calloc(1,sizeof(NCX_FILTER_CLIENT))) == NULL) goto fail;
|
|
*dup = *info;
|
|
return dup;
|
|
fail:
|
|
reclaiminfo(dup);
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
NCZ_global_filter_action(int op, unsigned int id, NC_FILTER_OBJ_HDF5* infop)
|
|
{
|
|
int stat = NC_NOERR;
|
|
H5Z_class2_t* h5filterinfo = NULL;
|
|
herr_t herr;
|
|
int pos = -1;
|
|
NCX_FILTER_CLIENT* dup = NULL;
|
|
NCX_FILTER_CLIENT* elem = NULL;
|
|
NCX_FILTER_CLIENT ncf;
|
|
|
|
switch (op) {
|
|
case NCFILTER_CLIENT_REG: /* Ignore id argument */
|
|
if(infop == NULL) {stat = NC_EINVAL; goto done;}
|
|
assert(NC_FILTER_FORMAT_HDF5 == infop->hdr.format);
|
|
assert(NC_FILTER_SORT_CLIENT == infop->sort);
|
|
elem = (NCX_FILTER_CLIENT*)&infop->u.client;
|
|
h5filterinfo = elem->info;
|
|
/* Another sanity check */
|
|
if(id != h5filterinfo->id)
|
|
{stat = NC_EINVAL; goto done;}
|
|
/* See if this filter is already defined */
|
|
if((pos = filterlookup(id)) >= 0)
|
|
{stat = NC_ENAMEINUSE; goto done;} /* Already defined */
|
|
if((herr = H5Zregister(h5filterinfo)) < 0)
|
|
{stat = NC_EFILTER; goto done;}
|
|
/* Save a copy of the passed in info */
|
|
ncf.id = id;
|
|
ncf.info = elem->info;
|
|
if((dup=dupfilterinfo(&ncf)) == NULL)
|
|
{stat = NC_ENOMEM; goto done;}
|
|
nclistpush(NCZ_registeredfilters,dup);
|
|
break;
|
|
case NCFILTER_CLIENT_UNREG:
|
|
if(id <= 0)
|
|
{stat = NC_EFILTER; goto done;}
|
|
/* See if this filter is already defined */
|
|
if((pos = filterlookup(id)) < 0)
|
|
{stat = NC_ENOFILTER; goto done;} /* Not defined */
|
|
if((herr = H5Zunregister(id)) < 0)
|
|
{stat = NC_EFILTER; goto done;}
|
|
if((stat=filterremove(pos))) goto done;
|
|
break;
|
|
case NCFILTER_CLIENT_INQ:
|
|
if(infop == NULL) goto done;
|
|
/* Look up the id in our local table */
|
|
if((pos = filterlookup(id)) < 0)
|
|
{stat = NC_ENOFILTER; goto done;} /* Not defined */
|
|
elem = (NCX_FILTER_CLIENT*)nclistget(NCZ_registeredfilters,pos);
|
|
if(elem == NULL) {stat = NC_EINTERNAL; goto done;}
|
|
if(infop != NULL) {
|
|
infop->u.client = *elem;
|
|
}
|
|
break;
|
|
default:
|
|
{stat = NC_EINTERNAL; goto done;}
|
|
}
|
|
done:
|
|
return THROW(stat);
|
|
}
|
|
#endif /*ENABLE_CLIENT_FILTERS*/
|
|
|
|
/**************************************************/
|
|
|
|
/**
|
|
* @internal Define filter settings. Called by nc_def_var_filter().
|
|
*
|
|
* @param ncid File ID.
|
|
* @param varid Variable ID.
|
|
* @param id Filter ID
|
|
* @param nparams Number of parameters for filter.
|
|
* @param parms Filter parameters.
|
|
*
|
|
* @returns ::NC_NOERR for success
|
|
* @returns ::NC_EBADID Bad ncid.
|
|
* @returns ::NC_ENOTVAR Invalid variable ID.
|
|
* @returns ::NC_ENOTNCZ Attempting netcdf-4 operation on file that is
|
|
* not netCDF-4/HDF5.
|
|
* @returns ::NC_ELATEDEF Too late to change settings for this variable.
|
|
* @returns ::NC_EFILTER Filter error.
|
|
* @returns ::NC_EINVAL Invalid input
|
|
* @author Dennis Heimbigner
|
|
*/
|
|
int
|
|
NCZ_filter_actions(int ncid, int varid, int op, void* args)
|
|
{
|
|
int stat = NC_NOERR;
|
|
NC_GRP_INFO_T *grp = NULL;
|
|
NC_FILE_INFO_T *h5 = NULL;
|
|
NC_VAR_INFO_T *var = NULL;
|
|
NC_FILTERX_OBJ* obj = (NC_FILTERX_OBJ*)args;
|
|
NC_FILTERX_SPEC* spec = NULL;
|
|
char** xfilterids = NULL;
|
|
size_t nfilters = 0;
|
|
|
|
LOG((2, "%s: ncid 0x%x varid %d op=%d", __func__, ncid, varid, op));
|
|
|
|
if(args == NULL) return THROW(NC_EINVAL);
|
|
|
|
/* Find info for this file and group and var, and set pointer to each. */
|
|
if ((stat = nc4_find_grp_h5_var(ncid, varid, &h5, &grp, &var)))
|
|
return THROW(stat);
|
|
|
|
assert(h5 && var && var->hdr.id == varid);
|
|
|
|
nfilters = nclistlength(var->filters);
|
|
|
|
switch (op) {
|
|
case NCFILTER_DEF: {
|
|
if(obj->usort != NC_FILTER_UNION_SPEC) return THROW(NC_EFILTER);
|
|
/* If the dataset has already been created, then it is too
|
|
* late to set all the extra stuff. */
|
|
if (!(h5->flags & NC_INDEF)) {stat = THROW(NC_EINDEFINE); goto done;}
|
|
if (!var->ndims) goto done; /* For scalars, ignore */
|
|
if (var->created)
|
|
{stat = THROW(NC_ELATEDEF); goto done;}
|
|
/* Filter => chunking */
|
|
var->storage = NC_CHUNKED;
|
|
/* Determine default chunksizes for this variable unless already specified */
|
|
if(var->chunksizes && !var->chunksizes[0]) {
|
|
/* Should this throw error? */
|
|
if((stat = ncz_find_default_chunksizes2(grp, var)))
|
|
goto done;
|
|
}
|
|
spec = &obj->u.spec;
|
|
if((stat = NC4_filterx_add(var,!FILTERACTIVE,spec->filterid,spec->nparams,(const char**)spec->params)))
|
|
goto done;
|
|
} break;
|
|
case NCFILTER_FILTERIDS: {
|
|
if(obj->usort != NC_FILTER_UNION_IDS) return THROW(NC_EFILTER);
|
|
if((obj->u.ids.filterids = calloc(sizeof(char*),nfilters))==NULL)
|
|
{stat = NC_ENOMEM; goto done;}
|
|
obj->u.ids.nfilters = nfilters;
|
|
if(nfilters > 0) {
|
|
int k;
|
|
for(k=0;k<nfilters;k++) {
|
|
NC_FILTERX_SPEC* f = (NC_FILTERX_SPEC*)nclistget(var->filters,k);
|
|
if((obj->u.ids.filterids[k] = strdup(f->filterid)) == NULL)
|
|
{stat = NC_ENOMEM; goto done;}
|
|
}
|
|
}
|
|
} break;
|
|
case NCFILTER_INFO: {
|
|
int k,found;
|
|
if(obj->usort != NC_FILTER_UNION_SPEC) return THROW(NC_EFILTER);
|
|
for(found=0,k=0;k<nfilters;k++) {
|
|
NC_FILTERX_SPEC* f = (NC_FILTERX_SPEC*)nclistget(var->filters,k);
|
|
if(strcasecmp(f->filterid,obj->u.spec.filterid)==0) {
|
|
obj->u.spec.nparams = f->nparams;
|
|
obj->u.spec.active = f->active;
|
|
if((stat = NC_filterx_copy(f->nparams,(const char**)f->params,&obj->u.spec.params)))
|
|
goto done;
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if(!found) {stat = NC_ENOFILTER; goto done;}
|
|
} break;
|
|
case NCFILTER_REMOVE:
|
|
if (!(h5->flags & NC_INDEF)) return THROW(NC_EINDEFINE);
|
|
if(obj->usort != NC_FILTER_UNION_SPEC) return THROW(NC_EFILTER);
|
|
if((stat = NC4_filterx_lookup(var,obj->u.spec.filterid,&spec))) goto done;
|
|
if(spec && spec->active)
|
|
{stat = NC_EFILTER; goto done;}
|
|
if((stat = NC4_filterx_remove(var,obj->u.spec.filterid))) goto done;
|
|
break;
|
|
default:
|
|
{stat = NC_EINTERNAL; goto done;}
|
|
}
|
|
|
|
done:
|
|
NC_filterx_freestringvec(nfilters,xfilterids);
|
|
return THROW(stat);
|
|
}
|