Skip to content

Commit

Permalink
Extend the netcdf API to support programmatic changes to the plugin s…
Browse files Browse the repository at this point in the history
…earch path

Replaces PR Unidata#3024
         and PR Unidata#3033

re: Unidata#2753

As suggested by Ed Hartnett, This PR extends the netcdf.h API to support programmatic control over the search path used to locate plugins.

I created several different APIs, but finally settled on the following API as being the simplest possible. It does have the disadvantage that it requires use of a global lock (not implemented) if used in a threaded environment.

Specifically, note that modifying the plugin path must be done "atomically". That is, in a multi-threaded environment, it is important that the sequence of actions involved in setting up the plugin path must be done by a single processor or in some other way as to guarantee that two or more processors are not simultaneously accessing the plugin path get/set operations.

As an example, assume there exists a mutex lock called PLUGINLOCK. Then any processor accessing the plugin paths should operate as follows:
````
lock(PLUGINLOCK);
nc_plugin_path_get(...);
<rebuild plugin path>
nc_plugin_path_set(...);
unlock(PLUGINLOCK);
````
## Internal Architecture

It is assumed here that there only needs to be a single set of plugin path directories that is shared by all filter code and is independent of any file descriptor; it is global in other words. This means, for example, that the path list for NCZarr and for HDF5 will always be the same.

However internally, processing the set of plugin paths depends on the particular NC_FORMATX value (NC_FORMATX_NC_HDF5 and NC_FORMATX_NCZARR, currently). So the *nc_plugin_path_set* function, will take the paths it is given and propagate them to each of the NC_FORMATX dispatchers to store in a way that is appropriate to the given dispatcher.

There is a complication with respect to the *nc_plugin_path_get* function. It is possible for users to bypass the netcdf API and modify the HDF5 plugin paths directly. This can result in an inconsistent plugin path between the value used by HDF5 and the global value used by netcdf-c. Since there is no obvious fix for this, we warn the user of this possibility and otherwise ignore it.

## Test Changes
* New tests<br>
    a. unit_test/run_pluginpaths.sh -- was created to test this new capability.<br>
    b. A new test utility has been added as *unit_test/run_dfaltpluginpath.sh* to test the default plugin path list.
* New test support utilities<br>
    a. unit_test/ncpluginpath.c -- report current state of the plugin path<br>
    b. unit_test/tst_pluginpaths.c -- test program to support run_pluginpaths.sh

## Documentation
* A new file -- docs/pluginpath.md -- provides documentation of the new API. It includes some
  material taken fro filters.md.

## Other Major Changes
1. Cleanup the whole plugin path decision tree. This is described in the *docs/pluginpath.md* document and summarized in Addendum 2 below.
2. I noticed that the ncdump/testpathcvt.sh had been disabled, so fixed and re-enabled it. This necessitated some significant changes to dpathmgr.c.

## Misc. Changes
1. Add some path manipulation utilities to netcf_aux.h
2. Fix some minor bugs in netcdf_json.h
3. Convert netcdf_json.h and netcdf_proplist.h to BUILT_SOURCE.
4. Add NETCDF_ENABLE_HDF5 as synonym for USE_HDF5
5. Fix some size_t <-> int conversion warnings.
6. Encountered and fixed the Windows \r\n problem in tst_pluginpaths.c.
7. Cleanup some minor CMakeLists.txt problems.
8. Provide an implementation of echo -n since it appears to not be
   available on all platforms.
9. Add a property list mechanism to pass environmental information to filters.
10. Cleanup Doxyfile.in
11. Fixed a memory leak in libdap2; surprised that I did not find this earlier.

## Addendum 1: Proposed API

The API makes use of a counted vector of strings representing the sequence of directories in the path. The relevant type definition is as follows.
````
typedef struct NCPluginList {size_t ndirs; char** dirs;} NCPluginList;
````

The API proposed in this PR looks like this (from netcdf-c/include/netcdf_filter.h).

