Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 1292

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css">
<title>Erlang -- Advanced Agent Topics</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/snmp-4.22.1.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Simple Network Management Protocol (SNMP)</strong><br><strong>User's Guide</strong><br><small>Version 4.22.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../../../../doc/js/flipmenu">
<li id="no" title="SNMP Introduction" expanded="false">SNMP Introduction<ul>
<li><a href="snmp_intro.html">
              Top of chapter
            </a></li>
<li title="Scope and Purpose"><a href="snmp_intro.html#id73205">Scope and Purpose</a></li>
<li title="Prerequisites"><a href="snmp_intro.html#id63280">Prerequisites</a></li>
<li title="Definitions"><a href="snmp_intro.html#id61217">Definitions</a></li>
<li title="About This Manual"><a href="snmp_intro.html#id66265">About This Manual</a></li>
<li title="Where to Find More Information"><a href="snmp_intro.html#id65242">Where to Find More Information</a></li>
</ul>
</li>
<li id="no" title="Agent Functional Description" expanded="false">Agent Functional Description<ul>
<li><a href="snmp_agent_funct_descr.html">
              Top of chapter
            </a></li>
<li title="Features"><a href="snmp_agent_funct_descr.html#id70043">Features</a></li>
<li title="SNMPv1, SNMPv2 and SNMPv3"><a href="snmp_agent_funct_descr.html#id69677">SNMPv1, SNMPv2 and SNMPv3</a></li>
<li title="Operation"><a href="snmp_agent_funct_descr.html#id71220">Operation</a></li>
<li title="Sub-agents and MIB Loading"><a href="snmp_agent_funct_descr.html#id75292">Sub-agents and MIB Loading</a></li>
<li title="Contexts and Communities"><a href="snmp_agent_funct_descr.html#id74241">Contexts and Communities</a></li>
<li title="Management of the Agent"><a href="snmp_agent_funct_descr.html#id74376">Management of the Agent</a></li>
<li title="Notifications"><a href="snmp_agent_funct_descr.html#id73838">Notifications</a></li>
<li title="Discovery"><a href="snmp_agent_funct_descr.html#id75718">Discovery</a></li>
</ul>
</li>
<li id="no" title="Manager Functional Description" expanded="false">Manager Functional Description<ul>
<li><a href="snmp_manager_funct_descr.html">
              Top of chapter
            </a></li>
<li title="Features"><a href="snmp_manager_funct_descr.html#id75862">Features</a></li>
<li title="Operation"><a href="snmp_manager_funct_descr.html#id76012">Operation</a></li>
<li title="MIB loading"><a href="snmp_manager_funct_descr.html#id76080">MIB loading</a></li>
</ul>
</li>
<li id="no" title="The MIB Compiler" expanded="false">The MIB Compiler<ul>
<li><a href="snmp_mib_compiler.html">
              Top of chapter
            </a></li>
<li title="Operation"><a href="snmp_mib_compiler.html#id76200">Operation</a></li>
<li title="Importing MIBs"><a href="snmp_mib_compiler.html#id76263">Importing MIBs</a></li>
<li title="MIB Consistency Checking"><a href="snmp_mib_compiler.html#id76334">MIB Consistency Checking</a></li>
<li title=".hrl File Generation"><a href="snmp_mib_compiler.html#id76371">.hrl File Generation</a></li>
<li title="Emacs Integration"><a href="snmp_mib_compiler.html#id76421">Emacs Integration</a></li>
<li title="Compiling from a Shell or a Makefile"><a href="snmp_mib_compiler.html#id76467">Compiling from a Shell or a Makefile</a></li>
<li title="Deviations from the Standard"><a href="snmp_mib_compiler.html#id76521">Deviations from the Standard</a></li>
</ul>
</li>
<li id="no" title="Running the application" expanded="false">Running the application<ul>
<li><a href="snmp_config.html">
              Top of chapter
            </a></li>
