Sophie

Sophie

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

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 -- Agent Implementation Example</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="loadscrollpos" title="Agent Implementation Example" expanded="true">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="no" title="Advanced Agent Topics" expanded="false">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>8 Agent Implementation Example</h1>
  
  <p>This <strong>Implementation Example</strong> section describes how an
    MIB can be implemented with the SNMP Development Toolkit. </p>
  <p>The example shown can be found in the toolkit distribution. </p>
  <p>The agent is configured with the configuration tool, using
    default suggestions for everything but the manager node. </p>

  <h3><a name="id81793">8.1 
        MIB</a></h3>
    
    <p>The MIB used in this example is called EX1-MIB. It contains two
      objects, a variable with a name and a table with friends.
      </p>
    <div class="example"><pre>
EX1-MIB DEFINITIONS ::= BEGIN
 
          IMPORTS
                  RowStatus      FROM STANDARD-MIB
                  DisplayString  FROM RFC1213-MIB
                  OBJECT-TYPE    FROM RFC-1212
                  ;
 
          example1       OBJECT IDENTIFIER ::= { experimental 7 }
 
          myName OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "My own name"
              ::= { example1 1 }
 
          friendsTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF FriendsEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "A list of friends."
              ::= { example1 4 }
 
          friendsEntry OBJECT-TYPE
              SYNTAX  FriendsEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      ""
              INDEX   { fIndex }
              ::= { friendsTable 1 }
 
          FriendsEntry ::=
              SEQUENCE {
            fIndex
                      INTEGER,
                   fName
                      DisplayString,
                   fAddress
                      DisplayString,
                   fStatus
                      RowStatus              }
 
          fIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  not-accessible
              STATUS  mandatory
               DESCRIPTION
                      "number of friend"
              ::= { friendsEntry 1 }
 
          fName OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "Name of friend"
              ::= { friendsEntry 2 }
          fAddress OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "Address of friend"
              ::= { friendsEntry 3 }
           fStatus OBJECT-TYPE
              SYNTAX      RowStatus
              ACCESS      read-write
              STATUS      mandatory
              DESCRIPTION
                      "The status of this conceptual row."
              ::= { friendsEntry 4 }
          fTrap TRAP-TYPE
              ENTERPRISE  example1
              VARIABLES   { myName, fIndex }
              DESCRIPTION
                          "This trap is sent when something happens to
         the friend specified by fIndex."
              ::= 1
END
    </pre></div>
  

  <h3><a name="id81833">8.2 
        Default Implementation</a></h3>
    
    <p>Without writing any instrumentation functions, we can compile
      the MIB and use the default implementation of it. Recall that MIBs
      imported by "EX1-MIB.mib" must be present and compiled in the
      current directory ("./STANDARD-MIB.bin","./RFC1213-MIB.bin") when
      compiling.
      </p>
    <div class="example"><pre>
unix&gt; <span class="bold_code">erl -config ./sys</span>
1&gt; <span class="bold_code">application:start(snmp).</span>
ok
2&gt; <span class="bold_code">snmpc:compile("EX1-MIB").</span>
No accessfunction for 'friendsTable', using default.
No accessfunction for 'myName', using default.
{ok, "EX1-MIB.bin"}
3&gt; <span class="bold_code">snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).</span>
ok
    </pre></div>
    <p>This MIB is now loaded into the agent, and a manager can ask
      questions. As an example of this, we start another Erlang system
      and the simple Erlang manager in the toolkit:
      </p>
    <div class="example"><pre>
1&gt; <span class="bold_code">snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},</span>
 %% making it understand symbolic names: {mibs,["EX1-MIB","STANDARD-MIB"]}]).
{ok, &lt;0.89.0&gt;}
%% a get-next request with one OID.
2&gt; <span class="bold_code">snmp_test_mgr:gn([[1,3,6,1,3,7]]).</span>
ok 
* Got PDU:
[myName,0] = [] 
%% A set-request (now using symbolic names for convenience)
3&gt; <span class="bold_code">snmp_test_mgr:s([{[myName,0], "Martin"}]).</span>
ok                           
* Got PDU:
[myName,0] = "Martin"    
%% Try the same get-next request again
4&gt; <span class="bold_code">snmp_test_mgr:gn([[1,3,6,1,3,7]]).</span>
ok                           
* Got PDU:
[myName,0] = "Martin"    
%% ... and we got the new value.
%% you can event do row operations. How to add a row:
5&gt; <span class="bold_code">snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).</span>
 %% createAndGo
