diff --git a/.github/workflows/run_tests_osx.yml b/.github/workflows/run_tests_osx.yml index 8b7e15e99..b85df0133 100644 --- a/.github/workflows/run_tests_osx.yml +++ b/.github/workflows/run_tests_osx.yml @@ -7,7 +7,7 @@ name: Run macOS-based netCDF Tests -on: [push, pull_request, workflow_dispatch] +on: [push,pull_request, workflow_dispatch] jobs: diff --git a/docs/Makefile.am b/docs/Makefile.am index e6e8a84e6..29be233d9 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -7,13 +7,15 @@ # See netcdf-c/COPYRIGHT file for more info. # These files will be included with the dist. -EXTRA_DIST = netcdf.m4 DoxygenLayout.xml Doxyfile.in footer.html \ -mainpage.dox tutorial.dox architecture.dox internal.dox \ -windows-binaries.md dispatch.md building-with-cmake.md CMakeLists.txt groups.dox \ -notes.md install-fortran.md credits.md auth.md filters.md \ -obsolete/fan_utils.html indexing.dox inmemory.md FAQ.md \ -known_problems.md COPYRIGHT.md inmeminternal.dox testserver.dox \ -byterange.dox nczarr.md quantize.md all-error-codes.md +EXTRA_DIST = CMakeLists.txt COPYRIGHT.md FAQ.md \ +netcdf.m4 DoxygenLayout.xml Doxyfile.in footer.html \ +mainpage.dox tutorial.dox architecture.dox \ +groups.dox indexing.dox inmeminternal.dox testserver.dox \ +byterange.dox \ +windows-binaries.md dispatch.md building-with-cmake.md \ +notes.md install-fortran.md credits.md auth.md filters.md \ +obsolete/fan_utils.html inmemory.md known_problems.md \ +nczarr.md quantize.md all-error-codes.md # Turn off parallel builds in this directory. .NOTPARALLEL: diff --git a/docs/dispatch.dox b/docs/dispatch.dox deleted file mode 100644 index 0f54275ff..000000000 --- a/docs/dispatch.dox +++ /dev/null @@ -1,27 +0,0 @@ -/*! \file -Documentation for the dispatch system - -\internal - -\defgroup dispatch The Dispatch Layer - -The dispatch layer is a way to add read/write modules to the netCDF -library. - -Dispatch modules, plugged into the netCDF library, will allow netCDF -programs to read and write other, perhaps quite local, formats. - -This should be of particular interest to anyone contemplating the -conversion of large data collections to netCDF in order to gain access -to those data in netCDF-oriented tools and software systems. Instead -of converting the data, a read module could be written which would -read the data as if it were in netCDF. This would give netCDF tools -read-only access to data in this format, transparently to the tool. - -This mechanism is already used within the netCDF library to handle the -netCDF-4/HDF5 files, and the remote data access features. - -Conceptually, the dispatch layer provides the same capabilities as the -IOSP in the netCDF-Java library. However, unlike Java, C does not -provide the advanced features to make this seamless. -*/ diff --git a/docs/dispatch.md b/docs/dispatch.md index 55346503f..f46a5b31d 100644 --- a/docs/dispatch.md +++ b/docs/dispatch.md @@ -4,7 +4,7 @@ Internal Dispatch Table Architecture # Internal Dispatch Table Architecture -\tableofcontents +[TOC] # Introduction {#dispatch_intro} @@ -146,7 +146,9 @@ Finalization is handled in an analogous fashion. ## Testing the new dispatch table -Add a directory of tests: *ncm_test*, say. The file *ncm_test/Makefile.am* +Typically, tests for a new dispatcher are kept in a separate directory +with a related name. For our running example, it might be *ncm_test*. +The file *ncm_test/Makefile.am* will look something like this. ```` # These files are created by the tests. @@ -370,7 +372,7 @@ purpose: - NOTNC3_inq_base_pe - NOTNC3_set_base_pe -# HDF4 Dispatch Layer as a Simple Example +# Appendix A. HDF4 Dispatch Layer as a Simple Example The HDF4 dispatch layer is about the simplest possible dispatch layer. It is read-only, classic model. It will serve as a nice, simple @@ -385,21 +387,25 @@ as follows. ... #endif /*USE_HDF4*/ ```` - Code in libhdf4 is only compiled if HDF4 is turned on in the build. +## Header File Changes + +Adding the HDF4 dispatch table will first require changes to +a number of header files. + ### The netcdf.h File -In the main netcdf.h file, we have the following: - +In the main netcdf.h file, we add the following +to the list of NC_FORMATX_XXX definitions ```` #define NC_FORMATX_NC_HDF4 (3) ```` ### The ncdispatch.h File -In ncdispatch.h we have the following: +In ncdispatch.h we add the following: ```` #ifdef USE_HDF4 @@ -412,18 +418,17 @@ extern int HDF4_finalize(void); ### The netcdf_meta.h File The netcdf_meta.h file allows for easy determination of what features -are in use. For HDF4, It contains the following, set by configure: +are in use. For HDF4, the following is added -- as set by *./configure*: ```` -... #define NC_HAS_HDF4 0 /*!< HDF4 support. */ -... ```` ### The hdf4dispatch.h File The file *hdf4dispatch.h* contains prototypes and macro definitions used within the HDF4 code in libhdf4. This include -file should not be used anywhere except in libhdf4. +file should not be used anywhere except in libhdf4. It can be kept +in either the *include* directory or (preferably) the *libhdf4* directory. ### Initialization Code Changes in liblib Directory @@ -462,8 +467,8 @@ table. It looks like this: /* This is the dispatch object that holds pointers to all the * functions that make up the HDF4 dispatch interface. */ static NC_Dispatch HDF4_dispatcher = { -NC_FORMATX_NC_HDF4, -NC_DISPATCH_VERSION, +NC_FORMATX_NC_HDF4, /* The model identifier */ +NC_DISPATCH_VERSION, /* The version of this dispatch table */ NC_RO_create, NC_HDF4_open, NC_RO_redef, @@ -499,9 +504,67 @@ The code in *hdf4var.c* does an *nc_get_vara()* on the HDF4 SD dataset. This is all that is needed for all the nc_get_* functions to work. +# Appendix B. Inferring the Dispatch Table + +As mentioned above, the dispatch table is inferred using the following +information: +1. The mode argument +2. The file path/URL +3. The file contents (when available) + +The primary function for doing this inference is in the file +*libdispatch/dinfermodel.c* via the API in *include/ncmodel.h*. +The term *model* is used here to include (at least) the following +information (see the structure type *NCmodel* in *include/ncmodel.h*). + +1. impl -- this is an NC_FORMATX_XXX value defining, in effect, the + dispatch table to use. +2. format -- this is an NC_FORMAT_XXX value defining the API to support: netcdf classic or netcdf enhanced. + +The construction of the model is primarily carried out by the function +*NC*infermodel()* (in *libdispatch/dinfermodel.c*). +It is given the following parameters: +1. path -- (IN) absolute file path or URL +2. modep -- (IN/OUT) the set of mode flags given to *NC_open* or *NC_create*. +3. iscreate -- (IN) distinguish open from create. +4. useparallel -- (IN) indicate if parallel IO can be used. +5. params -- (IN/OUT) arbitrary data dependent on the mode and path. +6. model -- (IN/OUT) place to store inferred model. +7. newpathp -- (OUT) the canonical rewrite of the path argument. + +As a rule, these values are used in the this order to infer the model. +1. file contents -- highest precedence +2. url (if it is one) -- using the "mode=" key in the fragment (see below). +3. mode flags +4. default format -- lowest precedence + +If the path appears to be a URL, then it is parsed. +Information is extracted from the URL, and specifically, +the fragment key "mode=" is the critical element. +The URL will be rewritten to a canonical form with the following +changes. +1. The fragment part ("#..." at the end) is parsed and the "mode=" key + is extracted and its value is converted to a list of tags. +2. If the leading protocol is not http/https, then the protocol is added + to the mode list. That protocol is then replaced with either http or https. +3. Certain singleton values in the fragment are extracted and removed + and added to the mode list. Consider, for example, "http://....#dap4". + The "dap4" singleton is removed and added to the mode list. +4. For backward compatibility, the values of "proto=" and "protocol=" + are removed from the fragment and their value is added to the mode list. +5. The final mode list is converted to a comma separated string + and re-inserted into the fragment. +6. The final mode list is modified to remove duplicates. + +The final result is the canonical form of the URL and is returned in the +newpathp argument described above. + +The mode list then is used as part of the inference process to choose +a dispatch table. + # Point of Contact {#dispatch_poc} *Author*: Dennis Heimbigner
*Email*: dmh at ucar dot edu
*Initial Version*: 12/22/2021
-*Last Revised*: 12/22/2021 +*Last Revised*: 11/15/2022 diff --git a/docs/internal.dox b/docs/internal.dox deleted file mode 100644 index aa4cd0eed..000000000 --- a/docs/internal.dox +++ /dev/null @@ -1,538 +0,0 @@ -/** \file - -\internal - -\page nc_dispatch Internal Dispatch Table Architecture - -\tableofcontents - -This document describes the architecture and details of the netCDF -internal dispatch mechanism. The idea is that when a user opens or -creates a netcdf file, a specific dispatch table is chosen. -A dispatch table is a struct containing an entry for every function -in the netcdf-c API. -Subsequent netcdf API calls are then channeled through that -dispatch table to the appropriate function for implementing that API -call. The functions in the dispatch table are not quite the same -as those defined in netcdf.h. For simplicity and compactness, -some netcdf.h API calls are -mapped to the same dispatch table function. In addition to -the functions, the first entry in the table defines the model -that this dispatch table implements. It will be one of the -NC_FORMATX_XXX values. - -The list of supported dispatch tables will grow over time. -To date, at least the following dispatch tables are supported. -- netcdf classic files (netcdf-3) -- netcdf enhanced files (netcdf-4) -- DAP2 to netcdf-3 -- DAP4 to netcdf-4 -- PnetCDF (parallel I/O for classic files -- version 1,2, or 5) -- HDF4 SD files - -The dispatch table represents a distillation of the netcdf API down to -a minimal set of internal operations. The format of the dispatch table -is defined in the file libdispatch/ncdispatch.h. Every new dispatch -table must define this minimal set of operations. - -\section adding_dispatch Adding a New Dispatch Table - -In order to make this process concrete, let us assume we plan to add -an in-memory implementation of netcdf-3. - -\subsection dispatch_configure_ac Defining configure.ac flags - -Define a _–-enable_ flag and an _AM_CONFIGURE_ flag in _configure.ac_. -For our example, we assume the option "--enable-ncm" and the AM_CONFIGURE -flag "ENABLE_NCM". If you examine the existing _configure.ac_ and see how, -for example, _DAP2_ is defined, then it should be clear how to do it for -your code. - -\subsection dispatch_namespace Defining a "name space" - -Choose some prefix of characters to identify the new dispatch -system. In effect we are defining a name-space. For our in-memory -system, we will choose "NCM" and "ncm". NCM is used for non-static -procedures to be entered into the dispatch table and ncm for all other -non-static procedures. Note that the chosen prefix should probably start -with "nc" in order to avoid name conflicts outside the netcdf-c library. - -\subsection dispatch_netcdf_h Extend include/netcdf.h - -Modify the file _include/netcdf.h_ to add an NC_FORMATX_XXX flag -by adding a flag for this dispatch format at the appropriate places. -\code - \c \#define NC_FORMATX_NCM 7 -\endcode - -Add any format specific new error codes. -\code - \c \#define NC_ENCM (?) -\endcode - -\subsection dispatch_ncdispatch Extend include/ncdispatch.h - -Modify the file _include/ncdispatch.h_ to -add format specific data and functions; note the use of our NCM namespace. -\code - #ifdef ENABLE_NCM - extern NC_Dispatch* NCM_dispatch_table; - extern int NCM_initialize(void); - #endif -\endcode - -\subsection dispatch_define_code Define the dispatch table functions - -Define the functions necessary to fill in the dispatch table. As a -rule, we assume that a new directory is defined, _libsrcm_, say. Within -this directory, we need to define _Makefile.am_ and _CMakeLists.txt_. -We also need to define the source files -containing the dispatch table and the functions to be placed in the -dispatch table -– call them _ncmdispatch.c_ and _ncmdispatch.h_. Look at -_libsrc/nc3dispatch.[ch]_ or _libdap4/ncd4dispatch.[ch]_ for examples. - -Similarly, it is best to take existing _Makefile.am_ and _CMakeLists.txt_ -files (from _libdap4_ for example) and modify them. - -\subsection dispatch_lib Adding the dispatch code to libnetcdf - -Provide for the inclusion of this library in the final libnetcdf -library. This is accomplished by modifying _liblib/Makefile.am_ by -adding something like the following. -\code - if ENABLE_NCM - libnetcdf_la_LIBADD += $(top_builddir)/libsrcm/libnetcdfm.la - endif -\endcode - -\subsection dispatch_init Extend library initialization - -Modify the _NC_initialize_ function in _liblib/nc_initialize.c_ by adding -appropriate references to the NCM dispatch function. -\code - #ifdef ENABLE_NCM - extern int NCM_initialize(void); - #endif - ... - int NC_initialize(void) - { - ... - #ifdef ENABLE_NCM - if((stat = NCM_initialize())) return stat; - #endif - ... - } -\endcode - -\section dispatch_tests Testing the new dispatch table - -Add a directory of tests: _ncm_test_, say. The file _ncm_test/Makefile.am_ -will look something like this. -\code - # These files are created by the tests. - CLEANFILES = ... - # These are the tests which are always run. - TESTPROGRAMS = test1 test2 ... - test1_SOURCES = test1.c ... - ... - # Set up the tests. - check_PROGRAMS = $(TESTPROGRAMS) - TESTS = $(TESTPROGRAMS) - # Any extra files required by the tests - EXTRA_DIST = ... -\endcode - -\section dispatch_toplevel Top-Level build of the dispatch code - -Provide for _libnetcdfm_ to be constructed by adding the following to -the top-level _Makefile.am_. - -\code - if ENABLE_NCM - NCM=libsrcm - NCMTESTDIR=ncm_test - endif - ... - SUBDIRS = ... $(DISPATCHDIR) $(NCM) ... $(NCMTESTDIR) -\endcode - -\section choosing_dispatch_table Choosing a Dispatch Table - -The dispatch table is chosen in the NC_create and the NC_open -procedures. -This can be, unfortunately, a complex process. -The code for inferring a dispatch table is largely isolated -to the file _libdispatch/dinfermodel.c_, which is invoked -from _NC_create_ or _NC_open_ in _libdispatch/dfile.c_. - -In any case, the choice of dispatch table is currently based on the following -pieces of information. - -1. The mode argument – this can be used to detect, for example, what kind -of file to create: netcdf-3, netcdf-4, 64-bit netcdf-3, etc. -Using a mode flag is the most common mechanism, in which case -_netcdf.h_ needs to be modified to define the relevant mode flag. - -2. The file path – this can be used to detect, for example, a DAP url -versus a normal file system file. If the path looks like a URL, then -the choice is determined using the function _NC_urlmodel_. - -3. The file contents - when the contents of a real file are available, -the contents of the file can be used to determine the dispatch table. -As a rule, this is likely to be useful only for _nc_open_. - -\section special_dispatch Special Dispatch Table Signatures. - -The entries in the dispatch table do not necessarily correspond -to the external API. In many cases, multiple related API functions -are merged into a single dispatch table entry. - -\subsection create_open_dispatch Create/Open - -The create table entry and the open table entry in the dispatch table -have the following signatures respectively. -\code - int (*create)(const char *path, int cmode, - size_t initialsz, int basepe, size_t *chunksizehintp, - int useparallel, void* parameters, - struct NC_Dispatch* table, NC* ncp); -\endcode - -\code - int (*open)(const char *path, int mode, - int basepe, size_t *chunksizehintp, - int use_parallel, void* parameters, - struct NC_Dispatch* table, NC* ncp); -\endcode - -The key difference is that these are the union of all the possible -create/open signatures from the include/netcdfXXX.h files. Note especially the last -three parameters. The parameters argument is a pointer to arbitrary data -to provide extra info to the dispatcher. -The table argument is included in case the create -function (e.g. _NCM_create_) needs to invoke other dispatch -functions. The very last argument, ncp, is a pointer to an NC -instance. The raw NC instance will have been created by _libdispatch/dfile.c_ -and is passed to e.g. open with the expectation that it will be filled in -by the dispatch open function. - -\subsection put_vara_dispatch Accessing Data with put_vara() and get_vara() - -\code - int (*put_vara)(int ncid, int varid, const size_t *start, const size_t *count, - const void *value, nc_type memtype); -\endcode - -\code - int (*get_vara)(int ncid, int varid, const size_t *start, const size_t *count, - void *value, nc_type memtype); -\endcode - -Most of the parameters are similar to the netcdf API parameters. The -last parameter, however, is the type of the data in -memory. Additionally, instead of using an "int islong" parameter, the -memtype will be either ::NC_INT or ::NC_INT64, depending on the value -of sizeof(long). This means that even netcdf-3 code must be prepared -to encounter the ::NC_INT64 type. - -\subsection put_attr_dispatch Accessing Attributes with put_attr() and get_attr() - -\code - int (*get_att)(int ncid, int varid, const char *name, - void *value, nc_type memtype); -\endcode - -\code - int (*put_att)(int ncid, int varid, const char *name, nc_type datatype, size_t len, - const void *value, nc_type memtype); -\endcode - -Again, the key difference is the memtype parameter. As with -put/get_vara, it used ::NC_INT64 to encode the long case. - -\subsection pre_def_dispatch Pre-defined Dispatch Functions - -It is sometimes not necessary to implement all the functions in the -dispatch table. Some pre-defined functions are available which may be -used in many cases. - -\subsubsection inquiry_functions Inquiry Functions - -The netCDF inquiry functions operate from an in-memory model of -metadata. Once a file is opened, or a file is created, this -in-memory metadata model is kept up to date. Consequenty the inquiry -functions do not depend on the dispatch layer code. These functions -can be used by all dispatch layers which use the internal netCDF -enhanced data model. - -- NC4_inq -- NC4_inq_type -- NC4_inq_dimid -- NC4_inq_dim -- NC4_inq_unlimdim -- NC4_inq_att -- NC4_inq_attid -- NC4_inq_attname -- NC4_get_att -- NC4_inq_varid -- NC4_inq_var_all -- NC4_show_metadata -- NC4_inq_unlimdims -- NC4_inq_ncid -- NC4_inq_grps -- NC4_inq_grpname -- NC4_inq_grpname_full -- NC4_inq_grp_parent -- NC4_inq_grp_full_ncid -- NC4_inq_varids -- NC4_inq_dimids -- NC4_inq_typeids -- NC4_inq_type_equal -- NC4_inq_user_type -- NC4_inq_typeid - -\subsubsection ncdefault_functions NCDEFAULT get/put Functions - -The mapped (varm) get/put functions have been -implemented in terms of the array (vara) functions. So dispatch layers -need only implement the vara functions, and can use the following -functions to get the and varm functions: - -- NCDEFAULT_get_varm -- NCDEFAULT_put_varm - -For the netcdf-3 format, the strided functions (nc_get/put_vars) -are similarly implemented in terms of the vara functions. So the following -convenience functions are available. - -- NCDEFAULT_get_vars -- NCDEFAULT_put_vars - -For the netcdf-4 format, the vars functions actually exist, so -the default vars functions are not used. - -\subsubsection read_only_functions Read-Only Functions - -Some dispatch layers are read-only (ex. HDF4). Any function which -writes to a file, including nc_create(), needs to return error code -::NC_EPERM. The following read-only functions are available so that -these don't have to be re-implemented in each read-only dispatch layer: - -- NC_RO_create -- NC_RO_redef -- NC_RO__enddef -- NC_RO_sync -- NC_RO_set_fill -- NC_RO_def_dim -- NC_RO_rename_dim -- NC_RO_rename_att -- NC_RO_del_att -- NC_RO_put_att -- NC_RO_def_var -- NC_RO_rename_var -- NC_RO_put_vara -- NC_RO_def_var_fill - -\subsubsection classic_functions Classic NetCDF Only Functions - -There are two functions that are only used in the classic code. All -other dispatch layers (except PnetCDF) return error ::NC_ENOTNC3 for -these functions. The following functions are provided for this -purpose: - -- NOTNC3_inq_base_pe -- NOTNC3_set_base_pe - -\section dispatch_layer HDF4 Dispatch Layer as a Simple Example - -The HDF4 dispatch layer is about the simplest possible dispatch -layer. It is read-only, classic model. It will serve as a nice, simple -example of a dispatch layer. - -Note that the HDF4 layer is optional in the netCDF build. Not all -users will have HDF4 installed, and those users will not build with -the HDF4 dispatch layer enabled. For this reason HDF4 code is guarded -as follows. -\code -\c \#ifdef USE_HDF4 -... -\c \#endif /*USE_HDF4*/ -\endcode - -Code in libhdf4 is only compiled if HDF4 is -turned on in the build. - -\subsection header_changes Header File Changes in include Directory - -\subsubsection netcdf_h_file The netcdf.h File - -In the main netcdf.h file, we have the following: - -\code -\c \#define NC_FORMATX_NC_HDF4 (3) -\c \#define NC_FORMAT_NC_HDF4 NC_FORMATX_NC_HDF4 -\endcode - -\subsubsection ncdispatch_h_file The ncdispatch.h File - -In ncdispatch.h we have the following: - -\code -#ifdef USE_HDF4 -extern NC_Dispatch* HDF4_dispatch_table; -extern int HDF4_initialize(void); -extern int HDF4_finalize(void); -#endif -\endcode - -\subsubsection netcdf_meta_h_file The netcdf_meta.h File - -The netcdf_meta.h file allows for easy determination of what features -are in use. It contains the following, set by configure: - -\code -\c \#define NC_HAS_HDF4 1 /*!< hdf4 support. */ -\endcode - -\subsubsection hdf4dispatch_h_file The hdf4dispatch.h File - -The file _hdf4dispatch.h_ contains prototypes and -macro definitions used within the HDF4 code in libhdf4. This include -file should not be used anywhere except in libhdf4. - -\subsection liblib_init Initialization Code Changes in liblib Directory - -The file _nc_initialize.c_ is modified to include the following: -\code -#ifdef USE_HDF4 -extern int HDF4_initialize(void); -extern int HDF4_finalize(void); -#endif -\endcode - -\subsection libdispatch_changes Dispatch Code Changes in libdispatch Directory - -\subsubsection dfile_c_changes Changes to dfile.c - -In order for a dispatch layer to be used, it must be correctly -determined in functions _NC_open()_ or _NC_create()_ in _libdispatch/dfile.c_. - -HDF4 has a magic number that is detected in -_NC_interpret_magic_number()_, which allows _NC_open_ to automatically -detect an HDF4 file. - -Once HDF4 is detected, the _model_ variable is set to _NC_FORMATX_NC_HDF4_, -and later this is used in a case statement: - -\code - case NC_FORMATX_NC_HDF4: - dispatcher = HDF4_dispatch_table; - break; -\endcode - -This sets the dispatcher to the HDF4 dispatcher, which is defined in -the libhdf4 directory. - -\subsection libhdf4_dispatch_code Dispatch Code in libhdf4 - -\subsubsection hdf4dispatch_c_table Dispatch Table in hdf4dispatch.c - -The file _hdf4dispatch.c_ contains the definition of the HDF4 dispatch -table. It looks like this: -\code -/* This is the dispatch object that holds pointers to all the - * functions that make up the HDF4 dispatch interface. */ -static NC_Dispatch HDF4_dispatcher = { -NC_FORMATX_NC_HDF4, -NC_RO_create, -NC_HDF4_open, -NC_RO_redef, -NC_RO__enddef, -NC_RO_sync, - -... - -NC_NOTNC4_set_var_chunk_cache, -NC_NOTNC4_get_var_chunk_cache, -}; -\endcode - -Note that most functions use some of the predefined dispatch -functions. Functions that start with NC_RO_ are read-only, they return -::NC_EPERM. Functions that start with NOTNC4_ return ::NC_ENOTNC4. - -Only the functions that start with NC_HDF4_ need to be implemented for -the HDF4 dispatch layer. There are 6 such functions: - -- NC_HDF4_open -- NC_HDF4_abort -- NC_HDF4_close -- NC_HDF4_inq_format -- NC_HDF4_inq_format_extended -- NC_HDF4_get_vara - -\subsubsection hdf4_reading_code HDF4 Reading Code - -The code in _hdf4file.c_ opens the HDF4 SD dataset, and reads the -metadata. This metadata is stored in the netCDF internal metadata -model, allowing the inq functions to work. - -The code in _hdf4var.c_ does an _nc_get_vara()_ on the HDF4 SD -dataset. This is all that is needed for all the nc_get_* functions to -work. - -\subsection model_infer Inferring the Dispatch Table - -As mentioned above, the dispatch table is inferred using the following -information: -1. The mode argument -2. The file path/URL -3. The file contents (when available) - -The primary function for doing this inference is in the file -_libdispatch/dinfermodel.c_ via the API in _include/ncmodel.h_. -The term _model_ is used here to include (at least) the following -information (see the structure type _NCmodel_ in _include/ncmodel.h_). - -1. impl -- this is an NC_FORMATX_XXX value defining, in effect, the - dispatch table to use. - -The construction of the model is primarily carried out by the function -_NC_infermodel()_ (in _libdispatch/dinfermodel.c_). -It is given the following parameters: -1. path -- (IN) absolute file path or URL -2. modep -- (IN/OUT) the set of mode flags given to _NC_open_ or _NC_create_. -3. iscreate -- (IN) distinguish open from create. -4. useparallel -- (IN) indicate if parallel IO can be used. -5. params -- (IN/OUT) arbitrary data dependent on the mode and path. -6. model -- (IN/OUT) place to store inferred model. -7. newpathp -- (OUT) the canonical rewrite of the path argument. - -As a rule, these values are used in the this order to infer the model. -1. file contents -- highest precedence -2. url (if it is one) -- using the "mode=" key in the fragment (see below). -3. mode flags -4. default format -- lowest precedence - -If the path appears to be a URL, then it is parsed. -Information is extracted from the URL, and specifically, -the fragment key "mode=" is the critical element. -The URL will be rewritten to a canonical form with the following -changes. -1. The fragment part ("#..." at the end) is parsed and the "mode=" key - is extracted and its value is converted to a list of tags. -2. If the leading protocol is not http/https, then the protocol is added - to the mode list. That protocol is then replaced with either http or https. -3. Certain singleton values inb the fragment are extracted and removed - and added to the mode list. Consider, for example, "http://....#dap4". - The "dap4" singleton is removed and added to the mode list. -4. For backward compatibility, the values of "proto=" and "protocol=" - are removed from the fragment and their value is added to the mode list. -5. The final mode list is converted to a comma separated string - and re-inserted into the fragment. -6. The final mode list is modified to remove duplicates. - -The final result is the canonical form of the URL and is returned in the -newpathp argument described above. - -*/