* ````int nc_plugin_path_ndirs(size_t* ndirsp);````
    Arguments: *ndirsp* -- store the number of directories in this memory.

    This function returns the number of directories in the sequence if internal directories of the internal plugin path list.

* ````int nc_plugin_path_get(NCPluginList* dirs);````
    Arguments:  *dirs* -- counted vector for storing the sequence of directies in the internal path list.

    This function returns the current sequence of directories from the internal plugin path list. Since this function does not modify the plugin path, it does not need to be locked; it is only when used to get the path to be modified that locking is required.  If the value of *dirs.dirs* is NULL (the normal case), then memory is allocated to hold the vector of directories. Otherwise, use the memory of *dirs.dirs* to hold the vector of directories.

* ````int nc_plugin_path_set(const NCPluginList* dirs);````
    Arguments: *dirs* -- counted vector for providing the new sequence of directories in the internal path list.

    This function empties the current internal path sequence and replaces it with the sequence of directories argument. Using an *ndirs* argument of 0 will clear the set of plugin paths.

## Addendum 2: Build-Time and Run-Time Constants.

### Build-Time Constants
<table style="border:2px solid black;border-collapse:collapse">
<tr style="outline: thin solid;" align="center"><td colspan="4">Table showing the build-time computation of NETCDF_PLUGIN_INSTALL_DIR and NETCDF_PLUGIN_SEARCH_PATH.</td>
<tr style="outline: thin solid" ><th>--with-plugin-dir<th>--prefix<th>NETCDF_PLUGIN_INSTALL_DIR<th>NETCDF_PLUGIN_SEARCH_PATH
<tr style="outline: thin solid" ><td>undefined<td>undefined<td>undefined<td>PLATFORMDEFALT
<tr style="outline: thin solid" ><td>undefined<td>&lt;abspath-prefix&gt;<td>&lt;abspath-prefix&gt;/hdf5/lib/plugin<td>&lt;abspath-prefix&gt;/hdf5/lib/plugin&lt;SEP&gt;PLATFORMDEFALT
<tr style="outline: thin solid" ><td>&lt;abspath-plugins&gt;<td>N.A.<td>&lt;abspath-plugins&gt;<td>&lt;abspath-plugins&gt;&lt;SEP&gt;PLATFORMDEFALT
</table>

<table style="border:2px solid black;border-collapse:collapse">
<tr style="outline: thin solid" align="center"><td colspan="2">Table showing the computation of the initial global plugin path</td>
<tr style="outline: thin solid"><th>HDF5_PLUGIN_PATH<th>Initial global plugin path
<tr style="outline: thin solid"><td>undefined<td>NETCDF_PLUGIN_SEARCH_PATH
<tr style="outline: thin solid"><td>&lt;path1;...pathn&gt;<td>&lt;path1;...pathn&gt;
</table>
  • Loading branch information