<li title="Configuring the application"><a href="snmp_config.html#id76778">Configuring the application</a></li>
<li title="Modifying the Configuration Files"><a href="snmp_config.html#id79236">Modifying the Configuration Files</a></li>
<li title="Starting the application"><a href="snmp_config.html#id79327">Starting the application</a></li>
<li title="Debugging the application"><a href="snmp_config.html#id79377">Debugging the application</a></li>
</ul>
</li>
<li id="no" title="Definition of Agent Configuration Files" expanded="false">Definition of Agent Configuration Files<ul>
<li><a href="snmp_agent_config_files.html">
              Top of chapter
            </a></li>
<li title="Agent Information"><a href="snmp_agent_config_files.html#id79867">Agent Information</a></li>
<li title="Contexts"><a href="snmp_agent_config_files.html#id79944">Contexts</a></li>
<li title="System Information"><a href="snmp_agent_config_files.html#id79997">System Information</a></li>
<li title="Communities"><a href="snmp_agent_config_files.html#id80066">Communities</a></li>
<li title="MIB Views for VACM"><a href="snmp_agent_config_files.html#id80148">MIB Views for VACM</a></li>
<li title="Security data for USM"><a href="snmp_agent_config_files.html#id80387">Security data for USM</a></li>
<li title="Notify Definitions"><a href="snmp_agent_config_files.html#id80603">Notify Definitions</a></li>
<li title="Target Address Definitions"><a href="snmp_agent_config_files.html#id80684">Target Address Definitions</a></li>
<li title="Target Parameters Definitions"><a href="snmp_agent_config_files.html#id80890">Target Parameters Definitions</a></li>
</ul>
</li>
<li id="no" title="Definition of Manager Configuration Files" expanded="false">Definition of Manager Configuration Files<ul>
<li><a href="snmp_manager_config_files.html">
              Top of chapter
            </a></li>
<li title="Manager Information"><a href="snmp_manager_config_files.html#id81118">Manager Information</a></li>
<li title="Users"><a href="snmp_manager_config_files.html#id81260">Users</a></li>
<li title="Agents"><a href="snmp_manager_config_files.html#id81361">Agents</a></li>
<li title="Security data for USM"><a href="snmp_manager_config_files.html#id81544">Security data for USM</a></li>
</ul>
</li>
<li id="no" title="Agent Implementation Example" expanded="false">Agent Implementation Example<ul>
<li><a href="snmp_impl_example_agent.html">
              Top of chapter
            </a></li>
<li title="MIB"><a href="snmp_impl_example_agent.html#id81793">MIB</a></li>
<li title="Default Implementation"><a href="snmp_impl_example_agent.html#id81833">Default Implementation</a></li>
<li title="Manual Implementation"><a href="snmp_impl_example_agent.html#id81912">Manual Implementation</a></li>
</ul>
</li>
<li id="no" title="Manager Implementation Example" expanded="false">Manager Implementation Example<ul>
<li><a href="snmp_impl_example_manager.html">
              Top of chapter
            </a></li>
<li title="The example manager"><a href="snmp_impl_example_manager.html#id82242">The example manager</a></li>
<li title="A simple standard test"><a href="snmp_impl_example_manager.html#id82333">A simple standard test</a></li>
</ul>
</li>
<li id="no" title="Instrumentation Functions" expanded="false">Instrumentation Functions<ul>
<li><a href="snmp_instr_functions.html">
              Top of chapter
            </a></li>
<li title="Instrumentation Functions"><a href="snmp_instr_functions.html#id82473">Instrumentation Functions</a></li>
<li title="Using the ExtraArgument"><a href="snmp_instr_functions.html#id83088">Using the ExtraArgument</a></li>
<li title="Default Instrumentation"><a href="snmp_instr_functions.html#id83196">Default Instrumentation</a></li>
<li title="Atomic Set"><a href="snmp_instr_functions.html#id83301">Atomic Set</a></li>
</ul>
</li>
<li id="no" title="Definition of Instrumentation Functions" expanded="false">Definition of Instrumentation Functions<ul>
<li><a href="snmp_def_instr_functions.html">
              Top of chapter
            </a></li>