ok
* Got PDU:
[fName,0] = "Martin"    
[fAddress,0] = "home"    
[fStatus,0] = 4    
6&gt; <span class="bold_code">snmp_test_mgr:gn([[myName,0]]).</span>
ok
* Got PDU:
[fName,0] = "Martin"    
7&gt; <span class="bold_code">snmp_test_mgr:gn().</span>
ok
* Got PDU:
[fAddress,0] = "home"    
8&gt; <span class="bold_code">snmp_test_mgr:gn().</span>
ok
* Got PDU:
[fStatus,0] = 1    
9&gt; 
    </pre></div>
  

  <h3><a name="id81912">8.3 
        Manual Implementation</a></h3>
    
    <p>The following example shows a "manual" implementation of the
      EX1-MIB in Erlang.  In this example, the values of the objects are
      stored in an Erlang server.  The server has a 2-tuple as loop
      data, where the first element is the value of variable
      <span class="code">myName</span>, and the second is a sorted list of rows in the
      table <span class="code">friendsTable</span>.  Each row is a 4-tuple.
      </p>
    <div class="note">
<div class="label">Note</div>
<div class="content"><p>
      <p>There are more efficient ways to create tables manually, i.e.
        to use the module <span class="code">snmp_index</span>.</p>
    </p></div>
</div>

    <h4>Code</h4>
      
      <div class="example"><pre>
-module(ex1).
-author('dummy@flop.org').
%% External exports
-export([start/0, my_name/1, my_name/2, friends_table/3]).
%% Internal exports
-export([init/0]).
-define(status_col, 4).
-define(active, 1).
-define(notInService, 2).
-define(notReady, 3).
-define(createAndGo, 4).   % Action; written, not read
-define(createAndWait, 5). % Action; written, not read
-define(destroy, 6).       % Action; written, not read
start() -&gt;
    spawn(ex1, init, []).
%%----------------------------------------------------------------
%% Instrumentation function for variable myName.
%% Returns: (get) {value, Name}
%%          (set) noError
%%----------------------------------------------------------------
my_name(get) -&gt;
    ex1_server ! {self(), get_my_name},
    Name = wait_answer(),
    {value, Name}.
my_name(set, NewName) -&gt;
    ex1_server ! {self(), {set_my_name, NewName}},
    noError.
%%----------------------------------------------------------------
%% Instrumentation function for table friendsTable.
%%----------------------------------------------------------------
friends_table(get, RowIndex, Cols) -&gt;
    case get_row(RowIndex) of
   {ok, Row} -&gt;
        get_cols(Cols, Row);
   _  -&gt;
        {noValue, noSuchInstance}
    end;
friends_table(get_next, RowIndex, Cols) -&gt;
    case get_next_row(RowIndex) of
   {ok, Row} -&gt;
        get_next_cols(Cols, Row);
   _  -&gt;
       case get_next_row([]) of
     {ok, Row} -&gt;
         % Get next cols from first row.
         NewCols = add_one_to_cols(Cols),
         get_next_cols(NewCols, Row);
     _  -&gt;
        end_of_table(Cols)
        end
    end;
%%----------------------------------------------------------------
%% If RowStatus is set, then:
%%    *) If set to destroy, check that row does exist
%%    *) If set to createAndGo, check that row does not exist AND
%%         that all columns are given values.
%%    *) Otherwise, error (for simplicity).
%% Otherwise, row is modified; check that row exists.
%%----------------------------------------------------------------
friends_table(is_set_ok, RowIndex, Cols) -&gt;
    RowExists = 
   case get_row(RowIndex) of
        {ok, _Row} -&gt; true;
       _ -&gt; false
   end, 
    case is_row_status_col_changed(Cols) of
   {true, ?destroy} when RowExists == true -&gt;
        {noError, 0};
   {true, ?createAndGo} when RowExists == false,
                                 length(Cols) == 3 -&gt;
        {noError, 0};
   {true, _} -&gt;
       {inconsistentValue, ?status_col};
   false when RowExists == true -&gt;
        {noError, 0};
   _ -&gt;
        [{Col, _NewVal} | _Cols] = Cols,
       {inconsistentName, Col}
      end;