DennisHeimbigner committed Oct 19, 2024
1 parent 318eb36 commit efdec07
Show file tree
Hide file tree
Showing 26 changed files with 529 additions and 436 deletions.
130 changes: 50 additions & 80 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -626,93 +626,63 @@ option(NETCDF_ENABLE_FILTER_BZ2 "Enable use of Bz2 compression library if it i
option(NETCDF_ENABLE_FILTER_BLOSC "Enable use of blosc compression library if it is available." ON)
option(NETCDF_ENABLE_FILTER_ZSTD "Enable use of Zstd compression library if it is available." ON)

# If user wants, then install selected plugins (default on)
set(NETCDF_PLUGIN_INSTALL_DIR "YES" CACHE STRING "Whether and where we should install plugins; defaults to yes")
if(NOT NETCDF_ENABLE_PLUGINS)
unset(NETCDF_PLUGIN_INSTALL_DIR CACHE)
endif()

# This is ugly, but seems necessary because of CMake's boolean structure
set(boolval FALSE)
if(DEFINED NETCDF_PLUGIN_INSTALL_DIR)
booleanize(${NETCDF_PLUGIN_INSTALL_DIR} boolval)
if(boolval)
set(ENABLE_PLUGIN_INSTALL YES)
# No actual value was specified
unset(NETCDF_PLUGIN_INSTALL_DIR CACHE)
else()
if(boolval STREQUAL "NOTFOUND")
# Must be an actual value
set(ENABLE_PLUGIN_INSTALL YES)
else()
set(ENABLE_PLUGIN_INSTALL NO)
endif()
endif()
# If user wants, then install selected plugins (default off)
option(NETCDF_PLUGIN_INSTALL "Enable plugin installation" NO)

# Note: the term PLATFORMDEFAULT stands for:
# -- /usr/loca/hdf5/lib/plugin If on a *nix* machine
# -- %ALLUSERSPROFILE%/hdf5/lib/plugins If on a windows or Mingw platform
if(ISMSVC OR ISMINGW)
set(PLATFORMDEFAULT "$ENV{ALLUSERSPROFILE}\\hdf5\\lib\\plugin")
set(PLATFORMSEP ";")
else()
set(ENABLE_PLUGIN_INSTALL NO)
set(PLATFORMDEFAULT "/usr/local/hdf5/lib/plugin")
set(PLATFORMSEP ":")
endif()

# Ensure no defined plugin dir if not enabled
if(NOT ENABLE_PLUGIN_INSTALL)
unset(NETCDF_PLUGIN_INSTALL_DIR CACHE)
endif()
# Internally, the variable DEFAULT_PLUGIN_INSTALL_DIR is the default
# directory into which plugins are installed; this may be undefined if
# plugin installation is disabled (the usual case). It is exported as
# NETCDF_DEFAULT_PLUGIN_INSTALL_DIR.
#
# Similarly the variable DEFAULT_PLUGIN_SEARCH_PATH is the default list
# of directories to search to locate plugins.
#
# See configure.ac to see a table defining the rules for computing these two variables.

# Internally, the variable HDF5_PLUGIN_PATH
# is always used as a surrogate for the default
# plugin path. If it was not defined by the user,
# then set it internally.
if((NOT DEFINED HDF5_PLUGIN_PATH) OR ("${HDF5_PLUGIN_PATH}" STREQUAL ""))
if(ISMSVC OR ISMINGW)
string(REPLACE "\\" "/" AUP "$ENV{ALLUSERSPROFILE}")
set(HDF5_PLUGIN_PATH "${AUP}/hdf5/lib/plugin")
else()
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(HDF5_PLUGIN_PATH "/usr/local/hdf5/lib/plugin")
else()
set(HDF5_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/hdf5/lib/plugin")
endif(NOT DEFINED CMAKE_INSTALL_PREFIX)
endif()
set(ENV{HDF5_PLUGIN_PATH} "${HDF5_PLUGIN_PATH}")
endif()

# The --with-plugin-dir gives the user control of the plugin
# directory. If set to 'yes' (the default), then the last directory in
# HDF5_PLUGIN_PATH is used (see above).
# If a specific directory is provided, it will be used.
# If 'no', then plugins will not be installed.

if(NETCDF_ENABLE_PLUGIN_INSTALL)
if(DEFINED NETCDF_PLUGIN_INSTALL_DIR)
set(NETCDF_PLUGIN_INSTALL_DIR "${HDF5_PLUGIN_PATH}")
# Default to HDF5_PLUGIN_PATH or its default directories
if(DEFINED ENV{HDF5_PLUGIN_PATH})
set(NETCDF_PLUGIN_INSTALL_DIR "$ENV{HDF5_PLUGIN_PATH}")
else()
if(ISMSVC OR ISMINGW)
set(NETCDF_PLUGIN_INSTALL_DIR "$ENV{ALLUSERSPROFILE}\\hdf5\\lib\\plugin")
else()
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(NETCDF_PLUGIN_INSTALL_DIR "/usr/local/hdf5/lib/plugin")
else()
set(NETCDF_PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/hdf5/lib/plugin")
endif(NOT DEFINED CMAKE_INSTALL_PREFIX)
endif(ISMSVC OR ISMINGW)
endif(DEFINED ENV{HDF5_PLUGIN_PATH})
message(STATUS "Defaulting to -DPLUGIN_INSTALL_DIR=${NETCDF_PLUGIN_INSTALL_DIR}")
endif()
endif(NETCDF_ENABLE_PLUGIN_INSTALL)
# Inferences about plugins

if(ENABLE_PLUGIN_INSTALL)
# Use the lowest priority dir in the path
getlastdir("${HDF5_PLUGIN_PATH}" "NETCDF_PLUGIN_INSTALL_DIR")
message(STATUS "Final value of-DPLUGIN_INSTALL_DIR=${NETCDF_PLUGIN_INSTALL_DIR}")
else() # No option specified
unset(NETCDF_PLUGIN_INSTALL_DIR)
unset(NETCDF_PLUGIN_INSTALL_DIR CACHE)
set(PLUGIN_INSTALL_DIR_SETTING "N.A.")
if(NETCDF_WITH_PLUGIN_DIR)
set(NETCDF_ENABLE_PLUGINS yes)
endif()

message(STATUS "ENABLE_PLUGIN_INSTALL=${ENABLE_PLUGIN_INSTALL} PLUGIN_INSTALL_DIR=${NETCDF_PLUGIN_INSTALL_DIR}")
if(NOT NETCDF_ENABLE_PLUGINS)
unset(NETCDF_PLUGIN_INSTALL)
unset(NETCDF_WITH_PLUGIN_DIR)
endif()

if (DEFINED NETCDF_WITH_PLUGIN_DIR) # Table row 3
set(DEFAULT_PLUGIN_INSTALL_DIR "${NETCDF_WITH_PLUGIN_DIR}")
set(DEFAULT_PLUGIN_SEARCH_PATH "${NETCDF_WITH_PLUGIN_DIR}${PLATFORMSEP}${PLATFORMDEFAULT}")
elseif (DEFINED CMAKE_INSTALL_PREFIX) # Table row 2
set(DEFAULT_PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/hdf5/lib/plugin")
set(DEFAULT_PLUGIN_SEARCH_PATH "${DEFAULT_PLUGIN_INSTALL_DIR}${PLATFORMSEP}${PLATFORMDEFAULT}")
else() # Table row 1
unset(DEFAULT_PLUGIN_INSTALL_DIR)
set(DEFAULT_PLUGIN_SEARCH_PATH "${PLATFORMDEFAULT}")
endif()
# canonical form is all forward slashes
string(REPLACE "\\" "/" DEFAULT_PLUGIN_INSTALL_DIR "${DEFAULT_PLUGIN_INSTALL_DIR}")
string(REPLACE "\\" "/" DEFAULT_PLUGIN_SEARCH_PATH "${DEFAULT_PLUGIN_SEARCH_PATH}")

# Inferences
if (DEFINED DEFAULT_PLUGIN_INSTALL_DIR)
set(ENABLE_PLUGIN_DIR yes)
else()
set(ENABLE_PLUGIN_DIR no)
endif()
set(NETCDF_PLUGIN_INSTALL_DIR "${DEFAULT_PLUGIN_INSTALL_DIR}")
set(NETCDF_PLUGIN_SEARCH_PATH "${DEFAULT_PLUGIN_SEARCH_PATH}")

# Try to enable NCZarr zip support
option(NETCDF_ENABLE_NCZARR_ZIP "Enable NCZarr ZIP support." ${NETCDF_ENABLE_NCZARR})
Expand Down
9 changes: 3 additions & 6 deletions cmake/modules/FindBlosc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,14 @@ IF(Blosc_INCLUDE_DIRS)
GET_FILENAME_COMPONENT(Blosc_LIBRARY_DIRS ${Blosc_LIBRARY_DIRS} PATH)
ENDIF("${Blosc_LIBRARY_DIRS}" MATCHES "/include$")

IF(EXISTS "${Blosc_LIBRARY_DIRS}/lib")
SET(Blosc_LIBRARY_DIRS ${Blosc_LIBRARY_DIRS}/lib)
ENDIF(EXISTS "${Blosc_LIBRARY_DIRS}/lib")

# Find Blosc libraries
FIND_LIBRARY(Blosc_DEBUG_LIBRARY NAMES bloscd blosc_d libbloscd libblosc_d libblosc
PATH_SUFFIXES Debug ${CMAKE_LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_ARCHITECTURE}/Debug
PATHS ${Blosc_LIBRARY_DIRS} NO_DEFAULT_PATH)
PATHS ${Blosc_LIBRARY_DIRS} ${Blosc_LIBRARY_DIRS}/lib ${Blosc_LIBRARY_DIRS}/lib64 NO_DEFAULT_PATH)
FIND_LIBRARY(Blosc_RELEASE_LIBRARY NAMES blosc libblosc
PATH_SUFFIXES Release ${CMAKE_LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_ARCHITECTURE}/Release
PATHS ${Blosc_LIBRARY_DIRS} NO_DEFAULT_PATH)
PATHS ${Blosc_LIBRARY_DIRS} ${Blosc_LIBRARY_DIRS}/lib ${Blosc_LIBRARY_DIRS}/lib64 NO_DEFAULT_PATH)


SET(Blosc_LIBRARIES )
IF(Blosc_DEBUG_LIBRARY AND Blosc_RELEASE_LIBRARY)
Expand Down
8 changes: 2 additions & 6 deletions cmake/modules/FindSzip.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,13 @@ IF(Szip_INCLUDE_DIRS)
GET_FILENAME_COMPONENT(Szip_LIBRARY_DIRS ${Szip_LIBRARY_DIRS} PATH)
ENDIF("${Szip_LIBRARY_DIRS}" MATCHES "/include$")

IF(EXISTS "${Szip_LIBRARY_DIRS}/lib")
SET(Szip_LIBRARY_DIRS ${Szip_LIBRARY_DIRS}/lib)
ENDIF(EXISTS "${Szip_LIBRARY_DIRS}/lib")

# Find Szip libraries
FIND_LIBRARY(Szip_DEBUG_LIBRARY NAMES szipd szip_d libszipd libszip_d szip libszip sz2 libsz2
PATH_SUFFIXES Debug ${CMAKE_LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_ARCHITECTURE}/Debug
PATHS ${Szip_LIBRARY_DIRS} NO_DEFAULT_PATH)
PATHS ${Szip_LIBRARY_DIRS} ${Szip_LIBRARY_DIRS}/lib ${Szip_LIBRARY_DIRS}/lib64 NO_DEFAULT_PATH)
FIND_LIBRARY(Szip_RELEASE_LIBRARY NAMES szip libszip sz libsz sz2 libsz2
PATH_SUFFIXES Release ${CMAKE_LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_ARCHITECTURE}/Release
PATHS ${Szip_LIBRARY_DIRS} NO_DEFAULT_PATH)
PATHS ${Szip_LIBRARY_DIRS} ${Szip_LIBRARY_DIRS}/lib ${Szip_LIBRARY_DIRS}/lib64 NO_DEFAULT_PATH)

