mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-02-17 16:50:18 +08:00
Merge pull request #1464 from NetCDF-World-Domination-Council/ejh_next
Remove obsolete _CRAYMPP and LOCKNUMREC macros
This commit is contained in:
commit
207f2b57fa
@ -21,6 +21,11 @@ test-driver-verbose test_common.in
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = netcdf.pc
|
||||
|
||||
# Does the user want to build and run unit tests?
|
||||
if BUILD_UNIT_TESTS
|
||||
UNIT_TEST = unit_test
|
||||
endif # BUILD_UNIT_TESTS
|
||||
|
||||
# Does the user want to build the V2 API?
|
||||
if BUILD_V2
|
||||
V2_TEST = nctest
|
||||
@ -85,8 +90,8 @@ endif # BUILD_BENCHMARKS
|
||||
|
||||
# Define Test directories
|
||||
if BUILD_TESTSETS
|
||||
TESTDIRS = $(V2_TEST) nc_test $(NC_TEST4) $(BENCHMARKS_DIR) \
|
||||
$(HDF4_TEST_DIR) $(NCDAP2TESTDIR) $(NCDAP4TESTDIR)
|
||||
TESTDIRS = $(UNIT_TEST) $(V2_TEST) nc_test $(NC_TEST4) \
|
||||
$(BENCHMARKS_DIR) $(HDF4_TEST_DIR) $(NCDAP2TESTDIR) $(NCDAP4TESTDIR)
|
||||
endif
|
||||
|
||||
# This is the list of subdirs for which Makefiles will be constructed
|
||||
|
@ -7,6 +7,13 @@ This file contains a high-level description of this package's evolution. Release
|
||||
|
||||
## 4.7.1 - TBD
|
||||
|
||||
* [Bug Fix] Remove obsolete _CRAYMPP and LOCKNUMREC macros from
|
||||
code. Also brought documentation up to date in man page. These macros
|
||||
were used in ancient times, before modern parallel I/O systems were
|
||||
developed. Programmers interested in parallel I/O should see
|
||||
nc_open_par() and nc_create_par().
|
||||
See [GitHub #1436](https://github.com/Unidata/netcdf-c/issues/1459)
|
||||
|
||||
* [Enhancement] Remove obsolete and deprecated functions
|
||||
nc_set_base_pe() and nc_inq_base_pe() from the dispatch table. (Both
|
||||
functions are still supported in the library, this is an internal
|
||||
|
@ -184,6 +184,14 @@ if test "x$enable_jna" = xyes ; then
|
||||
AC_DEFINE([JNA], [1], [if true, include jna bug workaround code])
|
||||
fi
|
||||
|
||||
# Does the user want to turn off unit tests (useful for test coverage
|
||||
# analysis).
|
||||
AC_ARG_ENABLE([unit-tests],
|
||||
[AS_HELP_STRING([--disable-unit-tests],
|
||||
[Disable tests in unit_test directory. Other tests still run.])])
|
||||
test "x$enable_unit_tests" = xno || enable_unit_tests=yes
|
||||
AM_CONDITIONAL([BUILD_UNIT_TESTS], [test "x$enable_unit_tests" = xyes])
|
||||
|
||||
# Does the user want to build netcdf-4?
|
||||
AC_MSG_CHECKING([whether we should build netCDF-4])
|
||||
AC_ARG_ENABLE([netcdf-4], [AS_HELP_STRING([--disable-netcdf-4],
|
||||
@ -1536,6 +1544,7 @@ AC_CONFIG_FILES([Makefile
|
||||
ncdump/expected/Makefile
|
||||
docs/Makefile
|
||||
docs/images/Makefile
|
||||
unit_test/Makefile
|
||||
nctest/Makefile
|
||||
nc_test4/Makefile
|
||||
nc_perf/Makefile
|
||||
|
@ -1411,47 +1411,29 @@ May be used to change access to a variable from independent to collective data a
|
||||
.HP
|
||||
.SH "MPP FUNCTION DESCRIPTIONS"
|
||||
.LP
|
||||
Additional functions for use on SGI/Cray MPP machines (_CRAYMPP).
|
||||
These are used to set and inquire which PE is the base for MPP
|
||||
for a particular netCDF. These are only relevant when
|
||||
using the SGI/Cray ``global''
|
||||
Flexible File I/O layer and desire to have
|
||||
only a subset of PEs to open the specific netCDF file.
|
||||
For technical reasons, these functions are available on all platforms.
|
||||
On a platform other than SGI/Cray MPP, it is as if
|
||||
only processor available were processor 0.
|
||||
These functions were used on archaic SGI/Cray MPP machines. These
|
||||
functions are retained for backward compatibility; the PE arguments
|
||||
must all be set to zero.
|
||||
.LP
|
||||
To use this feature, you need to specify a communicator group and call
|
||||
CODE(glio_group_mpi(\|)) or CODE(glio_group_shmem(\|)) prior to the netCDF
|
||||
FREF(open) and FREF(create) calls.
|
||||
.HP
|
||||
FDECL(_create_mp, (IPATH(), ICMODE(), IINITSIZE(), IPE(), OCHUNKSIZE(), ONCID()))
|
||||
.sp
|
||||
Like FREF(_create) but allows the base PE to be set.
|
||||
Like FREF(_create).
|
||||
.sp
|
||||
The argument ARG(pe) sets the base PE at creation time. In the MPP
|
||||
environment, FREF(_create) and FREF(create) set the base PE to processor
|
||||
zero by default.
|
||||
The argument ARG(pe) must be zero.
|
||||
.HP
|
||||
FDECL(_open_mp, (IPATH(), IMODE(), IPE(), OCHUNKSIZE(), ONCID()))
|
||||
.sp
|
||||
Like FREF(_open) but allows the base PE to be set.
|
||||
The argument ARG(pe) sets the base PE at creation time. In the MPP
|
||||
environment, FREF(_open) and FREF(open) set the base PE to processor
|
||||
zero by default.
|
||||
Like FREF(_open).
|
||||
The argument ARG(pe) must be zero.
|
||||
.HP
|
||||
FDECL(inq_base_pe, (INCID(), OPE()))
|
||||
.sp
|
||||
Inquires of the netCDF dataset which PE is being used as the base for MPP use.
|
||||
This is safe to use at any time.
|
||||
Always returns pe of zero.
|
||||
.HP
|
||||
FDECL(set_base_pe, (INCID(), IPE()))
|
||||
.sp
|
||||
Resets the base PE for the netCDF dataset.
|
||||
Only perform this operation when the affected communicator group
|
||||
synchronizes before and after the call.
|
||||
This operation is very risky and should only be contemplated
|
||||
under only the most extreme cases.
|
||||
This function does nothing.
|
||||
.SH "ENVIRONMENT VARIABLES"
|
||||
.TP 4
|
||||
.B NETCDF_FFIOSPEC
|
||||
|
@ -221,15 +221,6 @@ NC_lookupvar(NC3_INFO* ncp, int varid, NC_var **varp);
|
||||
#define IS_RECVAR(vp) \
|
||||
((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 )
|
||||
|
||||
#ifdef LOCKNUMREC
|
||||
/*
|
||||
* typedef SHMEM type
|
||||
* for whenever the SHMEM functions can handle other than shorts
|
||||
*/
|
||||
typedef unsigned short int ushmem_t;
|
||||
typedef short int shmem_t;
|
||||
#endif
|
||||
|
||||
struct NC3_INFO {
|
||||
/* contains the previous NC during redef. */
|
||||
NC3_INFO *old;
|
||||
@ -258,18 +249,6 @@ struct NC3_INFO {
|
||||
NC_dimarray dims;
|
||||
NC_attrarray attrs;
|
||||
NC_vararray vars;
|
||||
#ifdef LOCKNUMREC
|
||||
/* size and named indexes for the lock array protecting NC.numrecs */
|
||||
# define LOCKNUMREC_DIM 4
|
||||
# define LOCKNUMREC_VALUE 0
|
||||
# define LOCKNUMREC_LOCK 1
|
||||
# define LOCKNUMREC_SERVING 2
|
||||
# define LOCKNUMREC_BASEPE 3
|
||||
/* Used on Cray T3E MPP to maintain the
|
||||
* integrity of numrecs for an unlimited dimension
|
||||
*/
|
||||
ushmem_t lock[LOCKNUMREC_DIM];
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NC_readonly(ncp) \
|
||||
@ -305,7 +284,6 @@ struct NC3_INFO {
|
||||
#define NC_doNsync(ncp) \
|
||||
fIsSet((ncp)->flags, NC_NSYNC)
|
||||
|
||||
#ifndef LOCKNUMREC
|
||||
# define NC_get_numrecs(nc3i) \
|
||||
((nc3i)->numrecs)
|
||||
|
||||
@ -314,11 +292,6 @@ struct NC3_INFO {
|
||||
|
||||
# define NC_increase_numrecs(nc3i, nrecs) \
|
||||
{if((nrecs) > (nc3i)->numrecs) ((nc3i)->numrecs = (nrecs));}
|
||||
#else
|
||||
size_t NC_get_numrecs(const NC3_INFO *nc3i);
|
||||
void NC_set_numrecs(NC3_INFO *nc3i, size_t nrecs);
|
||||
void NC_increase_numrecs(NC3_INFO *nc3i, size_t nrecs);
|
||||
#endif
|
||||
|
||||
/* Begin defined in nc.c */
|
||||
|
||||
|
@ -4,7 +4,7 @@ Main header file for the C API.
|
||||
|
||||
Copyright 2018, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
|
||||
2015, 2016, 2017, 2018
|
||||
2015, 2016, 2017, 2018, 2019
|
||||
University Corporation for Atmospheric Research/Unidata.
|
||||
|
||||
See \ref copyright file for more info.
|
||||
@ -1760,19 +1760,17 @@ nc_show_metadata(int ncid);
|
||||
|
||||
/* End {put,get}_var */
|
||||
|
||||
/* #ifdef _CRAYMPP */
|
||||
/* Delete a file. */
|
||||
EXTERNL int
|
||||
nc_delete(const char *path);
|
||||
|
||||
/*
|
||||
* Public interfaces to better support
|
||||
* CRAY multi-processor systems like T3E.
|
||||
* A tip of the hat to NERSC.
|
||||
*/
|
||||
/*
|
||||
* It turns out we need to declare and define
|
||||
* these public interfaces on all platforms
|
||||
* or things get ugly working out the
|
||||
* FORTRAN interface. On !_CRAYMPP platforms,
|
||||
* these functions work as advertised, but you
|
||||
* can only use "processor element" 0.
|
||||
* The following functions were written to accomodate the old Cray
|
||||
* systems. Modern HPC systems do not use these functions any more,
|
||||
* but use the nc_open_par()/nc_create_par() functions instead. These
|
||||
* functions are retained for backward compatibibility. These
|
||||
* functions work as advertised, but you can only use "processor
|
||||
* element" 0.
|
||||
*/
|
||||
|
||||
EXTERNL int
|
||||
@ -1783,9 +1781,6 @@ EXTERNL int
|
||||
nc__open_mp(const char *path, int mode, int basepe,
|
||||
size_t *chunksizehintp, int *ncidp);
|
||||
|
||||
EXTERNL int
|
||||
nc_delete(const char *path);
|
||||
|
||||
EXTERNL int
|
||||
nc_delete_mp(const char *path, int basepe);
|
||||
|
||||
@ -1795,8 +1790,6 @@ nc_set_base_pe(int ncid, int pe);
|
||||
EXTERNL int
|
||||
nc_inq_base_pe(int ncid, int *pe);
|
||||
|
||||
/* #endif _CRAYMPP */
|
||||
|
||||
/* This v2 function is used in the nc_test program. */
|
||||
EXTERNL int
|
||||
nctypelen(nc_type datatype);
|
||||
|
107
libdispatch/nc.c
107
libdispatch/nc.c
@ -1,31 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018, University Corporation for Atmospheric Research
|
||||
* Copyright 2018, University Corporation for Atmospheric Research
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @internal
|
||||
*
|
||||
* This file contains functions that work with the NC struct. There is
|
||||
* an NC struct for every open netCDF file.
|
||||
*
|
||||
* @author Glenn Davis
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#if defined(LOCKNUMREC) /* && _CRAYMPP */
|
||||
# include <mpp/shmem.h>
|
||||
# include <intrinsics.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ncdispatch.h"
|
||||
|
||||
/* This is the default create format for nc_create and nc__create. */
|
||||
/** This is the default create format for nc_create and nc__create. */
|
||||
static int default_create_format = NC_FORMAT_CLASSIC;
|
||||
|
||||
/* These have to do with version numbers. */
|
||||
#define MAGIC_NUM_LEN 4
|
||||
#define VER_CLASSIC 1
|
||||
#define VER_64BIT_OFFSET 2
|
||||
#define VER_HDF5 3
|
||||
|
||||
/**
|
||||
* Find the NC struct for an open file, using the ncid.
|
||||
*
|
||||
* @param ncid The ncid to find.
|
||||
* @param ncpp Pointer that gets a pointer to the NC.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EBADID ncid not found.
|
||||
* @author Glenn Davis, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
NC_check_id(int ncid, NC** ncpp)
|
||||
{
|
||||
@ -35,25 +43,45 @@ NC_check_id(int ncid, NC** ncpp)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an NC struct and its related resources. Before this is done,
|
||||
* be sure to remove the NC from the open file list with
|
||||
* del_from_NCList().
|
||||
*
|
||||
* @param ncp Pointer to the NC struct to be freed.
|
||||
*
|
||||
* @author Glenn Davis, Dennis Heimbigner
|
||||
*/
|
||||
void
|
||||
free_NC(NC *ncp)
|
||||
{
|
||||
if(ncp == NULL)
|
||||
return;
|
||||
return;
|
||||
if(ncp->path)
|
||||
free(ncp->path);
|
||||
free(ncp->path);
|
||||
if(ncp->model)
|
||||
free(ncp->model);
|
||||
free(ncp->model);
|
||||
/* We assume caller has already cleaned up ncp->dispatchdata */
|
||||
#if _CRAYMPP && defined(LOCKNUMREC)
|
||||
shfree(ncp);
|
||||
#else
|
||||
free(ncp);
|
||||
#endif /* _CRAYMPP && LOCKNUMREC */
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and initialize a new NC struct. The ncid is assigned later.
|
||||
*
|
||||
* @param dispatcher
|
||||
* @param path The name of the file.
|
||||
* @param mode The open or create mode.
|
||||
* @param model
|
||||
* @param ncpp A pointer that gets a pointer to the newlly allocacted
|
||||
* and initialized NC struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_ENOMEM Out of memory.
|
||||
* @author Glenn Davis, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
new_NC(const NC_Dispatch* dispatcher, const char* path, int mode, NCmodel* model, NC** ncpp)
|
||||
new_NC(const NC_Dispatch* dispatcher, const char* path, int mode,
|
||||
NCmodel* model, NC** ncpp)
|
||||
{
|
||||
NC *ncp = (NC*)calloc(1,sizeof(NC));
|
||||
if(ncp == NULL) return NC_ENOMEM;
|
||||
@ -61,31 +89,40 @@ new_NC(const NC_Dispatch* dispatcher, const char* path, int mode, NCmodel* model
|
||||
ncp->path = nulldup(path);
|
||||
ncp->mode = mode;
|
||||
if((ncp->model = malloc(sizeof(NCmodel)))==NULL)
|
||||
return NC_ENOMEM;
|
||||
return NC_ENOMEM;
|
||||
*ncp->model = *model; /* Make a copy */
|
||||
if(ncp->path == NULL) { /* fail */
|
||||
free_NC(ncp);
|
||||
return NC_ENOMEM;
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if(ncpp) {
|
||||
*ncpp = ncp;
|
||||
*ncpp = ncp;
|
||||
} else {
|
||||
free_NC(ncp);
|
||||
free_NC(ncp);
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/* This function sets a default create flag that will be logically
|
||||
or'd to whatever flags are passed into nc_create for all future
|
||||
calls to nc_create.
|
||||
Valid default create flags are NC_64BIT_OFFSET, NC_CLOBBER,
|
||||
NC_LOCK, NC_SHARE. */
|
||||
/**
|
||||
* This function sets a default create flag that will be logically
|
||||
* or'd to whatever flags are passed into nc_create for all future
|
||||
* calls to nc_create.
|
||||
*
|
||||
* @param format The format that should become the default.
|
||||
* @param old_formatp Pointer that gets the previous default. Ignored
|
||||
* if NULL.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_ENOTBUILD Requested format not built with this install.
|
||||
* @return ::NC_EINVAL Invalid input.
|
||||
* @author Ed Hartnett, Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
nc_set_default_format(int format, int *old_formatp)
|
||||
{
|
||||
/* Return existing format if desired. */
|
||||
if (old_formatp)
|
||||
*old_formatp = default_create_format;
|
||||
*old_formatp = default_create_format;
|
||||
|
||||
/* Make sure only valid format is set. */
|
||||
#ifndef ENABLE_CDF5
|
||||
@ -95,7 +132,7 @@ nc_set_default_format(int format, int *old_formatp)
|
||||
#ifdef USE_HDF5
|
||||
if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT_OFFSET &&
|
||||
format != NC_FORMAT_NETCDF4 && format != NC_FORMAT_NETCDF4_CLASSIC &&
|
||||
format != NC_FORMAT_CDF5)
|
||||
format != NC_FORMAT_CDF5)
|
||||
return NC_EINVAL;
|
||||
#else
|
||||
if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_NETCDF4_CLASSIC)
|
||||
@ -108,6 +145,12 @@ nc_set_default_format(int format, int *old_formatp)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current default format.
|
||||
*
|
||||
* @return the default format.
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
int
|
||||
nc_get_default_format(void)
|
||||
{
|
||||
|
@ -1,7 +1,15 @@
|
||||
/*********************************************************************
|
||||
Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for
|
||||
copying and redistribution conditions.
|
||||
*********************************************************************/
|
||||
*********************************************************************/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Functions to manage the list of NC structs. There is one NC struct
|
||||
* for each open file.
|
||||
*
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
@ -9,22 +17,40 @@
|
||||
#include <assert.h>
|
||||
#include "ncdispatch.h"
|
||||
|
||||
/** This shift is applied to the ext_ncid in order to get the index in
|
||||
* the array of NC. */
|
||||
#define ID_SHIFT (16)
|
||||
|
||||
/** This is the length of the NC list - the number of files that can
|
||||
* be open at one time. We use 2^16 = 65536 entries in the array, but
|
||||
* slot 0 is not used, so only 65535 files may be open at one
|
||||
* time. */
|
||||
#define NCFILELISTLENGTH 0x10000
|
||||
|
||||
/* Version one just allocates the max space (sizeof(NC*)*2^16)*/
|
||||
/** This is the pointer to the array of NC, one for each open file. */
|
||||
static NC** nc_filelist = NULL;
|
||||
|
||||
/** The number of files currently open. */
|
||||
static int numfiles = 0;
|
||||
|
||||
/* Common */
|
||||
/**
|
||||
* How many files are currently open?
|
||||
*
|
||||
* @return number of open files.
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
count_NCList(void)
|
||||
{
|
||||
return numfiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free an empty NCList. @note If list is not empty, or has not been
|
||||
* allocated, function will silently exit.
|
||||
*
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
void
|
||||
free_NCList(void)
|
||||
{
|
||||
@ -33,86 +59,156 @@ free_NCList(void)
|
||||
nc_filelist = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an already-allocated NC to the list. It will be assigned an
|
||||
* ncid in this function.
|
||||
*
|
||||
* If this is the first file to be opened, the nc_filelist will be
|
||||
* allocated and set to all 0.
|
||||
*
|
||||
* The ncid is assigned by finding the first open index in the
|
||||
* nc_filelist array (skipping index 0). The ncid is this index
|
||||
* left-shifted ID_SHIFT bits (16). This puts the file ID in the first
|
||||
* two bytes of the 4-byte integer, and leaves the last two bytes for
|
||||
* group IDs for netCDF-4 files.
|
||||
*
|
||||
* @param ncp Pointer to already-allocated and initialized NC struct.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_ENOMEM Out of memory.
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
add_to_NCList(NC* ncp)
|
||||
{
|
||||
int i;
|
||||
int new_id;
|
||||
if(nc_filelist == NULL) {
|
||||
if (!(nc_filelist = calloc(1, sizeof(NC*)*NCFILELISTLENGTH)))
|
||||
return NC_ENOMEM;
|
||||
numfiles = 0;
|
||||
if (!(nc_filelist = calloc(1, sizeof(NC*)*NCFILELISTLENGTH)))
|
||||
return NC_ENOMEM;
|
||||
numfiles = 0;
|
||||
}
|
||||
|
||||
new_id = 0; /* id's begin at 1 */
|
||||
for(i=1; i < NCFILELISTLENGTH; i++) {
|
||||
if(nc_filelist[i] == NULL) {new_id = i; break;}
|
||||
if(nc_filelist[i] == NULL) {new_id = i; break;}
|
||||
}
|
||||
if(new_id == 0) return NC_ENOMEM; /* no more slots */
|
||||
nc_filelist[new_id] = ncp;
|
||||
numfiles++;
|
||||
new_id = (new_id << ID_SHIFT);
|
||||
ncp->ext_ncid = new_id;
|
||||
ncp->ext_ncid = (new_id << ID_SHIFT);
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an NC struct from the list. This happens when the file is
|
||||
* closed. Relies on all memory in the NC being deallocated after this
|
||||
* function with freeNC().
|
||||
*
|
||||
* @note If the file list is empty, or this NC can't be found in the
|
||||
* list, this function will silently exit.
|
||||
*
|
||||
* @param ncp Pointer to NC to be removed from list.
|
||||
*
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
void
|
||||
del_from_NCList(NC* ncp)
|
||||
{
|
||||
unsigned int ncid = ((unsigned int)ncp->ext_ncid) >> ID_SHIFT;
|
||||
if(numfiles == 0 || ncid == 0 || nc_filelist == NULL) return;
|
||||
if(nc_filelist[ncid] != ncp) return;
|
||||
unsigned int ncid = ((unsigned int)ncp->ext_ncid) >> ID_SHIFT;
|
||||
if(numfiles == 0 || ncid == 0 || nc_filelist == NULL) return;
|
||||
if(nc_filelist[ncid] != ncp) return;
|
||||
|
||||
nc_filelist[ncid] = NULL;
|
||||
numfiles--;
|
||||
nc_filelist[ncid] = NULL;
|
||||
numfiles--;
|
||||
|
||||
/* If all files have been closed, release the filelist memory. */
|
||||
if (numfiles == 0)
|
||||
free_NCList();
|
||||
/* If all files have been closed, release the filelist memory. */
|
||||
if (numfiles == 0)
|
||||
free_NCList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an NC in the list, given an ext_ncid. The NC list is indexed
|
||||
* with the first two bytes of ext_ncid. (The last two bytes specify
|
||||
* the group for netCDF4 files, or are zeros for classic files.)
|
||||
*
|
||||
* @param ext_ncid The ncid of the file to find.
|
||||
*
|
||||
* @return pointer to NC or NULL if not found.
|
||||
* @author Dennis Heimbigner, Ed Hartnett
|
||||
*/
|
||||
NC *
|
||||
find_in_NCList(int ext_ncid)
|
||||
{
|
||||
NC* f = NULL;
|
||||
unsigned int ncid = ((unsigned int)ext_ncid) >> ID_SHIFT;
|
||||
if(numfiles > 0 && nc_filelist != NULL && ncid < NCFILELISTLENGTH)
|
||||
f = nc_filelist[ncid];
|
||||
NC* f = NULL;
|
||||
/* Discard the first two bytes of ext_ncid to get ncid. */
|
||||
unsigned int ncid = ((unsigned int)ext_ncid) >> ID_SHIFT;
|
||||
|
||||
/* for classic files, ext_ncid must be a multiple of (1<<ID_SHIFT) */
|
||||
if (f != NULL && f->model->impl == NC_FORMATX_NC3 && (ext_ncid % (1<<ID_SHIFT)))
|
||||
return NULL;
|
||||
/* If we have a filelist, there will be an entry, possibly NULL,
|
||||
* for this ncid. */
|
||||
if (nc_filelist)
|
||||
{
|
||||
assert(numfiles);
|
||||
f = nc_filelist[ncid];
|
||||
}
|
||||
|
||||
return f;
|
||||
/* For classic files, ext_ncid must be a multiple of
|
||||
* (1<<ID_SHIFT). That is, the group part of the ext_ncid (the
|
||||
* last two bytes) must be zero. If not, then return NULL, which
|
||||
* will eventually lead to an NC_EBADID error being returned to
|
||||
* user. */
|
||||
if (f != NULL && f->model->impl == NC_FORMATX_NC3 && (ext_ncid % (1<<ID_SHIFT)))
|
||||
return NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
Added to support open by name
|
||||
*/
|
||||
/**
|
||||
* Find an NC in the list using the file name.
|
||||
*
|
||||
* @param path Name of the file.
|
||||
*
|
||||
* @return pointer to NC or NULL if not found.
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
NC*
|
||||
find_in_NCList_by_name(const char* path)
|
||||
{
|
||||
int i;
|
||||
NC* f = NULL;
|
||||
if(nc_filelist == NULL)
|
||||
return NULL;
|
||||
for(i=1; i < NCFILELISTLENGTH; i++) {
|
||||
if(nc_filelist[i] != NULL) {
|
||||
if(strcmp(nc_filelist[i]->path,path)==0) {
|
||||
f = nc_filelist[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return f;
|
||||
int i;
|
||||
NC* f = NULL;
|
||||
if(nc_filelist == NULL)
|
||||
return NULL;
|
||||
for(i=1; i < NCFILELISTLENGTH; i++) {
|
||||
if(nc_filelist[i] != NULL) {
|
||||
if(strcmp(nc_filelist[i]->path,path)==0) {
|
||||
f = nc_filelist[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an NC in list based on its index. The index is ((unsigned
|
||||
* int)ext_ncid) >> ID_SHIFT. This is the two high bytes of the
|
||||
* ext_ncid. (The other two bytes are used for the group ID for
|
||||
* netCDF-4 files.)
|
||||
*
|
||||
* @param index The index in the NC list.
|
||||
* @param ncp Pointer that gets pointer to the next NC. Igored if
|
||||
* NULL.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_ERANGE Index out of range.
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
iterate_NCList(int index, NC** ncp)
|
||||
{
|
||||
/* Walk from 0 ...; 0 return => stop */
|
||||
if(index < 0 || index >= NCFILELISTLENGTH)
|
||||
return NC_ERANGE;
|
||||
return NC_ERANGE;
|
||||
if(ncp) *ncp = nc_filelist[index];
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
@ -10,10 +10,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#if defined(LOCKNUMREC) /* && _CRAYMPP */
|
||||
# include <mpp/shmem.h>
|
||||
# include <intrinsics.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -47,11 +43,7 @@ free_NC3INFO(NC3_INFO *nc3)
|
||||
free_NC_dimarrayV(&nc3->dims);
|
||||
free_NC_attrarrayV(&nc3->attrs);
|
||||
free_NC_vararrayV(&nc3->vars);
|
||||
#if _CRAYMPP && defined(LOCKNUMREC)
|
||||
shfree(nc3);
|
||||
#else
|
||||
free(nc3);
|
||||
#endif /* _CRAYMPP && LOCKNUMREC */
|
||||
}
|
||||
|
||||
static NC3_INFO *
|
||||
@ -948,21 +940,6 @@ NC_endef(NC3_INFO *ncp,
|
||||
return ncio_sync(ncp->nciop);
|
||||
}
|
||||
|
||||
#ifdef LOCKNUMREC
|
||||
static int
|
||||
NC_init_pe(NC *ncp, int basepe) {
|
||||
if (basepe < 0 || basepe >= _num_pes()) {
|
||||
return NC_EINVAL; /* invalid base pe */
|
||||
}
|
||||
/* initialize common values */
|
||||
ncp->lock[LOCKNUMREC_VALUE] = 0;
|
||||
ncp->lock[LOCKNUMREC_LOCK] = 0;
|
||||
ncp->lock[LOCKNUMREC_SERVING] = 0;
|
||||
ncp->lock[LOCKNUMREC_BASEPE] = basepe;
|
||||
return NC_NOERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Compute the expected size of the file.
|
||||
@ -1017,11 +994,7 @@ int NC3_new_nc(NC3_INFO** ncpp)
|
||||
NC *nc;
|
||||
NC3_INFO* nc3;
|
||||
|
||||
#if _CRAYMPP && defined(LOCKNUMREC)
|
||||
ncp = (NC *) shmalloc(sizeof(NC));
|
||||
#else
|
||||
ncp = (NC *) malloc(sizeof(NC));
|
||||
#endif /* _CRAYMPP && LOCKNUMREC */
|
||||
if(ncp == NULL)
|
||||
return NC_ENOMEM;
|
||||
(void) memset(ncp, 0, sizeof(NC));
|
||||
@ -1058,20 +1031,13 @@ NC3_create(const char *path, int ioflags, size_t initialsz, int basepe,
|
||||
fSet(ioflags, NC_SHARE);
|
||||
#endif
|
||||
|
||||
#if defined(LOCKNUMREC) /* && _CRAYMPP */
|
||||
if (status = NC_init_pe(nc3, basepe)) {
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* !_CRAYMPP, only pe 0 is valid
|
||||
* Only pe 0 is valid
|
||||
*/
|
||||
if(basepe != 0) {
|
||||
if(nc3) free(nc3);
|
||||
return NC_EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(nc3) free(nc3);
|
||||
return NC_EINVAL;
|
||||
}
|
||||
assert(nc3->flags == 0);
|
||||
|
||||
/* Now we can set min size */
|
||||
@ -1193,23 +1159,17 @@ NC3_open(const char *path, int ioflags, int basepe, size_t *chunksizehintp,
|
||||
fSet(ioflags, NC_SHARE);
|
||||
#endif
|
||||
|
||||
#if defined(LOCKNUMREC) /* && _CRAYMPP */
|
||||
if (status = NC_init_pe(nc3, basepe)) {
|
||||
goto unwind_alloc;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* !_CRAYMPP, only pe 0 is valid
|
||||
* Only pe 0 is valid.
|
||||
*/
|
||||
if(basepe != 0) {
|
||||
if(nc3) {
|
||||
free(nc3);
|
||||
nc3 = NULL;
|
||||
}
|
||||
status = NC_EINVAL;
|
||||
goto unwind_alloc;
|
||||
}
|
||||
#endif
|
||||
if(nc3) {
|
||||
free(nc3);
|
||||
nc3 = NULL;
|
||||
}
|
||||
status = NC_EINVAL;
|
||||
goto unwind_alloc;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BYTERANGE
|
||||
/* If the model specified the use of byte-ranges, then signal by
|
||||
@ -1577,37 +1537,6 @@ NC3_set_fill(int ncid,
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
#ifdef LOCKNUMREC
|
||||
|
||||
/* create function versions of the NC_*_numrecs macros */
|
||||
size_t
|
||||
NC_get_numrecs(const NC *nc3) {
|
||||
shmem_t numrec;
|
||||
shmem_short_get(&numrec, (shmem_t *) nc3->lock + LOCKNUMREC_VALUE, 1,
|
||||
nc3->lock[LOCKNUMREC_BASEPE]);
|
||||
return (size_t) numrec;
|
||||
}
|
||||
|
||||
void
|
||||
NC_set_numrecs(NC *nc3, size_t nrecs)
|
||||
{
|
||||
shmem_t numrec = (shmem_t) nrecs;
|
||||
/* update local value too */
|
||||
nc3->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrec;
|
||||
shmem_short_put((shmem_t *) nc3->lock + LOCKNUMREC_VALUE, &numrec, 1,
|
||||
nc3->lock[LOCKNUMREC_BASEPE]);
|
||||
}
|
||||
|
||||
void NC_increase_numrecs(NC *nc3, size_t nrecs)
|
||||
{
|
||||
/* this is only called in one place that's already protected
|
||||
* by a lock ... so don't worry about it */
|
||||
if (nrecs > NC_get_numrecs(nc3))
|
||||
NC_set_numrecs(nc3, nrecs);
|
||||
}
|
||||
|
||||
#endif /* LOCKNUMREC */
|
||||
|
||||
/**
|
||||
* Return the file format.
|
||||
*
|
||||
@ -1719,7 +1648,18 @@ NC3_inq_type(int ncid, nc_type typeid, char *name, size_t *size)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/**
|
||||
* This is an obsolete form of nc_delete(), supported for backwards
|
||||
* compatibility.
|
||||
*
|
||||
* @param path Filename to delete.
|
||||
* @param basepe Must be 0.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EIO Couldn't delete file.
|
||||
* @return ::NC_EINVAL Invaliod basepe. Must be 0.
|
||||
* @author Glenn Davis, Ed Hartnett
|
||||
*/
|
||||
int
|
||||
nc_delete_mp(const char * path, int basepe)
|
||||
{
|
||||
@ -1733,17 +1673,11 @@ nc_delete_mp(const char * path, int basepe)
|
||||
status = NC_check_id(ncid,&nc);
|
||||
if(status) return status;
|
||||
|
||||
#if defined(LOCKNUMREC) /* && _CRAYMPP */
|
||||
if (status = NC_init_pe(nc3, basepe)) {
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* !_CRAYMPP, only pe 0 is valid
|
||||
* Only pe 0 is valid.
|
||||
*/
|
||||
if(basepe != 0)
|
||||
return NC_EINVAL;
|
||||
#endif
|
||||
|
||||
(void) nc_close(ncid);
|
||||
if(unlink(path) == -1) {
|
||||
|
@ -28,13 +28,6 @@ dnl
|
||||
#include "ncx.h"
|
||||
#include "fbits.h"
|
||||
#include "onstack.h"
|
||||
#ifdef LOCKNUMREC
|
||||
# include <mpp/shmem.h> /* for SGI/Cray SHMEM routines */
|
||||
# ifdef LN_TEST
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#undef MIN /* system may define MIN somewhere and complain */
|
||||
#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
|
||||
@ -403,40 +396,6 @@ static int
|
||||
NCvnrecs(NC3_INFO* ncp, size_t numrecs)
|
||||
{
|
||||
int status = NC_NOERR;
|
||||
#ifdef LOCKNUMREC
|
||||
ushmem_t myticket = 0, nowserving = 0;
|
||||
ushmem_t numpe = (ushmem_t) _num_pes();
|
||||
|
||||
/* get ticket and wait */
|
||||
myticket = shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
|
||||
ncp->lock[LOCKNUMREC_BASEPE]);
|
||||
#ifdef LN_TEST
|
||||
fprintf(stderr,"%d of %d : ticket = %hu\n",
|
||||
_my_pe(), _num_pes(), myticket);
|
||||
#endif
|
||||
do {
|
||||
shmem_short_get((shmem_t *) &nowserving,
|
||||
(shmem_t *) ncp->lock + LOCKNUMREC_SERVING, 1,
|
||||
ncp->lock[LOCKNUMREC_BASEPE]);
|
||||
#ifdef LN_TEST
|
||||
fprintf(stderr,"%d of %d : serving = %hu\n",
|
||||
_my_pe(), _num_pes(), nowserving);
|
||||
#endif
|
||||
/* work-around for non-unique tickets */
|
||||
if (nowserving > myticket && nowserving < myticket + numpe ) {
|
||||
/* get a new ticket ... you've been bypassed */
|
||||
/* and handle the unlikely wrap-around effect */
|
||||
myticket = shmem_short_finc(
|
||||
(shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
|
||||
ncp->lock[LOCKNUMREC_BASEPE]);
|
||||
#ifdef LN_TEST
|
||||
fprintf(stderr,"%d of %d : new ticket = %hu\n",
|
||||
_my_pe(), _num_pes(), myticket);
|
||||
#endif
|
||||
}
|
||||
} while(nowserving != myticket);
|
||||
/* now our turn to check & update value */
|
||||
#endif
|
||||
|
||||
if(numrecs > NC_get_numrecs(ncp))
|
||||
{
|
||||
@ -519,11 +478,6 @@ NCvnrecs(NC3_INFO* ncp, size_t numrecs)
|
||||
|
||||
}
|
||||
common_return:
|
||||
#ifdef LOCKNUMREC
|
||||
/* finished with our lock - increment serving number */
|
||||
(void) shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
|
||||
ncp->lock[LOCKNUMREC_BASEPE]);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -244,11 +244,6 @@ main(
|
||||
#endif
|
||||
memset(&globalspecials,0,sizeof(GlobalSpecialData));
|
||||
|
||||
#if _CRAYMPP && 0
|
||||
/* initialize CRAY MPP parallel-I/O library */
|
||||
(void) par_io_init(32, 32);
|
||||
#endif
|
||||
|
||||
while ((c = getopt(argc, argv, "134567bB:cdD:fhHk:l:M:no:Pv:xL:N:")) != EOF)
|
||||
switch(c) {
|
||||
case 'd':
|
||||
|
@ -114,11 +114,6 @@ main(
|
||||
cmode_modifier = 0;
|
||||
nofill_flag = 0;
|
||||
|
||||
#if _CRAYMPP && 0
|
||||
/* initialize CRAY MPP parallel-I/O library */
|
||||
(void) par_io_init(32, 32);
|
||||
#endif
|
||||
|
||||
while ((c = getopt(argc, argv, "bcfk:l:no:v:x")) != EOF)
|
||||
switch(c) {
|
||||
case 'c': /* for c output, old version of "-lc" */
|
||||
|
21
unit_test/Makefile.am
Normal file
21
unit_test/Makefile.am
Normal file
@ -0,0 +1,21 @@
|
||||
## This is a automake file, part of Unidata's netCDF package.
|
||||
# Copyright 2019, see the COPYRIGHT file for more information.
|
||||
|
||||
# This file builds and runs the unit tests. These tests are not run in
|
||||
# the CMake build, because we would then have to extern these internal
|
||||
# functions, to allow Windows to work. Since we have not extern'd
|
||||
# these functions, they will only be run under the autotools build.
|
||||
|
||||
# Ed Hartnett 8/9/19
|
||||
|
||||
# Put together AM_CPPFLAGS and AM_LDFLAGS.
|
||||
include $(top_srcdir)/lib_flags.am
|
||||
|
||||
# Find and link to the netcdf-c library.
|
||||
LDADD = ${top_builddir}/liblib/libnetcdf.la
|
||||
|
||||
check_PROGRAMS = tst_nclist
|
||||
TESTS = tst_nclist
|
||||
|
||||
# If valgrind is present, add valgrind targets.
|
||||
@VALGRIND_CHECK_RULES@
|
110
unit_test/tst_nclist.c
Normal file
110
unit_test/tst_nclist.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* This is part of the netCDF package. Copyright 2005-2019 University
|
||||
Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
|
||||
for conditions of use.
|
||||
|
||||
Test list functions in nclistmgr.c.
|
||||
|
||||
Ed Hartnett, 8/10/19
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <nc_tests.h>
|
||||
#include "nc.h"
|
||||
#include "ncdispatch.h"
|
||||
#include "err_macros.h"
|
||||
|
||||
/* An integer value to use in testing. */
|
||||
#define TEST_VAL_42 42
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
printf("\n*** Testing netcdf internal NC list functions.\n");
|
||||
printf("Testing NC list functions with no open files...");
|
||||
{
|
||||
/* These are cases where there are no files, or NULL
|
||||
* params. */
|
||||
if (count_NCList()) ERR;
|
||||
free_NCList();
|
||||
if (find_in_NCList_by_name("nope")) ERR;
|
||||
if (iterate_NCList(0, NULL)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
printf("Testing adding to NC list...");
|
||||
{
|
||||
int ncid;
|
||||
NC *ncp, *ncp2;
|
||||
int mode = 0;
|
||||
NCmodel model;
|
||||
char path[] = {"file.nc"};
|
||||
int ret;
|
||||
|
||||
/* Create the NC* instance and insert its dispatcher and model. */
|
||||
if ((ret = new_NC(NULL, path, mode, &model, &ncp))) ERR;
|
||||
|
||||
/* Nothing to find yet. */
|
||||
if (find_in_NCList(TEST_VAL_42)) ERR;
|
||||
|
||||
/* Add to list of known open files and define ext_ncid. */
|
||||
add_to_NCList(ncp);
|
||||
|
||||
/* These won't work! */
|
||||
if (find_in_NCList(TEST_VAL_42)) ERR;
|
||||
if (find_in_NCList_by_name("nope")) ERR;
|
||||
if ((ret = iterate_NCList(2, &ncp2))) ERR;
|
||||
|
||||
/* Find it in the list. */
|
||||
if (!(ncp2 = find_in_NCList(ncp->ext_ncid))) ERR;
|
||||
if (!(ncp2 = find_in_NCList_by_name(path))) ERR;
|
||||
if ((ret = iterate_NCList(1, &ncp2))) ERR;
|
||||
if (count_NCList() != 1) ERR;
|
||||
|
||||
/* Won't do anything because list contains an entry. */
|
||||
free_NCList();
|
||||
|
||||
/* Delete it. */
|
||||
ncid = ncp->ext_ncid;
|
||||
del_from_NCList(ncp); /* Will free empty list. */
|
||||
free_NC(ncp);
|
||||
if (find_in_NCList(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
#ifdef LARGE_FILE_TESTS
|
||||
/* This test is slow, only run it on large file test builds. */
|
||||
printf("Testing maxing out NC list...");
|
||||
{
|
||||
NC *ncp;
|
||||
int mode = 0;
|
||||
NCmodel model;
|
||||
char path[] = {"file.nc"};
|
||||
int max_num_nc = 65535;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
/* Fill the NC list. */
|
||||
for (i = 0; i < max_num_nc; i++)
|
||||
{
|
||||
if ((ret = new_NC(NULL, path, mode, &model, &ncp))) ERR;
|
||||
if (add_to_NCList(ncp)) ERR;
|
||||
}
|
||||
|
||||
/* Check the count. */
|
||||
if (count_NCList() != max_num_nc) ERR;
|
||||
|
||||
/* Try and add another. It will fail. */
|
||||
if (add_to_NCList(ncp) != NC_ENOMEM) ERR;
|
||||
|
||||
/* Delete them all. */
|
||||
for (i = 0; i < max_num_nc; i++)
|
||||
{
|
||||
if (iterate_NCList(i + 1, &ncp)) ERR;
|
||||
if (!ncp) ERR;
|
||||
del_from_NCList(ncp);
|
||||
free_NC(ncp);
|
||||
}
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
#endif /* LARGE_FILE_TESTS */
|
||||
|
||||
FINAL_RESULTS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user