Architecture - Tables
FriendlySNMP API presents tables declared in MIBs as
org.friendlysnmp.FTable
class objects.
This class architecture is very similar to
a
org.friendlysnmp.FScalar class.
Refer to Scalar to learn basics.
How and where tables are created
The following discussion uses a table flightEntry declared in
DEMO-TABLE-FLIGHT-MIB
from a demo application as an example.
This table is defined in the MIB as follows:
flightTable OBJECT-TYPE
SYNTAX SEQUENCE OF FlightEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "Table of Flights"
::= { demoMIBObjects 13 }
flightEntry OBJECT-TYPE
SYNTAX FlightEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "Row with flight info"
INDEX { flightIndex }
::= { flightTable 1 }
FlightEntry ::= SEQUENCE {
flightIndex Unsigned32,
flightCarrier DisplayString,
...more definitions here...
flightRowStatus RowStatus
}
flightIndex OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "This is a table column: INDEX"
::= { flightEntry 2 }
flightCarrier OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-create
STATUS current
DESCRIPTION "This is a table column: flight carrier."
::= { flightEntry 10 }
...more definitions here...
flightRowStatus OBJECT-TYPE
SYNTAX RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION "The row status..."
DEFVAL { active }
::= { flightEntry 40 }
|
Tools discussed in MIB-to-Java generation
convert the MIB file
DEMO-TABLE-FLIGHT-MIB
into Java class DemoTableFlightMibFriend .
This class has the following structure:
public class DemoTableFlightMibFriend extends BaseMib {
private FTable flightEntry;
// Columns for table flightEntry
public final static FColumn COLUMN_FlightCarrier =
new FColumn("FlightCarrier",
DemoTableFlightMib.idxFlightCarrier,
DemoTableFlightMib.colFlightCarrier);
. . .
public final static FColumn COLUMN_FlightRowStatus =
new FColumn("FlightRowStatus",
DemoTableFlightMib.idxFlightRowStatus,
DemoTableFlightMib.colFlightRowStatus);
. . .
public FTable getFlightEntry() {
return flightEntry;
}
}
|
The table flightEntry is initialized when object of the class
DemoTableFlightMibFriend added to the SNMP agent.
A set of final static FColumn objects are generated as well.
The
org.friendlysnmp.FColumn
objects are used to access column data.
The class FColumn is immutable class.
It contains a column name which could be used for logging, messages and so on.
It also contains column OID index and column sequential index.
All these values cannot be altered thus making this class safe to use.
How to access table object
There are two techniques to get access to FTable objects.
Technique 1. Direct access from the MIB object using getters
generated for each table. This technique is used most of the time:
DemoTableFlightMibFriend mib = new DemoTableFlightMibFriend();
. . .
FTable table = mib.getFlightEntry();
|
Technique 2. Indirect access from the agent object using table OID.
This technique is used very rear, usually when a MIB object is hidden,
for example when MIB is internal to the agent and is not visible from the outside:
import org.snmp4j.mp.SnmpConstants;
. . .
FriendlyAgent agent = new FriendlyAgent();
. . .
FTable table = agent.getTable(DemoTableFlightMib.oidFlightEntry);
|
Table internals
The FTable class is a wrapper which hides SNMP4J
org.snmp4j.agent.mo.MOTable managed object and
org.snmp4j.agent.mo.MOTableModel table model.
The class provides
persistency layer and mechanism to add / remove
listeners.
Each table object is associated with immutable identifier
org.friendlysnmp.FID .
See also FID.
The table FID could be accessed but cannot be modified.
Table rows
There is no special class to present a table row object.
Instead there is a set of methods in the FTable class
to access table cell values.
Rows could be deleted one by one using row FID or all at once.
Rows could be added to the table with specified row FID or with
generated next available row FID.
Table cell syntax and value
The FTable class provides transparent cell values
access with conversion basic Java objects and primitives to / from
SNMP4J specific org.snmp4j.smi.Variable .
The conversion is driven by column syntax declared in the MIB and may throw
an exception.
Table cell values are accessed with methods which are very similar to
JTable .
try {
table.setValueAt(..);
. . .
Object obj = table.getValueAt(..);
. . .
} catch (FException e) {
// handle the problem
}
|
Exception is thrown when the new value cannot be properly converted
into / from internal presentation or for invalid row / column identifiers.
Table persistency
Table persistency makes sense only for tables declared with read-write
access in a MIB.
The table persistent content is saved into an external to the application
persistent storage and the table content is restored from it after the
application startup.
The table content becomes persistent only after successful explicit SNMP SET
request from a MIB browser for non-volatile scalars.
See also Persistency.
The full table content is stored in the persistent storage after any
table modification requested from a MIB browser. The MIB browser may modify
a single cell value, or add / remove a row. Any of these actions marks
the table content as modified and the new modified table content
becomes persistent.
The table is volatile by default
and its content is not stored in the persistent storage.
Explicit call table.setVolatile(false)
is required to enable table persistency.
This call also loads table persistent content from external storage
if table persistent content exists.
This call does nothing for read-only table.
private DemoTableFlightMibFriend mib = new DemoTableFlightMibFriend();
. . .
FTable table = mib.getFlightEntry();
table.setVolatile(false); // loads persistent value (if exist)
if (table.isPersistLoaded()) {
... use persistent table content ...
} else {
... use default table content ...
}
|
Table GET event and listener
The FTable class supports listening GET events which are triggered
by MIB browser GET requests.
The following methods in the class allow adding and removing GET listeners:
public void addGetListener(FTableGetListener l)
public void removeGetListener(FTableGetListener l)
|
GET listener is called when a MIB browser requests a table value.
The GET request from the MIB browser is received
by the SNMP agent in the application.
The SNMP agent keeps collection of all tables as managed objects.
The application is responsible to update the table content in the listener's code
thus making the table content correctly reflect the application's current
internal content associated with the table. This update is required for
tables which represent dynamic application values. Example of the code from
demo application to update the table:
private DemoTableFlightMibFriend mib = new DemoTableFlightMibFriend();
private List<FlightRow> lstRows = content of the table
. . .
FTable table = mib.getFlightEntry();
. . .
table.deleteAll(); // remove all content and load new one
for (FlightRow row : lstRows) {
FID idRow = table.addRow(row.id);
table.setValueAt(row.sCarrier,
idRow, DemoTableFlightMibFriend.COLUMN_FlightCarrier);
table.setValueAt(row.nFlightNo,
idRow, DemoTableFlightMibFriend.COLUMN_FlightNumber);
table.setValueAt(row.sDestination,
idRow, DemoTableFlightMibFriend.COLUMN_FlightDestination);
table.setValueAt(row.sDepartTime,
idRow, DemoTableFlightMibFriend.COLUMN_FlightDepartTime);
table.setValueAt(row.statusFlight.nStatus,
idRow, DemoTableFlightMibFriend.COLUMN_FlightStatus);
table.setValueAt(RowStatusTC.active,
idRow, DemoTableFlightMibFriend.COLUMN_FlightRowStatus);
}
|
See also Events and Listeners.
Table VALIDATE + SET event and listener
The FTable class supports listening SET events which are triggered
by MIB browser SET requests. Each SET event is prepended with VALIDATION event.
Handling VALIDATION event is optional. It allows rejecting invalid SET request.
The following methods in the class allow adding and removing SET
and optional VALIDATE listeners:
public void addValidationListener(FTableValidationListener l)
public void removeValidationListener(FTableValidationListener l)
public void addSetListener(FTableSetListener l)
public void removeSetListener(FTableSetListener l)
|
VALIDATE listener is called when a MIB browser attempts to SET a new value
to the table cell.
This listener makes no sense for read-only table and it is not called
at all for it.
Missing VALIDATE listener for read-write table allows MIB browser
to set any new value.
SET listener is called when a MIB browser attempts to SET a new value
and VALIDATION listener is missing or it allows the new value.
The application is responsible for updating its internal copy of the
value associated with the updated table cell and starting to use it.
Example of the listeners code to VALIDATE and SET table cell value:
private DemoTableFlightMibFriend mib = new DemoTableFlightMibFriend();
. . .
FTable table = mib.getFlightEntry();
. . .
// Validate table cell new value
table.addValidationListener(new FTableValidationListener() {
public ValueValidation validate(FTable table, Object objNewValue,
FID idRow, FColumn col, RowAction action)
{
if (new cell value is not good) {
return ValueValidation.WRONG_VALUE;
}
return ValueValidation.SUCCESS;
}
});
// Set table cell new value
table.addSetListener(new FTableSetListener() {
public void set(FTable table, FID idRow, FColumn col, RowAction action) {
// The table object already has all new values set.
// The application is responsible to start use them.
. . .
}
});
|
Restore default value
Each read-write table over the lifetime has two sources of content:
default content which is initially set in the agent and a content which is set from
a MIB browser and preserved in a persistency storage.
It is very difficult to rollback table content
to a default after a new content is set from a MIB browser.
The FriendlySNMP API provides an option to remove table content from persistency
storage. The access to the tables persistency storage is provided in
FRIENDLY-SNMP-MIB .
The agent is notified about this action via SET operation. It is agent's
responsibility to handle this type of events with the following
RESTORE DEFAULTS listeners:
public void addRestoreDefaultListener(FRestoreDefaultListener l)
public void removeRestoreDefaultListener(FRestoreDefaultListener l)
|
Missing RESTORE DEFAULT listeners is not a disaster for the application if
the application is restarted to pick up the new persistency storage state.
Example of the listener code to RESTORE DEFAULT table content:
private DemoTableFlightMibFriend mib = new DemoTableFlightMibFriend();
. . .
mib.getFlightEntry().addRestoreDefaultListener(new FRestoreDefaultListener() {
public void restoreDefault(FRestoreDefaultEvent ev) {
... load default content ...
}
});
|
Static and dynamic table
Static table has a content which never (or very rare) changes during a lifetime
of the application.
Examples of such tables are application configuration properties,
list of classpath entries, list of used libraries, and so on.
The content of a static table should be set explicitly
without using GET listeners overhead.
Application may set value of
a static table at startup and do not keep a working copy of this table content.
MIB browser GET request is satisfied with a table content which is already set
in the table object.
Dynamic table has a content which is changing frequently in the code.
Application with read-only table should provide
GET listener to handle MIB browser request to access this table.
Application with read-write table should provide
at minimum GET and SET listeners to handle MIB browser request to access this table.
|