SET(Szip_LIBRARIES)
SET(Szip_LIBRARY)
Expand Down
6 changes: 6 additions & 0 deletions config.h.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ are set when opening a binary file on Windows. */
/* if true, Allow dynamically loaded plugins */
#cmakedefine NETCDF_ENABLE_PLUGINS 1

/* Define the plugin install dir */
#cmakedefine NETCDF_PLUGIN_INSTALL_DIR "${NETCDF_PLUGIN_INSTALL_DIR}"

/* Define the plugin search path */
#cmakedefine NETCDF_PLUGIN_SEARCH_PATH "${NETCDF_PLUGIN_SEARCH_PATH}"

/* if true, enable S3 support */
#cmakedefine NETCDF_ENABLE_S3 1

Expand Down
109 changes: 62 additions & 47 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2143,67 +2143,82 @@ fi

AC_SUBST(STD_FILTERS,[$std_filters])

# Internally, the variable HDF5_PLUGIN_PATH
# is always used as a surrogate for the default
# plugin path. If it was not defined by the user,
# then set it internally.
if test "x${HDF5_PLUGIN_PATH}" = x ; then
if test "x$ISMSVC" = xyes || test "x$ISMINGW" = xyes; then
HDF5_PLUGIN_PATH="${ALLUSERSPROFILE}\\hdfd5\\lib\\plugin"
else
HDF5_PLUGIN_PATH="/usr/local/hdf5/lib/plugin"
fi
fi

