    ============
    MFD template
    ============

The templates generated by the MFD configuration file (mib2c.mfd.conf) fall into
several categories: data structures, data lookup and data manipulation. Data
structures contain the data used to answer a request. Data lookup is finding the
right data for a request. Data manipulation is either returning existing values
or setting new values.


    Data structures
    ---------------

- User context: The user context is a pointer provided by user during module
initialization. It is not used by the MFD code, other than to save it for
the user. If your module needs access to some external data, you can use this
pointer instead of a global variable.

- MIB context: The MIB context is a generated structure which is used to store
the MIB indexes for a row.

- Data context: The data context structure should contain all the data needed
to get or set a value.

- Row request context: The row request context ties together all the other
contexts. The table container will have a row request context for each row in
the table.


    Data lookup
    -----------

There are lots of different ways to access data. The netsnmp_container interface
is used here. There are also several different interfaces between the MFD
template code and the netsnmp_container used to locate data for a request
(container-cached, iterator, direct). We use the container-cached interface:

The default method, which is generic enough to handle just about any situation,
is the container-cached method. It combines two features of net-snmp: the cache
helper and the netsnmp_container. Quite simply, the first time a request is
received for a table, a cache_load routine is called with a pointer to a
netsnmp_container. That function accesses any datastore(s) that contain data,
and adds all the rows to the container. The container is then used to find the
rows for the incoming request, and (optionally) kept around a configurable
number of seconds for future requests. While the basic principle is simple,
the flexiblity makes this method the preferred method for most situations.


    Data manipulation
    -----------------

Once the appropriate data structure is retrieved from the data store, the data
manipulation routines will be called. For each object defined in your mib
module, a function will be generated to extract the data value from the data
structure located during the data lookup phase.

For read-write objects, things get more complicated. SET requests are processed
in multiple steps, so there are multiple functions generated for each object.
These include functions for syntax checks, value checks, undo setup, value set
and undo value set. Additionlly, several functions are generated per table, for
tasks which only need to be performed once, even if multiple objects are set
for a given index. Two examples are consistency checks and commit changes.
See the states flow diagram in the xxxTable_data_set.c for a better
understanding.



    Function flow examples
    ----------------------

To give you the general idea of how the functions flow works, this
example flow is from a complete table implementation.

NOTE: Depending on your configuration, some of the functions used in the
      examples below  may not have been generated.

      Conversely, the examples below may not include some functions that
      were generated.


Initialization
--------------------------------
init_xxxTable: called                           xxx.c
   initialize_table_xxxTable                    xxx.c
      _xxxTable_initialize_interface            xxx_interface.c
         xxxTable_init_data                     xxx_data_access.c
      _xxxTable_container_init                  xxx_interface.c
         xxxTable_container_init                xxx_data_access.c


GET Request
--------------------------------
_cache_load                                     xxx_interface.c
   xxxTable_cache_load                          xxx_data_access.c
      xxxTable_allocate_rowreq_ctx              xxx_interface.c
         xxxTable_allocate_data                 xxx_data_get.c
         xxxTable_rowreq_ctx_init               xxx_data_get.c
      xxxTable_indexes_set                      xxx_data_get.c
         xxxTable_indexes_set_tbl_idx           xxx_data_get.c

xxxTable_pre_request

_mfd_xxxTable_object_lookup                     xxx_interface.c
   xxxTable_row_prep                            xxx_data_access.c

_mfd_xxxTable_get_values                        xxx_interface.c
   _mfd_xxxTable_get_column                     xxx_interface.c
      yyy_get                                   xxx_data_get.c

xxxTable_post_request


GETNEXT Request
--------------------------------
_cache_load                                     ...
xxxTable_pre_request                            ...
_mfd_xxxTable_object_lookup                     ...
_mfd_xxxTable_get_values                        ...
xxxTable_post_request                           ...


SET Request: success
--------------------------------
_cache_load                                     ...
xxxTable_pre_request
_mfd_xxxTable_object_lookup                     ...

_mfd_xxxTable_check_objects                     xxx_interface.c
   _xxxTable_check_column                       xxx_interface.c
      yyy_check_value                           xxx_data_set.c

_mfd_xxxTable_undo_setup                        xxx_interface.c
   xxxTable_allocate_data                       ...
   xxxTable_undo_setup                          xxx_interface.c
      _xxxTable_undo_setup_column               xxx_interface.c
         yyy_undo_setup                         xxx_data_set.c

_mfd_xxxTable_set_values                        xxx_interface.c
   _xxxTable_set_column                         xxx_interface.c
      yyy_set                                   xxx_data_set.c

_mfd_xxxTable_check_dependencies                xxx_interface.c
   xxxTable_check_dependencies                  xxx_data_set.c

_mfd_xxxTable_commit                            xxx_interface.c
   xxxTable_commit                              xxx_data_set.c

_mfd_xxxTable_undo_cleanup                      xxx_interface.c
   xxxTable_undo_cleanup                        xxx_data_set.c
      xxxTable_release_data                     ...

xxxTable_post_request                           ...


SET Request: row creation
--------------------------------
_cache_load                                     ...
xxxTable_pre_request

_mfd_xxxTable_object_lookup                     ...
   xxxTable_index_from_oid                      xxx_interface.c
   xxxTable_allocate_rowreq_ctx                 ...
      ...
   _xxxTable_check_indexes                      xxx_interface.c
      yyy_check_index                           xxx_data_set.c
      xxxTable_validate_index                   xxx_data_set.c

_mfd_xxxTable_check_objects                     ...
   _xxxTable_check_column                       ...
      yyy_check_value                           ...
   _xxxTable_check_column                       ...
      yyy_check_value                           ...

_mfd_xxxTable_undo_setup                        ...
_mfd_xxxTable_set_values                        ...
_mfd_xxxTable_check_dependencies                ...
_mfd_xxxTable_commit                            ...
_mfd_xxxTable_undo_cleanup                      ...
xxxTable_post_request                           ...


SET Resuest: value error
--------------------------------
_cache_load                                     ...
xxxTable_pre_request                            ...
_mfd_xxxTable_object_lookup                     ...

_mfd_xxxTable_check_objects                     ...
   _xxxTable_check_column                       ...
      yyy_check_value                           ...
      ERROR:"yyy value not supported"

xxxTable_post_request                           ...


SET Request: commit failure
--------------------------------
_cache_load                                     ...
xxxTable_pre_request                            ...
_mfd_xxxTable_object_lookup                     ...
_mfd_xxxTable_check_objects                     ...
_mfd_xxxTable_undo_setup                        ...
_mfd_xxxTable_set_values                        ...
_mfd_xxxTable_check_dependencies                ...

_mfd_xxxTable_commit                            ...
   xxxTable_commit                              ...
   ERROR: bad rc -1

_mfd_xxxTable_undo_commit                       xxx_interface.c
   xxxTable_undo_commit                         xxx_data_set.c

_mfd_xxxTable_undo_values                       xxx_interface.c
   _xxxTable_undo_column                        xxx_interface.c
      yyy_undo                                  xxx_data_set.c

_mfd_xxxTable_undo_cleanup                      ...
xxxTable_post_request                           ...


Row release (user initiated)
--------------------------------
xxxTable_release_rowreq_ctx                     xxx_interface.c
   xxxTable_rowreq_ctx_cleanup                  xxx_data_get.c
   xxxTable_release_data                        xxx_data_get.c





NOTE: This text is mostly based on the tutorial found at
http://net-snmp.sourceforge.net/tutorial/tutorial-5/toolkit/mfd/ and on the
README files auto-generated with the mib2c.mfd.conf template.