<li title="Variable Instrumentation"><a href="snmp_def_instr_functions.html#id83474">Variable Instrumentation</a></li>
<li title="Table Instrumentation"><a href="snmp_def_instr_functions.html#id83849">Table Instrumentation</a></li>
</ul>
</li>
<li id="no" title="Definition of Agent Net if" expanded="false">Definition of Agent Net if<ul>
<li><a href="snmp_agent_netif.html">
              Top of chapter
            </a></li>
<li title="Mandatory Functions"><a href="snmp_agent_netif.html#id84750">Mandatory Functions</a></li>
<li title="Messages"><a href="snmp_agent_netif.html#id84772">Messages</a></li>
</ul>
</li>
<li id="no" title="Definition of Manager Net if" expanded="false">Definition of Manager Net if<ul>
<li><a href="snmp_manager_netif.html">
              Top of chapter
            </a></li>
<li title="Mandatory Functions"><a href="snmp_manager_netif.html#id85574">Mandatory Functions</a></li>
<li title="Messages"><a href="snmp_manager_netif.html#id85591">Messages</a></li>
</ul>
</li>
<li id="no" title="Audit Trail Log" expanded="false">Audit Trail Log<ul>
<li><a href="snmp_audit_trail_log.html">
              Top of chapter
            </a></li>
<li title="Agent Logging"><a href="snmp_audit_trail_log.html#id85997">Agent Logging</a></li>
<li title="Manager Logging"><a href="snmp_audit_trail_log.html#id86040">Manager Logging</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Advanced Agent Topics" expanded="true">Advanced Agent Topics<ul>
<li><a href="snmp_advanced_agent.html">
              Top of chapter
            </a></li>
<li title="When to use a Sub-agent"><a href="snmp_advanced_agent.html#id86186">When to use a Sub-agent</a></li>
<li title="Agent Semantics"><a href="snmp_advanced_agent.html#id86296">Agent Semantics</a></li>
<li title="Sub-agents and Dependencies "><a href="snmp_advanced_agent.html#id86360">Sub-agents and Dependencies </a></li>
<li title="Distributed Tables"><a href="snmp_advanced_agent.html#id86378">Distributed Tables</a></li>
<li title="Fault Tolerance"><a href="snmp_advanced_agent.html#id86434">Fault Tolerance</a></li>
<li title="Using Mnesia Tables as SNMP Tables"><a href="snmp_advanced_agent.html#id86508">Using Mnesia Tables as SNMP Tables</a></li>
<li title="Deviations from the Standard"><a href="snmp_advanced_agent.html#id86786">Deviations from the Standard</a></li>
</ul>
</li>
<li id="no" title="SNMP Appendix A" expanded="false">SNMP Appendix A<ul>
<li><a href="snmp_app_a.html">
              Top of chapter
            </a></li>
<li title="Appendix A"><a href="snmp_app_a.html#id86932">Appendix A</a></li>
</ul>
</li>
<li id="no" title="SNMP Appendix B" expanded="false">SNMP Appendix B<ul>
<li><a href="snmp_app_b.html">
              Top of chapter
            </a></li>