# The --with-plugin-dir gives the user control of the plugin
# directory. If set to 'yes' (the default), then the last directory in
# HDF5_PLUGIN_PATH is used (see above).
# The --with-plugin-dir option gives the user control of the plugin install
# directory. This also used as one of the default plugin directory when
# searching for plugins.
# If a specific directory is provided, it will be used.
# If 'no', then plugins will not be installed.

# If not defined or defined with the value no, or --without-plugin-dir, then
# plugin installation will be suppressed (but see below).
AC_MSG_CHECKING([whether and where we should install plugins])
AC_ARG_WITH([plugin-dir], [AS_HELP_STRING([--with-plugin-dir=<absolute directory>|yes|no|--without-plugin-dir],
AC_ARG_WITH([plugin-dir], [AS_HELP_STRING([--with-plugin-dir=<absolute directory>|no|--without-plugin-dir],
[Install selected standard filters in specified or default directory])],
[],[with_plugin_dir=no])
AC_MSG_RESULT([$with_plugin_dir])

# Using selected filter options forces installation
if test "x$have_zstd" = xyes; then
if test "x$enable_plugins" = xyes && test "x$with_plugin_dir" = xno; then
AC_MSG_WARN([--enable_filter-zstd => --with-plugin-dir.])
with_plugin_dir=yes
fi
fi
if test "x$with_plugin_dir" = xno ; then # option missing|disabled
with_plugin_dir=no
with_plugin_dir_setting="N.A."
enable_plugin_dir=no
elif test "x$with_plugin_dir" != x ; then
if test "x$with_plugin_dir" != xyes && test "x$with_plugin_dir" != xno ; then
# Presume true directory
HDF5_PLUGIN_PATH="${with_plugin_dir}"
fi
AC_MSG_WARN([--enable_filter-zstd => --enable-plugins.])
enable_plugins=yes
fi

# Use the last dir (lowest search priority) in HDF5_PLUGIN_PATH
PLUGIN_PATH="$HDF5_PLUGIN_PATH"
# Note: the term PLATFORMDEFAULT stands for:
# -- /usr/loca/hdf5/lib/plugin If on a *nix* machine
# -- %ALLUSERSPROFILE%/hdf5/lib/plugins If on a windows or Mingw platform
if test "x$ISMSVC" = xyes || test "x$ISMINGW" = xyes; then
PLUGIN_DIR=`echo "$PLUGIN_PATH" | tr ';' ' '`
PLATFORMDEFAULT="${ALLUSERSPROFILE}\\hdf5\\lib\\plugin"
PLATFORMSEP=";"
else
PLUGIN_DIR=`echo "$PLUGIN_PATH" | tr ':;' ' '`
PLATFORMDEFAULT="/usr/local/hdf5/lib/plugin"
PLATFORMSEP=":"
fi

# Internally, the variable DEFAULT_PLUGIN_INSTALL_DIR is the default
# directory into which plugins are installed; this may be undefined if
# plugin installation is disabled (the usual case). It is exported as
# NETCDF_PLUGIN_INSTALL_DIR.
#
# Similarly the variable DEFAULT_PLUGIN_SEARCH_PATH is the default list
# of directories to search to locate plugins. It is exported as
# NETCDF_PLUGIN_SEARCH_PATH
#
# See the document docs/pluginpath.md for a more detailed discussion
# of how NETCDF_PLUGIN_INSTALL_DIR and NETCDF_PLUGIN_SEARCH_PATH are
# computed.

# Canonicalize --with-prefix-dir and --prefix
if test "x$with_plugin_dir" = xno ; then unset with_plugin_dir ; fi
if test "xprefix" = x ; then prefix=NONE ; fi
if test "x$with_plugin_dir" != x ; then # Table row 3
DEFAULT_PLUGIN_INSTALL_DIR="${with_plugin_dir}"
DEFAULT_PLUGIN_SEARCH_PATH="${with_plugin_dir}${PLATFORMSEP}${PLATFORMDEFAULT}"
elif test "x$prefix" != xNONE ; then # Table row 2
DEFAULT_PLUGIN_INSTALL_DIR="${prefix}/hdf5/lib/plugin"
DEFAULT_PLUGIN_SEARCH_PATH="${prefix}/hdf5/lib/plugin${PLATFORMSEP}${PLATFORMDEFAULT}"
else # Table row 1
unset DEFAULT_PLUGIN_INSTALL_DIR
DEFAULT_PLUGIN_SEARCH_PATH="${PLATFORMDEFAULT}"
fi
last=
for pp in ${PLUGIN_DIR} ; do last="$pp"; done
PLUGIN_DIR="$last"
with_plugin_dir_setting="$PLUGIN_DIR"
# canonical form is all forward slashes
with_plugin_dir=`echo "$PLUGIN_DIR" | tr '\\\\' '/'`
enable_plugin_dir=yes
AC_MSG_NOTICE([Final --with-plugin-dir=$with_plugin_dir])
DEFAULT_PLUGIN_INSTALL_DIR=`echo "$DEFAULT_PLUGIN_INSTALL_DIR" | tr '\\\\' '/'`
DEFAULT_PLUGIN_SEARCH_PATH=`echo "$DEFAULT_PLUGIN_SEARCH_PATH" | tr '\\\\' '/'`

# Inferences
if test "x$DEFAULT_PLUGIN_INSTALL_DIR" = x ; then # option missing|disabled
enable_plugin_dir=no
else
enable_plugin_dir=yes
fi

if test "x$enable_plugin_dir" = xyes ; then
AC_DEFINE([ENABLE_PLUGIN_DIR], [1], [If true, enable filter installation])
fi

AM_CONDITIONAL([ENABLE_PLUGIN_DIR], [test "x$enable_plugin_dir" = xyes])
AC_SUBST([PLUGIN_INSTALL_DIR], [$with_plugin_dir])
# Better value for libnetcdf.settings
AC_SUBST([PLUGIN_INSTALL_DIR_SETTING], [$with_plugin_dir_setting])
AC_SUBST(NETCDF_PLUGIN_INSTALL_DIR, [$PLUGIN_INSTALL_DIR])
AC_DEFINE_UNQUOTED([NETCDF_PLUGIN_INSTALL_DIR], ["${DEFAULT_PLUGIN_INSTALL_DIR}"], [Final Install Dir])
AC_DEFINE_UNQUOTED([NETCDF_PLUGIN_SEARCH_PATH], ["${DEFAULT_PLUGIN_SEARCH_PATH}"], [Final Search Path])
AC_SUBST([NETCDF_PLUGIN_INSTALL_DIR], [${DEFAULT_PLUGIN_INSTALL_DIR}])
AC_SUBST([NETCDF_PLUGIN_SEARCH_PATH], [${DEFAULT_PLUGIN_SEARCH_PATH}])

# Access netcdf specific version of config.h
AH_BOTTOM([#include "ncconfigure.h"])

Expand Down
60 changes: 41 additions & 19 deletions docs/pluginpath.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,52 @@ This initial global plugin path will be propagated to HDF5 and NCZarr.
At build-time, the target location directory into which libraries implementing plugins are installed is specified using a special *./configure* option
````
--with-plugin-dir=<directorypath>
or
--with-plugin-dir
````
or its corresponding *cmake* option.
````
-DNETCDF_PLUGIN_INSTALL_DIR=<directorypath>
or
-DNETCDF_PLUGIN_INSTALL_DIR=YES
-DNETCDF_WITH_PLUGIN_DIR=<directorypath>
````
If this option is specified but with no specific directory,
then it defaults to one of three values:
1. If *HDF5\_PLUGIN\_PATH* defined, then use the last directory in that path,
2. else use `/usr/local/hdf5/lib/plugin` for linux/unix operating systems (including Cygwin) else use
3. `%ALLUSERSPROFILE%\\hdf5\\lib\\plugin` for Windows and MinGW.

If the option is specified with an absolute directory path, then all plugin libraries will be installed in that directory only.

If the option is not specified at all, or one of the following options is used,
then no attempt will be made to install plugins.
````
--without-plugin-dir
or (cmake)
-DNETCDF_PLUGIN_INSTALL_DIR=NO
````
## Build-Time Operations

At build time, certain plugin-related constants are constructed.
1. NETCDF_PLUGIN_INSTALL_DIR -- the directory into which compiled plugins should be installed
2. NETCDF_PLUGIN_SEARCH_PATH -- the default search path to be used at run-time if not over-ridden by the *HDF5_PLUGIN_PATH* environment variable.

<table style="border:2px solid black;border-collapse:collapse">
<tr style="outline: thin solid;" align="center"><td colspan="4">Table showing the build-time computation of DEFAULT_PLUGIN_INSTALL_DIR and DEFAULT_PLUGIN_SEARCH_PATH.</td>
<tr style="outline: thin solid" ><th>--with-plugin-dir<th>--prefix<th>DEFAULT_PLUGIN_INSTALL_DIR<th>DEFAULT_PLUGIN_SEARCH_PATH
<tr style="outline: thin solid" ><td>undefined<td>undefined<td>undefined<td>PLATFORMDEFALT
<tr style="outline: thin solid" ><td>undefined<td>&lt;abspath-prefix&gt;<td>&lt;abspath-prefix&gt;/hdf5/lib/plugin<td>&lt;abspath-prefix&gt;/hdf5/lib/plugin&lt;SEP&gt;PLATFORMDEFALT
<tr style="outline: thin solid" ><td>&lt;abspath-plugins&gt;<td>N.A.<td>&lt;abspath-plugins&gt;<td>&lt;abspath-plugins&gt;&lt;SEP&gt;PLATFORMDEFALT
</table>

Notes:
1. HDF5_PLUGIN_PATH is ignored at build time.

2. ';' is used as a placeholder for PLATFORMSEP.

3. The term PLATFORMDEFAULT stands for:
- /usr/local/hdf5/lib/plugin If on a *nix* machine
- %ALLUSERSPROFILE%/hdf5/lib/plugins If on a windows or Mingw platform
4. The term SEP stands for:
- ':' If on a *nix* machine
- ';' If on a windows or Mingw platform

## Run-Time Operations

When the netcdf-c library initializes itself (at runtime), it chooses an
initial global plugin path for the config.h value.
This value defaults to *NETCDF_PLUGIN_SEARCH_PATH*.
If, however, HDF5_PLUGIN_PATH is defined, then it is used to override
*NETCDF_PLUGIN_SEARCH_PATH*.

<table style="border:2px solid black;border-collapse:collapse">
<tr style="outline: thin solid" align="center"><td colspan="2">Table showing the computation of the initial global plugin path</td>
<tr style="outline: thin solid"><th>HDF5_PLUGIN_PATH<th>Initial global plugin path
<tr style="outline: thin solid"><td>undefined<td>NETCDF_PLUGIN_SEARCH_PATH
<tr style="outline: thin solid"><td>&lt;path1;...pathn&gt;<td>&lt;path1;...pathn&gt;
</table>

## Multi-Threaded Access to the Plugin Path.
Specifically, note that modifying the plugin path must be done "atomically".
Expand Down
Loading

0 comments on commit efdec07

Please sign in to comment.