diff --git a/benchmarks/WRF-IO/wrf_io.c b/benchmarks/WRF-IO/wrf_io.c index 37be0119b..718196d81 100644 --- a/benchmarks/WRF-IO/wrf_io.c +++ b/benchmarks/WRF-IO/wrf_io.c @@ -102,11 +102,14 @@ int construct_vars(int hid, /* CDL header ID */ nc_type xtype; /* determine whether to use longitude, latitude set at command line */ + + /* retrieve the number of dimensions defined in the CDL file */ err = cdl_hdr_inq_ndims(hid, &ndims); CHECK_ERR("cdl_hdr_inq_ndims") if (*longitude <= 0) { for (i=0; i 0) free(fname); + + /* close the CDL file */ cdl_hdr_close(hid); if (out_files != NULL) free(out_files); } diff --git a/doc/cdl_api_guide.md b/doc/cdl_api_guide.md new file mode 100644 index 000000000..62934ec09 --- /dev/null +++ b/doc/cdl_api_guide.md @@ -0,0 +1,461 @@ +## The CDL Header API Reference Guide + +Starting from PnetCDF 1.14.1, a set of C APIs have been added that read and +parse the header section of a CDL file. +([Common Data Language](https://docs.unidata.ucar.edu/nug/2.0-draft/cdl.html)) +is a text notation for representing the structure and data of a binary netCDF +file. As CDL files are in a plain text format, they can can be read by a human. +The new APIs allow users to query the metadata defined in the CDL file. They +can be useful for programs that want to read only the file header of a netCDF +file produced by other applications. A CDL file can be generated by running the +PnetCDF utility program +[ncmpidump](https://github.com/Parallel-NetCDF/PnetCDF/tree/master/src/utils#ncmpidump) +or NetCDF's +[ncdump](https://docs.unidata.ucar.edu/nug/current/netcdf_utilities_guide.html#ncdump_guide). +Both utility programs take an command-line option "-h" to dump only the file +header in a plain text format. + +Example programs can be found in +[examples/create_from_cdl.c](../examples/C/create_from_cdl.c) and +[benchmarks/WRF-IO/wrf_io.c.c](../benchmarks/WRF-IO/wrf_io.c). + +--- +### Table of contents + +* [cdl_hdr_open](#cdl_hdr_open) opens and parses the CDL file's header +* [cdl_hdr_inq_format](#cdl_hdr_inq_format) returns the file format version +* [cdl_hdr_inq_ndims](#cdl_hdr_inq_ndims) returns the number of dimensions + defined in CDL file +* [cdl_hdr_inq_dim](#cdl_hdr_inq_dim) returns the metadata of a dimension +* [cdl_hdr_inq_nvars](#cdl_hdr_inq_nvars) returns the number of variables +* [cdl_hdr_inq_var](#cdl_hdr_inq_var) returns the metadata of a variable + defined in CDL file +* [cdl_hdr_inq_nattrs](#cdl_hdr_inq_nattrs) returns the number of attributes of + a given variable +* [cdl_hdr_inq_attr](#cdl_hdr_inq_attr) returns the metadata of an attribute +* [cdl_hdr_close](#cdl_hdr_close) closes the CDL file + +--- +### cdl_hdr_open() +This API opens a file that is in the CDL format. + +#### Usage + ``` + int cdl_hdr_open(const char *filename, + int *hidp); + ``` + + **path** - [input] File name for a CDL file to be opened. + + + **hidp** - [output] Pointer to location where returned file ID is to be + stored. + +#### Return Error Codes +This API returns the value `NC_NOERR` if no errors occurred. Otherwise, the +returned value of type `int` indicates an error. Possible error codes and +causes of errors include: + + `NC_ENFILE` - too many files opened. + + `NC_ENOENT` - the specified input file does not exist. + + `NC_EFILE` - other unknown I/O error, including unable to open the file. + + `NC_ENOMEM` - unable to allocate memory (out of memory). + + `NC_ENOTNC` - input file is not in the CDL format. + +#### Example + ``` + #include + + int err, hid; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + ``` + +--- +### cdl_hdr_inq_format() +This API returns the file format version of a given file ID. + +#### Usage + ``` + int cdl_hdr_inq_format(int hid, + int *formatp); + ``` + + **hid** - [input] file ID, from a previous call to `cdl_hdr_open`. + + **formatp** - [output] Pointer to location for returned format version, one + of the following constants define in the header file pnetcdf.h. When this + argument is NULL, this API takes no effect simply returns `NC_NOERR`. + + * 1 - the classic CDF-1 format. + * 2 - the classic CDF-2 format (NC_64BIT_OFFSET). + * 5 - the classic CDF-5 format (NC_64BIT_DATA). + +#### Return Error Codes +This API returns the value `NC_NOERR` if no errors occurred. Otherwise, the +returned value of type `int` indicates an error. Possible error codes and +causes of errors include: + + `NC_EBADID` - the specified file ID, `hid`, does not refer to an opened CDL + file. + +#### Example + ``` + #include + + int err, hid, format; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve file format information of the input file */ + err = cdl_hdr_inq_format(hid, &format); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + ``` + +--- +### cdl_hdr_inq_ndims() +This API returns number of dimensions defined in the CDL file. + +#### Usage + ``` + int cdl_hdr_inq_ndims(int *hid, + int *ndimsp); + ``` + + **hid** - [input] file ID, from a previous call to `cdl_hdr_open`. + + **ndimsp** - [output] Pointer to location for returned number of dimensions + defined in the CDL file. When this argument is NULL, this API takes no + effect simply returns `NC_NOERR`. + +#### Return Error Codes +This API returns the value `NC_NOERR` if no errors occurred. Otherwise, the +returned value of type `int` indicates an error. Possible error codes and +causes of errors include: + + `NC_EBADID` - the specified file ID, `hid`, does not refer to an opened CDL + file. + +#### Example + ``` + #include + + int err, hid, ndims; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve the number of dimensions defined in the CDL file */ + err = cdl_hdr_inq_ndims(hid, &ndims); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + ``` + +--- +### cdl_hdr_inq_dim() +This API returns metadata of a dimension. + +#### Usage + ``` + int cdl_hdr_inq_dim(int hid, + int dimid, + char **namep, + MPI_Offset *sizep); + ``` + + **hid** - [input] file ID, from a previous call to `cdl_hdr_open`. + + **dimid** - [input] dimension ID. + + **namep** - [output] returned the name of dimension specified by its ID, + 'dimid'. Note users should not alter the contents of character string + pointed by 'namep', as it is an internal allocated data structure. When + `NULL` is passed in, this argument is ignored. + + **sizep** - [output] size of the dimension. When `NULL` is passed in, this + argument is ignored. + +#### Return Error Codes +This API returns the value `NC_NOERR` if no errors occurred. Otherwise, the +returned value of type `int` indicates an error. Possible error codes and +causes of errors include: + + `NC_EBADID` - the specified file ID, `hid`, does not refer to an opened CDL + file, or or the value of `dimid` is not within the range of number of + dimension defined in the CDL file. + +#### Example + ``` + #include + + int i, err, hid, ndims, + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve the number of dimensions defined in the CDL file */ + err = cdl_hdr_inq_ndims(hid, &ndims); + + for (i=0; i + + int err, hid, nvars; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve number of variables defined in the CDL file */ + err = cdl_hdr_inq_nvars(hid, &nvars); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + ``` + +--- +### cdl_hdr_inq_var() +This API returns metadata of a variable defined in CDL file. + +#### Usage + ``` + int cdl_hdr_inq_var(int hid, + int varid, + char **namep, + nc_type *xtypep, + int *ndimsp, + int **dimidsp); + ``` + + **hid** - [input] file ID, from a previous call to `cdl_hdr_open`. + + **varid** - [input] variable ID. + + **namep** - [output] returned the name of variable specified by its ID, + 'varid'. Note users should not alter the contents of character string + pointed by 'namep', as it is an internal allocated data structure. When + `NULL` is passed in, this argument is ignored. + + **xtypep** - [output] pointer to location for returned variable's data + type, one of the set of predefined netCDF external data types. The type of + this parameter, `nc_type`, is defined in the PnetCDF header file. The valid + data types are `NC_BYTE`, `NC_CHAR`, `NC_SHORT`, `NC_INT`, `NC_FLOAT`, + `NC_DOUBLE`, `NC_UBYTE`, `NC _USHORT`, `NC_UINT`, `NC_INT64`, and + `NC_UINT64`. When `NULL` is passed in, this argument is ignored. + + **ndimsp** - [output] pointer to location for returned number of dimensions + the variable was defined as using. When `NULL` is passed in, this argument + is ignored. + + **dimidsp** - [output] returned vector of dimension IDs corresponding to + the variable dimensions. Note users should not alter the contents pointed + by argument `dimidsp`, as it is an internal allocated data structure. When + `NULL` is passed in, this argument is ignored. + +#### Return Error Codes +This API returns the value `NC_NOERR` if no errors occurred. Otherwise, the +returned value of type `int` indicates an error. Possible error codes and +causes of errors include: + + `NC_EBADID` - the specified file ID, `hid`, does not refer to an opened CDL + file, or the value of `varid` is not within the range of number of + variables defined in the CDL file. + +#### Example + ``` + #include + + int i, err, hid, nvars; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve number of variables defined in the CDL file */ + err = cdl_hdr_inq_nvars(hid, &nvars); + + for (i=0; i + + int err, hid; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve the number of global attributes */ + err = cdl_hdr_inq_nattrs(hid, NC_GLOBAL, &nattrs); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + + for (i=0; i + + int err, hid, nattrs, nvars, nelems; + char *name; + void *value; + nc_type xtype; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* retrieve the number of global attributes */ + err = cdl_hdr_inq_nattrs(hid, NC_GLOBAL, &nattrs); ERR + + for (i=0; i + + int err, hid; + + /* open the input file in CDL format */ + err = cdl_hdr_open("cdl_header.txt", &hid); + + /* close CDL file */ + err = cdl_hdr_close(&hid); + if (err != NC_NOERR) + printf("Error at %s:%d : %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); + ``` + diff --git a/examples/C/create_from_cdl.c b/examples/C/create_from_cdl.c index 67154f40b..a2a2ae179 100644 --- a/examples/C/create_from_cdl.c +++ b/examples/C/create_from_cdl.c @@ -133,7 +133,7 @@ int main(int argc, char **argv) err = ncmpi_create(MPI_COMM_WORLD, outfile, cmode, MPI_INFO_NULL, &ncid); CHECK_ERR - /* define dimensions */ + /* retrieve the number of dimensions defined in the CDL file */ err = cdl_hdr_inq_ndims(hid, &ndims); CHECK_ERR if (verbose) printf("Number of dimensions : %d\n", ndims); @@ -142,14 +142,16 @@ int main(int argc, char **argv) int dimid; MPI_Offset dimlen; + /* retrieve metadata of dimension i */ err = cdl_hdr_inq_dim(hid, i, &name, &dimlen); - CHECK_ERR + CHECK_ERR + /* define a new dimension in the new file */ err = ncmpi_def_dim(ncid, name, dimlen, &dimid); CHECK_ERR } - /* define variables */ + /* retrieve number of variables defined in the CDL file */ err = cdl_hdr_inq_nvars(hid, &nvars); CHECK_ERR if (verbose) printf("Number of variables : %d\n", nvars); @@ -158,13 +160,15 @@ int main(int argc, char **argv) int varid, *dimids; nc_type xtype; + /* retrieve metadata of variable i defined in the CDL file */ err = cdl_hdr_inq_var(hid, i, &name, &xtype, &ndims, &dimids); CHECK_ERR + /* define a new variable in the new file */ err = ncmpi_def_var(ncid, name, xtype, ndims, dimids, &varid); CHECK_ERR - /* define variable's attributes */ + /* retrieve metadata of attribute j associated with variable i */ err = cdl_hdr_inq_nattrs(hid, i, &nattrs); CHECK_ERR @@ -173,14 +177,17 @@ int main(int argc, char **argv) nc_type xtype; MPI_Offset nelems; + /* retrieve metadata of attribute j associated with variable i */ err = cdl_hdr_inq_attr(hid, i, j, &name, &xtype, &nelems, &value); CHECK_ERR + + /* define a new attribute and associate it to variable, varid */ err = ncmpi_put_att(ncid, varid, name, xtype, nelems, value); CHECK_ERR } } - /* define global attributes */ + /* retrieve the number of global attributes */ err = cdl_hdr_inq_nattrs(hid, NC_GLOBAL, &nattrs); CHECK_ERR if (verbose) printf("Number of global attributes: %d\n", nattrs); @@ -190,15 +197,21 @@ int main(int argc, char **argv) nc_type xtype; MPI_Offset nelems; + /* retrieve metadata of global attribute i */ err = cdl_hdr_inq_attr(hid, NC_GLOBAL, i, &name, &xtype, &nelems, &value); CHECK_ERR + + /* define a global attribute in the new file */ err = ncmpi_put_att(ncid, NC_GLOBAL, name, xtype, nelems, value); CHECK_ERR } + + /* close the NetCDF file */ err = ncmpi_close(ncid); CHECK_ERR + /* close the CDL file */ err = cdl_hdr_close(hid); CHECK_ERR diff --git a/sneak_peek.md b/sneak_peek.md index 6004b7630..7c8033e8a 100644 --- a/sneak_peek.md +++ b/sneak_peek.md @@ -42,6 +42,9 @@ This is essentially a placeholder for the next release note ... * `cdl_hdr_inq_nattrs()` returns number of attributes of a given variable * `cdl_hdr_inq_attr()` returns metadata of an attribute * `cdl_hdr_close()` closes the CDL file + + The CDL Header C Reference Manual is available in + [cdl_api_guide.md](doc/cdl_api_guide.md). See + [PR #184](https://github.com/Parallel-NetCDF/PnetCDF/pull/184). * API syntax changes + none diff --git a/src/dispatchers/cdl_header_parser.c b/src/dispatchers/cdl_header_parser.c index 5b3dc8375..456228370 100644 --- a/src/dispatchers/cdl_header_parser.c +++ b/src/dispatchers/cdl_header_parser.c @@ -797,6 +797,9 @@ int cdl_hdr_inq_format(int hid, if (hid >= NC_MAX_NFILES || cdl_filelist[hid] == NULL) return NC_EBADID; + if (format == NULL) + return NC_NOERR; + header = cdl_filelist[hid]; *format = header->format; @@ -814,6 +817,9 @@ int cdl_hdr_inq_ndims(int hid, if (hid >= NC_MAX_NFILES || cdl_filelist[hid] == NULL) return NC_EBADID; + if (ndims == NULL) + return NC_NOERR; + header = cdl_filelist[hid]; *ndims = header->dims.nelems; @@ -998,7 +1004,7 @@ int main(int argc, char **argv) if (err != NC_NOERR) exit(1); printf("Input CDF file : %s\n", argv[1]); - /* retrieve the input file in CDL format */ + /* retrieve file format information of the input file */ err = cdl_hdr_inq_format(hid, &format); ERR printf("CDF file format: CDF-%d\n", format); @@ -1020,7 +1026,7 @@ int main(int argc, char **argv) for (i=0; i