<li title="Appendix B"><a href="snmp_app_b.html#id87320">Appendix B</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>15 Advanced Agent Topics</h1>
  
  <p>The chapter <strong>Advanced Agent Topics</strong> describes the more advanced 
    agent related features of the SNMP development tool. The following topics 
    are covered:
    </p>
  <ul>
    <li>When to use a Sub-agent</li>
    <li>Agent semantics</li>
    <li>Sub-agents and dependencies</li>
    <li>Distributed tables</li>
    <li>Fault tolerance</li>
    <li>Using Mnesia tables as SNMP tables</li>
    <li>Audit Trail Logging</li>
    <li>Deviations from the standard
    </li>
  </ul>

  <h3><a name="id86186">15.1 
        When to use a Sub-agent</a></h3>
    
    <p>The section <strong>When to use a Sub-agent</strong> describes situations
      where the mechanism of loading and unloading MIBs is insufficient. 
      In these cases a sub-agent is needed.
      </p>

    <h4>Special Set Transaction Mechanism</h4>
      
      <p>Each sub-agent can implement its own mechanisms for
        <span class="code">set</span>, <span class="code">get</span> and <span class="code">get-next</span>. For example, if the
        application requires the <span class="code">get</span> mechanism to be
        asynchronous, or needs a N-phase <span class="code">set</span> mechanism, a
        specialized sub-agent should be used.
        </p>
      <p>The toolkit allows different kinds of sub-agents at the same
        time. Accordingly, different MIBs can have different <span class="code">set</span>
        or <span class="code">get</span> mechanisms.
        </p>
    

    <h4>Process Communication</h4>
      
      <p>A simple distributed agent can be managed without sub-agents. 
        The instrumentation functions can use distributed Erlang to 
        communicate with other parts of the application. However, a 
        sub-agent can be used on each node if this generates too much 
        unnecessary traffic. A sub-agent processes requests per 
        incoming SNMP request, not per variable. Therefore the network 
        traffic is minimized.
        </p>
      <p>If the instrumentation functions communicate with UNIX
        processes, it might be a good idea to use a special
        sub-agent. This sub-agent sends the SNMP request to the other
        process in one packet in order to minimize context switches. For
        example, if a whole MIB is implemented on the C level in UNIX,
        but you still want to use the Erlang SNMP tool, then you may
        have one special sub-agent, which sends the variables in the
        request as a single operation down to C.
        </p>
    

    <h4>Frequent Loading of MIBs</h4>
      
      <p>Loading and unloading of MIBs are quite cheap
        operations. However, if the application does this very often,
        perhaps several times per minute, it should load the MIBs once
        and for all in a sub-agent. This sub-agent only registers and
        unregisters itself under another agent instead of loading the
        MIBs each time. This is cheaper than loading an MIB.
        </p>
    

    <h4>Interaction With Other SNMP Agent Toolkits</h4>
      
      <p>If the SNMP agent needs to interact with sub-agents
        constructed in another package, a special sub-agent should be
        used, which communicates through a protocol specified by the
        other package.
        </p>
    
  

  <h3><a name="id86296">15.2 
        Agent Semantics</a></h3>
    
    <p>The agent can be configured to be multi-threaded, to process
      one incoming request at a time, or to have a request limit
      enabled (this can be used for load control or to limit the effect
      of DoS attacks). If it is multi-threaded, read requests (<span class="code">get</span>, 
      <span class="code">get-next</span> and <span class="code">get-bulk</span>) and traps are processed in 
      parallel with each other and <span class="code">set</span> requests. However, all 
      <span class="code">set</span> requests are serialized, which means that if the agent 
      is waiting for the application to complete a complicated write 
      operation, it will not process any new write requests until this 
      operation is finished. It processes read requests and sends traps, 
      concurrently. The reason for not handle write requests in parallel is 
      that a complex locking mechanism would be needed even in the simplest 
      cases. Even with the scheme described above, the user must be 
      careful not to violate that the <span class="code">set</span> requests are atoms. 
      If this is hard to do, do not use the multi-threaded feature.
      </p>
    <p>The order within an request is undefined and variables are not
      processed in a defined order. Do not assume that the first
      variable in the PDU will be processed before the second, even if
      the agent processes variables in this order. It
      cannot even be  assumed that requests belonging to different
      sub-agents have any order.
      </p>
    <p>If the manager tries to set the same variable many times in the
      same PDU, the agent is free to improvise. There is no definition
      which determines if the instrumentation will be called once or
      twice. If called once only, there is no definition that determines 
      which of the new values is going to be supplied.
      </p>
    <p>When the agent receives a request, it keeps the request ID for
      one second after the response is sent. If the agent receives
      another request with the same request ID during this time, from
      the same IP address and UDP port, that request will be
      discarded. This mechanism has nothing to do with the function
      <span class="code">snmpa:current_request_id/0</span>.</p>
  

  <h3><a name="id86360">15.3 
        Sub-agents and Dependencies </a></h3>
    
    <p>The toolkit supports the use of different types of sub-agents,
      but not the construction of sub-agents.
      </p>
    <p>Also, the toolkit does not support dependencies between
      sub-agents. A sub-agent should by definition be stand alone and it is
      therefore not good design to create dependencies between them.
      </p>
  

  <h3><a name="id86378">15.4 
        Distributed Tables</a></h3>
    
    <p>A common situation in more complex systems is that the data in
      a table is distributed. Different table rows are implemented in
      different places. Some SNMP tool-kits dedicate an SNMP sub-agent for
      each part of the table and load the corresponding MIB into all
      sub-agents. The Master Agent is responsible for presenting the
      distributed table as a single table to the manager. The toolkit
      supplied uses a different method.
      </p>
    <p>The method used to implement distributed tables with this SNMP
      tool is to implement a table coordinator process responsible for 
      coordinating the processes, which hold the table data and they 
      are called  table holders. All table holders must in some way be 
      known by the coordinator; the structure of the table data 
      determines how this is achieved. The coordinator may require 
      that the table holders explicitly register themselves and specify 
      their information. In other cases, the table holders can be 
      determined once at compile time.
      </p>
    <p>When the instrumentation function for the distributed table is
      called, the request should be forwarded to the table
      coordinator. The coordinator finds the requested information among
      the table holders and then returns the answer to the
      instrumentation function. The SNMP toolkit contains no support for
      coordination of tables since this must be independent of the
      implementation.
      </p>
    <p>The advantages of separating the table coordinator from the
      SNMP tool are:
      </p>
    <ul>
      <li>We do not need a sub-agent for each table holder. Normally,
       the sub-agent is needed to take care of communication, but in
       Distributed Erlang we use ordinary message passing.
      </li>
      <li>Most likely, some type of table coordinator already
       exists. This process should take care of the instrumentation for
       the table.
      </li>
      <li>The method used to present a distributed table is strongly
       application dependent. The use of different masking techniques
       is only valid for a small subset of problems and registering
       every row in a distributed table makes it non-distributed.
      </li>
    </ul>
  

  <h3><a name="id86434">15.5 
        Fault Tolerance</a></h3>
    
    <p>The SNMP agent toolkit gets input from three different sources:
      </p>
    <ul>
      <li>UDP packets from the network</li>
      <li>return values from the user defined instrumentation functions</li>
      <li>return values from the MIB.
      </li>
    </ul>
    <p>The agent is highly fault tolerant. If the manager gets an
      unexpected response from the agent, it is possible that some
      instrumentation function has returned an erroneous value. The
      agent will not crash even if the instrumentation does. It should
      be noted that if an instrumentation function enters an infinite
      loop, the agent will also be blocked forever. The supervisor ,or
      the application, specifies how to restart the agent.
      </p>

    <h4>Using the SNMP Agent in a Distributed Environment</h4>
      
      <p>The normal way to use the agent in a distributed
        environment is to use one master agent located at one node,
        and zero or more sub-agents located on other nodes.  However,
        this configuration makes the master agent node a single point
        of failure.  If that node goes down, the agent will not work.
        </p>
      <p>One solution to this problem is to make the snmp application
        a distributed Erlang application, and that means, the agent
        may be configured to run on one of several nodes.  If the node
        where it runs goes down, another node restarts the agent.
        This is called <strong>failover</strong>.  When the node starts again,
        it may  <strong>takeover</strong> the application.  This solution to
        the problem adds another problem.  Generally, the new node has
        another IP address than the first one, which may cause
        problems in the  communication between the SNMP managers and
        the agent.
        </p>
      <p>If the snmp agent is configured as a distributed Erlang
        application, it will during takeover try to load the same MIBs
        that were loaded at the old node. It uses the same filenames
        as the old node. If the MIBs are not located in the same
        paths at the different nodes, the MIBs must be loaded
        explicitly after takeover.
        </p>
    
  

  <h3><a name="id86508">15.6 
        Using Mnesia Tables as SNMP Tables</a></h3>
    
    <p>The Mnesia DBMS can be used for storing data of SNMP
      tables. This means that an SNMP table can be implemented as a
      Mnesia table, and that a Mnesia table can be made visible via
      SNMP. This mapping is largely automated.
      </p>
    <p>There are three main reasons for using this mapping:
      </p>
    <ul>
      <li>We get all features of Mnesia, such as fault tolerance,
       persistent data storage, replication, and so on.
      </li>
      <li>Much of the work involved is automated. This includes
      <span class="code">get-next</span> processing and <span class="code">RowStatus</span> handling.
      </li>
      <li>The table may be used as an ordinary Mnesia table, using
       the Mnesia API internally in the application at the same time as
       it is visible through SNMP.
      </li>
    </ul>
    <p>When this mapping is used, insertion and deletion in the
      original Mnesia table is slower, with a factor O(log n). The read
      access is not affected.
      </p>
    <p>A drawback with implementing an SNMP table as a Mnesia table is
      that the internal resource is forced to use the table definition
      from the MIB, which means that the external data model must be
      used internally. Actually, this is only partially true. The Mnesia
      table may extend the SNMP table, which means that the Mnesia table
      may have columns which are use internally and are not seen by
      SNMP. Still, the data model from SNMP must be maintained. Although
      this is undesirable, it is a pragmatic compromise in many
      situations where simple and efficient implementation is preferable
      to abstraction.
      </p>

    <h4>Creating the Mnesia Table</h4>
      
      <p>The table must be created in Mnesia before the manager can
        use it. The table must be declared as type <span class="code">snmp</span>.  This
        makes the table ordered in accordance with the lexicographical
        ordering rules of SNMP.  The name of the Mnesia table must be
        identical to the SNMP table name.  The types of the INDEX fields
        in the corresponding SNMP table must be specified.
        </p>
      <p>If the SNMP table has more than one INDEX column, the
        corresponding Mnesia row is a tuple, where the first element 
        is a tuple with the INDEX columns. Generally, if the SNMP table 
        has <strong>N</strong> INDEX columns and <strong>C</strong> data columns, the 
        Mnesia table is of arity <strong>(C-N)+1</strong>, where the key is a 
        tuple of arity <strong>N</strong> if <strong>N &gt; 1</strong>, or a single term 
        if <strong>N = 1</strong>.
        </p>
      <p>Refer to the Mnesia User's Guide for information on how to
        declare a Mnesia table as an SNMP table.
        </p>
      <p>The following example illustrates a situation in which we
        have an SNMP table that we wish to implement as a Mnesia
        table. The table stores information about employees at a
        company. Each employee is indexed with the department number and
        the name.
        </p>
      <div class="example"><pre>
       empTable OBJECT-TYPE
              SYNTAX      SEQUENCE OF EmpEntry
              ACCESS      not-accessible
              STATUS      mandatory
              DESCRIPTION
                      "A table with information about employees."
       ::= { emp 1}
       empEntry OBJECT-TYPE
              SYNTAX      EmpEntry
              ACCESS      not-accessible
              STATUS      mandatory
              DESCRIPTION
                 ""
              INDEX      { empDepNo, empName }
       ::= { empTable 1 }
       EmpEntry ::=
              SEQUENCE {
                  empDepNo         INTEGER,
                  empName          DisplayString,
                  empTelNo         DisplayString
                  empStatus        RowStatus
              }
      </pre></div>
      <p>The corresponding Mnesia table is specified as follows:
        </p>
      <div class="example"><pre>
