在线文档教程
Erlang 20

10.检测函数 | 10. Instrumentation Functions

10 检测函数

用户定义的每个对象的检测函数都会将管理对象附加到实际资源中。 该功能由代理在get或set操作中调用。 该函数可以读取一些硬件寄存器,执行计算或执行与概念变量关联的语义所需的任何内容。 必须为标量变量和表格写入这些函数。 它们在关联文件中指定,这是一个文本文件。 在这个文件中,OBJECT IDENTIFIER或每个被管理对象的符号名都与一个Erlang元组{Module,Function,ListOfExtraArguments}相关联。

在SNMP操作中引用托管对象时,将{Module, Function, ListOfExtraArguments}调用关联的对象。该函数应用于一些标准参数(例如操作类型)和用户提供的额外参数。

对于标量变量和表格,必须编写测试函数,对于表格只能使用get-next。 get-bulk操作被翻译为一系列调用get-next。

10.1仪表功能

以下部分描述了如何在Erlang中为不同的操作定义检测函数。以下RowIndex是该表的关键值列表,并且Column是列号。

这些功能在详细描述Definition of Instrumentation Functions详细描述。

新的/删除的业务

对于标量变量:

variable_access(new [, ExtraArg1, ...]) variable_access(delete [, ExtraArg1, ...])

表:

table_access(new [, ExtraArg1, ...]) table_access(delete [, ExtraArg1, ...])

当MIB被卸载或加载时,对MIB中的每个对象分别调用这些函数。

获取操作

对于标量变量:

variable_access(get [, ExtraArg1, ...])

表:

table_access(get,RowIndex,Cols [,ExtraArg1, ...])

Cols是一个列表Column。代理将对传入变量进行排序,以便同时提供一行(同一索引)上的所有操作。这是因为数据库通常会逐行检索信息。

这些函数必须返回关联变量的当前值。

集合操作

对于标量变量:

variable_access(set, NewValue [, ExtraArg1, ...])

表:

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols是元组列表{Column, NewValue}

这些函数返回noError如果分配成功,则为错误代码。

Is-set-ok操作

作为set操作的补充,可以指定测试功能。这个函数的语法与上面的set操作相同,只是第一个参数is_set_ok不是set。这个函数在变量被设置之前被调用。其目的是确保可以将变量设置为新值。

variable_access(is_set_ok, NewValue [, ExtraArg1, ...])

表:

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols是元组列表{Column, NewValue}

撤消操作

使用is_set_ok调用的函数将再次调用,如果没有错误,则使用set,如果发生错误,则使用撤销。 通过这种方式,可以在is_set_ok操作中保留资源,在撤消操作中释放资源,或在set操作中永久使用资源。

variable_access(undo, NewValue [, ExtraArg1, ...])

表:

table_access(set, RowIndex, Cols [, ExtraArg1,..])

Cols是元组列表{Column, NewValue}

GetNext操作

由于代理可以在MIB中找到下一个简单变量实例并使用get操作调用检测,因此应仅为表定义GetNext操作操作。

table_access(get_next, RowIndex, Cols [, ExtraArg1, ...])

Cols是一个整数列表,全部大于或等于零。 这表明仪器应该找到下一个可访问的实例。 该函数返回元组{NextOid,NextValue}或endOfTable。 NextOid应该是表中管理对象的字典顺序下一个可访问的实例。 它应该是一个整数列表,其中第一个整数是列,其余列表是下一行的索引。 如果返回endOfTable,代理将继续在其他变量和表中搜索下一个实例。

RowIndex 可能是空列表,未完整指定的行索引或未指定行的索引。

这个操作最好用一个例子来描述。

GetNext示例

名为myTable的表格有五列。 前两个是键(不可访问),并且该表有三行。 该表的检测功能称为my_table。

Figure 10.1: Contents of my_table

N / A表示无法访问。

管理者发出以下getNext请求:

getNext{ myTable.myTableEntry.3.1.1, myTable.myTableEntry.5.1.1 }

由于这两个操作都涉及1.1索引,因此这个操作转换为对my_table的一个调用:

my_table(get_next, [1, 1], [3, 5])

在这个调用中,[1,1]是RowIndex,其中键1的值为1,键2的值为1,[3,5]是请求列的列表。 该函数现在应该返回按字典顺序排列的下一个元素:

[{[3, 1, 2], d}, {[5, 1, 2], f}]

下表说明了这一点:

图10.2:GetNext来自3,1,1和5,1,1...

经理现在发出以下getNext请求:

getNext{ myTable.myTableEntry.3.2.1, myTable.myTableEntry.5.2.1 }

这转变成一个调用my_table

my_table(get_next, [2, 1], [3, 5])

该函数现在应该返回:

[{[4, 1, 1], b}, endOfTable]

下表说明了这一点:

图10.3:GetNext来自3,2,1和5,2,1...

经理现在发出以下getNext请求:

getNext{ myTable.myTableEntry.3.1.2, myTable.myTableEntry.4.1.2 }