friends_table(set, RowIndex, Cols) -&gt;
    case is_row_status_col_changed(Cols) of
   {true, ?destroy} -&gt;
        ex1_server ! {self(), {delete_row, RowIndex}};
   {true, ?createAndGo} -&gt;
       NewRow = make_row(RowIndex, Cols),
        ex1_server ! {self(), {add_row, NewRow}};
   false -&gt;
       {ok, Row} = get_row(RowIndex),
        NewRow = merge_rows(Row, Cols),
    ex1_server ! {self(), {delete_row, RowIndex}},
       ex1_server ! {self(), {add_row, NewRow}}
   end,
    {noError, 0}.
    
%%----------------------------------------------------------------
%% Make a list of {value, Val} of the Row and Cols list.
%%----------------------------------------------------------------
get_cols([Col | Cols], Row) -&gt;
    [{value, element(Col, Row)} | get_cols(Cols, Row)];
get_cols([], _Row) -&gt;
    [].
%%----------------------------------------------------------------
%% As get_cols, but the Cols list may contain invalid column
%% numbers. If it does, we must find the next valid column,
%% or return endOfTable.
%%----------------------------------------------------------------
get_next_cols([Col | Cols], Row) when Col &lt; 2 -&gt;
    [{[2, element(1, Row)], element(2, Row)} | 
     get_next_cols(Cols, Row)];
get_next_cols([Col | Cols], Row) when Col &gt; 4 -&gt;
    [endOfTable | 
     get_next_cols(Cols, Row)];
get_next_cols([Col | Cols], Row) -&gt;
    [{[Col, element(1, Row)], element(Col, Row)} | 
     get_next_cols(Cols, Row)];
get_next_cols([], _Row) -&gt;
    [].
%%----------------------------------------------------------------
%% Make a list of endOfTable with as many elems as Cols list.
%%----------------------------------------------------------------
end_of_table([Col | Cols]) -&gt;
    [endOfTable | end_of_table(Cols)];
end_of_table([]) -&gt;
    [].
add_one_to_cols([Col | Cols]) -&gt;
    [Col + 1 | add_one_to_cols(Cols)];
add_one_to_cols([]) -&gt;
    [].
is_row_status_col_changed(Cols) -&gt;
    case lists:keysearch(?status_col, 1, Cols) of
   {value, {?status_col, StatusVal}} -&gt;
        {true, StatusVal};
   _ -&gt; false
    end.
get_row(RowIndex) -&gt;
    ex1_server ! {self(), {get_row, RowIndex}},
    wait_answer().
get_next_row(RowIndex) -&gt;
    ex1_server ! {self(), {get_next_row, RowIndex}},
    wait_answer().
wait_answer() -&gt;
    receive
   {ex1_server, Answer} -&gt;
     Answer
    end.
%%%---------------------------------------------------------------
%%% Server code follows
%%%---------------------------------------------------------------
init() -&gt;
    register(ex1_server, self()),
    loop("", []).
    
loop(MyName, Table) -&gt;
    receive
   {From, get_my_name} -&gt;
        From ! {ex1_server, MyName},
       loop(MyName, Table);
   {From, {set_my_name, NewName}} -&gt;
        loop(NewName, Table);
   {From, {get_row, RowIndex}} -&gt;
       Res = table_get_row(Table, RowIndex),
       From ! {ex1_server, Res},
       loop(MyName, Table);
   {From, {get_next_row, RowIndex}} -&gt;
       Res = table_get_next_row(Table, RowIndex),
        From ! {ex1_server, Res},
       loop(MyName, Table);
   {From, {delete_row, RowIndex}} -&gt;
    NewTable = table_delete_row(Table, RowIndex),
       loop(MyName, NewTable);
   {From, {add_row, NewRow}} -&gt;
       NewTable = table_add_row(Table, NewRow),
       loop(MyName, NewTable)
    end.
%%%---------------------------------------------------------------
%%% Functions for table operations. The table is represented as
%%% a list of rows.
%%%---------------------------------------------------------------
table_get_row([{Index, Name, Address, Status} | _], [Index]) -&gt;
    {ok, {Index, Name, Address, Status}};
table_get_row([H | T], RowIndex) -&gt;
    table_get_row(T, RowIndex);