mnesia:create_table([{name, employees},
                     {snmp, [{key, {integer, string}}]},
                     {attributes, [key, telno, row_status]}]).
      </pre></div>
      <div class="note">
<div class="label">Note</div>
<div class="content"><p>
        <p>In the Mnesia tables, the two key columns are stored as a
          tuple with two elements. Therefore, the arity of the table is
          3.</p>
      </p></div>
</div>
    

    <h4>Instrumentation Functions</h4>
      
      <p>The MIB table shown in the previous section can be compiled
        as follows:
        </p>
      <div class="example"><pre>
1&gt; <span class="bold_code">snmpc:compile("EmpMIB", [{db, mnesia}]).</span>
      </pre></div>
      <p>This is all that has to be done! Now the manager can read,
        add, and modify rows. Also, you can use the ordinary Mnesia API
        to access the table from your programs. The only explicit action
        is to create the Mnesia table, an action the user has to perform
        in order to create the required table schemas.</p>
    

    <h4>Adding Own Actions</h4>
      
      <p>It is often necessary to take some specific action when a
        table is modified. This is accomplished with an instrumentation
        function. It executes some specific code when the table is set,
        and passes all other requests down to the pre-defined function.
        </p>
      <p>The following example illustrates this idea:
        </p>
      <div class="example"><pre>