这将转变为一个调用my_table

my_table(get_next, [1, 2], [3, 4])

该函数现在应该返回:

[{[3, 2, 1], g}, {[5, 1, 1], c}]

下表说明了这一点:

图10.4:GetNext来自3,1,2和4,1,2...

管理者现在发出以下getNext请求:

getNext{ myTable.myTableEntry, myTable.myTableEntry.1.3.2 }

这将转换为两个调用my_table*

my_table(get_next, [], [0]) and my_table(get_next, [3, 2], [1])

该函数现在应该返回:

[{[3, 1, 1], a}] and [{[3, 1, 1], a}]

在这两种情况下,都应该返回表中的第一个可访问元素。由于键列不可访问,这意味着第三列是第一行。

通常,上面描述的函数的行为与所示完全相同,但它们可以自由地执行其他操作。例如,get请求可能会产生副作用,例如设置其他变量,可能是全局变量。lastAccessed变量。

10.2使用Extraargument

ListOfExtraArguments可用于编写通用的功能。该列表被附加到每个函数的标准参数。考虑两个只读用于设备的变量,ipAdrname分别与对象标识符和1.1.23.4 1.1.7。要访问这些变量,一个可以实现两个二郎功能ip_accessname_access,这将是在MIB。这些函数可以在文本文件中指定如下:

{ipAdr, {my_module, ip_access, []}}. % Or using the oid syntax for 'name' {[1,1,7], {my_module, name_access, []}}.

ExtraArgument参数是空列表。例如,当代理收到该ipAdr变量的获取请求时,将进行调用ip_access(get)。该函数返回的值是获取请求的答案。

如果ip_accessname_access实现类似,我们可以编写一个generic_access函数使用ListOfExtraArguments*

{ipAdr, {my_module, generic_access, ['IPADR']}}. % The mnemonic 'name' is more convenient than 1.1.7 {name, {my_module, generic_access, ['NAME']}}.

当代理人收到与上述相同的获取请求时,将会拨打generic_access(get,'' IPADR')

另一种更接近硬件的可能性是:

{ipAdr, {my_module, generic_access, [16#2543]}}. {name, {my_module, generic_access, [16#A2B3]}}.

10.3默认仪表

当MIB定义工作完成后,还有两个主要问题。

  • 实施MIB

  • 实现Manager应用程序。

实现MIB可能是一项乏味的任务。 最有可能的是,在实施所有表和变量之前,需要测试代理。 在这种情况下,默认的仪器功能很有用。 该工具包可以为变量以及表格生成默认的检测功能。 因此,一个正在运行的原型代理可以处理set,get,get-next和table操作,而不需要任何编程。

代理将值存储在基于标准模块的内部易失性数据库中ets。但是,可以让MIB编译器生成使用内部持久性数据库或Mnesia DBMS的函数。snmp_generic有关更多信息,请参阅Mnesia用户指南和参考手册的SNMP部分。

当MIB的部分实现时,您将重新编译它,并使用默认函数继续运行。通过这种方法,可以逐步开发SNMP代理。

默认的工具允许管理端的应用程序与代理同时开发和测试。一旦ASN.1文件完成,就让MIB编译器生成一个默认实现,并由此开发管理应用程序。

表操作

表格的默认功能的生成适用于使用RowStatusSTANDARD-MIB和SNMPv2-TC中定义的SNMPv2文本约定的表格。

对于可以从管理器修改的每个表,我们强烈建议使用RowStatus约定,即使是新设计的SNMPv1 MIB也是如此。 在SNMPv1中,每个人都发明了自己的模拟表操作方案,这导致了许多不一致。 SNMPv2中的约定是灵活而强大的,并且已经测试成功。 如果该表是只读的,则不应使用RowStatus列。

10.4 原子集

在SNMP中,set操作是原子的。中指定的所有变量。set操作被更改,或者没有被更改。因此,set操作分为两个阶段。在第一阶段,每个变量的新值将根据MIB中变量的定义进行检查。检查下列定义:

  • 类型

  • 长度

  • 范围

  • 变量是可写的,并且在MIB视图中。

在第一阶段结束时,用户定义is_set_ok为每个标量变量和每组表操作调用函数。

如果没有发生错误,则执行第二阶段。此阶段调用定义的用户。set所有变量的函数。

如果发生错误,则在is_set_ok阶段,或处于set阶段,所有被调用的函数is_set_ok但不是set,被调用为undo...

这种交易机制有局限性。如果变量之间存在复杂的依赖关系,例如month和之间day,则需要另一种机制。将日期设置为'Feb 31'可以通过更通用的事务机制来避免。您可以继续并找到越来越复杂的情况,并构建N阶段集机制。该工具包只包含一个微不足道的机制。

事务机制最常见的应用是将行操作保持在一起。由于我们的代理对行操作进行排序,结合RowStatus(特别是'createAndWait'值)实现的机制可以优雅地解决大多数问题。