table_get_row([], _RowIndex) -&gt;
    no_such_row.
table_get_next_row([Row | T], []) -&gt;
    {ok, Row};
table_get_next_row([Row | T], [Index | _]) 
when element(1, Row) &gt; Index -&gt;
    {ok, Row};
table_get_next_row([Row | T], RowIndex) -&gt;
    table_get_next_row(T, RowIndex);
table_get_next_row([], RowIndex) -&gt;
    endOfTable.
table_delete_row([{Index, _, _, _} | T], [Index]) -&gt;
    T;
table_delete_row([H | T], RowIndex) -&gt;
    [H | table_delete_row(T, RowIndex)];
table_delete_row([], _RowIndex) -&gt;
    [].
table_add_row([Row | T], NewRow) 
  when element(1, Row) &gt; element(1, NewRow) -&gt;
    [NewRow, Row | T];
table_add_row([H | T], NewRow) -&gt;
    [H | table_add_row(T, NewRow)];
table_add_row([], NewRow) -&gt;
    [NewRow].
make_row([Index], [{2, Name}, {3, Address} | _]) -&gt;
    {Index, Name, Address, ?active}.
merge_rows(Row, [{Col, NewVal} | T]) -&gt;
    merge_rows(setelement(Col, Row, NewVal), T);
merge_rows(Row, []) -&gt;
    Row.
      </pre></div>
    

    <h4>Association File</h4>
      
      <p>The association file <span class="code">EX1-MIB.funcs</span> for the real
        implementation looks as follows:
        </p>
      <div class="example"><pre>
{myName, {ex1, my_name, []}}.
{friendsTable, {ex1, friends_table, []}}.
      </pre></div>
    

    <h4>Transcript</h4>
      
      <p>To use the real implementation, we must recompile the MIB and
        load it into the agent.
        </p>
      <div class="example"><pre>
1&gt; <span class="bold_code">application:start(snmp).</span>
ok
2&gt; <span class="bold_code">snmpc:compile("EX1-MIB").</span>
{ok,"EX1-MIB.bin"}
3&gt; <span class="bold_code">snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).</span>
ok
4&gt; <span class="bold_code">ex1:start().</span>
&lt;0.115.0&gt;
%% Now all requests operates on this "real" implementation.
%% The output from the manager requests will *look* exactly the
%% same as for the default implementation.
      </pre></div>
    

    <h4>Trap Sending</h4>
      
      <p>How to send a trap by sending the
        <span class="code">fTrap</span> from the master agent is shown in this section. 
        The master agent has the MIB <span class="code">EX1-MIB</span> loaded, where the 
        trap is defined. This trap specifies that two variables should 
        be sent along with the trap, <span class="code">myName</span> and <span class="code">fIndex</span>. 
        <span class="code">fIndex</span> is a table column, so we must provide its value 
        and the index for the row in the call to <span class="code">snmpa:send_trap/4</span>. 
        In the example below, we assume that the row in question is 
        indexed by 2 (the row with <span class="code">fIndex</span> 2).
        </p>
      <p>we use a simple Erlang SNMP manager, which can receive traps.
        </p>
      <div class="example"><pre>
[MANAGER]
1&gt; <span class="bold_code">snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"public"}</span>
 %% does not have write-access
1&gt;<span class="bold_code">{mibs,["EX1-MIB","STANDARD-MIB"]}]).</span>
{ok, &lt;0.100.0&gt;}
2&gt; <span class="bold_code">snmp_test_mgr:s([{[myName,0], "Klas"}]).</span>
ok                           
* Got PDU:
Received a trap:
      Generic: 4       %% authenticationFailure
   Enterprise: [iso,2,3]
     Specific: 0
   Agent addr: [123,12,12,21]
    TimeStamp: 42993
2&gt; 
[AGENT]
3&gt; <span class="bold_code">snmpa:send_trap(snmp_master_agent, fTrap,"standard trap", [{fIndex,[2],2}]).</span>
[MANAGER]
2&gt;
* Got PDU:
Received a trap:             
      Generic: 6
   Enterprise: [example1]
     Specific: 1
   Agent addr: [123,12,12,21]
    TimeStamp: 69649
[myName,0] = "Martin"    
[fIndex,2] = 2    
2&gt;
      </pre></div>
    
  
</div>
<div class="footer">
<hr>
<p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>