emp_table(set, RowIndex, Cols) -&gt;
    notify_internal_resources(RowIndex, Cols),
    snmp_generic:table_func(set, RowIndex, Cols, {empTable, mnesia});
emp_table(Op, RowIndex, Cols) -&gt;
    snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).
      </pre></div>
      <p>The default instrumentation functions are defined in the
        module <span class="code">snmp_generic</span>. Refer to the Reference Manual,
        section SNMP, module <span class="code">snmp_generic</span> for details.</p>
    

    <h4>Extending the Mnesia Table</h4>
      
      <p>A table may contain columns that are used internally, but
        should not be visible to a manager. These internal columns must
        be the last columns in the table. The <span class="code">set</span> operation will
        not work with this arrangement, because there are columns that
        the agent does not know about. This situation is handled by
        adding values for the internal columns in the <span class="code">set</span>
        function.
        </p>
      <p>To illustrate this, suppose we extend our Mnesia
        <span class="code">empTable</span> with one internal column. We create it as
        before, but with an arity of 4, by adding another attribute.
        </p>
      <div class="example"><pre>
mnesia:create_table([{name, employees},
                     {snmp, [{key, {integer, string}}]},
                     {attributes, {key, telno, row_status, internal_col}}]).
      </pre></div>
      <p>The last column is the internal column. When performing a
        <span class="code">set</span> operation, which creates a row, we must give a
        value to the internal column. The instrumentation functions will now
        look as follows:
        </p>
      <div class="example"><pre>
-define(createAndGo, 4).
-define(createAndWait, 5).

emp_table(set, RowIndex, Cols) -&gt;
  notify_internal_resources(RowIndex, Cols),
  NewCols =
    case is_row_created(empTable, Cols) of
      true -&gt; Cols ++ [{4, "internal"}]; % add internal column
      false -&gt; Cols                      % keep original cols
  end,
  snmp_generic:table_func(set, RowIndex, NewCols, {empTable, mnesia});
emp_table(Op, RowIndex, Cols) -&gt;
  snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).

is_row_created(Name, Cols) -&gt;
  case snmp_generic:get_status_col(Name, Cols) of
    {ok, ?createAndGo} -&gt; true;
    {ok, ?createAndWait} -&gt; true;
    _ -&gt; false
  end.
      </pre></div>
      <p>If a row is created, we always set the internal column to
        <span class="code">"internal"</span>.
        </p>
    
  

  <h3><a name="id86786">15.7 
        Deviations from the Standard</a></h3>
    
    <p>In some aspects the agent does not implement SNMP fully.  Here
      are the differences:
      </p>
    <ul>
      <li>The default functions and <span class="code">snmp_generic</span> cannot
       handle an object of type <span class="code">NetworkAddress</span> as INDEX
       (SNMPv1 only!).  Use <span class="code">IpAddress</span> instead.
      </li>
      <li>The agent does not check complex ranges specified for
       INTEGER objects.  In these cases it just checks that the value
       lies within the minimum and maximum values specified.  For
       example, if the range is specified as <span class="code">1..10 | 12..20</span>
       the agent would let 11 through, but not 0 or 21.  The
       instrumentation functions must check the complex ranges
       itself.
      </li>
      <li>The agent will never generate the <span class="code">wrongEncoding</span>
       error.  If a variable binding is erroneous encoded, the
      <span class="code">asn1ParseError</span> counter will be incremented.
      </li>
      <li>A <span class="code">tooBig</span> error in an SNMPv1 packet will always use
       the <span class="code">'NULL'</span> value in all variable bindings.
      </li>
      <li>The default functions and <span class="code">snmp_generic</span> do not check
       the range of each OCTET in textual conventions derived from
       OCTET STRING, e.g. <span class="code">DisplayString</span> and
      <span class="code">DateAndTime</span>.  This must be checked in an overloaded
      <span class="code">is_set_ok</span> function.
      </li>
    </ul>
  
</div>
<div class="footer">
<hr>
<p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>