查看源码 snmp_index (snmp v5.18)
SNMP 索引的抽象数据类型
模块 snmp_index
为 SNMP 表实现了一种 SNMP 索引结构的抽象数据类型(ADT)。它被实现为 ordered_set 数据类型的 ets 表,这意味着所有操作的时间复杂度都是 O(log n)。在表中,键是 ASN.1 OBJECT IDENTIFIER。
此索引用于将 SNMP 排序的实现与表的实际实现分离。SNMP 排序,即 GET NEXT 的实现,在此模块中实现。
例如,假设有一个 SNMP 表,在 Erlang 中最佳的实现方式是每个 SNMP 表行一个进程。进一步假设 SNMP 表中的 INDEX 是一个 OCTET STRING。索引结构将如下创建
snmp_index:new(string)
对于我们创建的每个新进程,我们在 snmp_index
结构中插入一个项
new_process(Name, SnmpIndex) ->
Pid = start_process(),
NewSnmpIndex =
snmp_index:insert(SnmpIndex, Name, Pid),
<...>
有了这个结构,我们现在可以将例如 GET NEXT 请求中的 OBJECT IDENTIFIER 映射到正确的进程
get_next_pid(Oid, SnmpIndex) ->
{ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
Pid.
警告
警告
所有更新索引的 API 函数都返回一个
NewIndex
项。这是为了向后兼容之前使用纯 Erlang 编写的 B+ 树作为索引的实现。NewIndex
返回值现在可以忽略。返回值现在是 ets 表的未更改的表标识符。使用 ets 表的实现引入了与旧实现的语义不兼容。在那些使用纯 Erlang 项的旧实现中,索引像任何其他 Erlang 项一样被垃圾回收,并且在丢弃时不必删除。只有当创建它的进程显式删除它或创建进程终止时,ets 表才会被删除。
现在添加了一个新的接口
delete/1
来处理进程想要丢弃索引表(即构建一个全新的索引表)的情况。任何使用瞬态 snmp 索引的应用程序都必须进行修改以处理这种情况。由于 snmp 适配通常在整个系统的生命周期中保留索引,因此这很少成为问题。
概要
类型
此类型表示 snmp 索引结构。
此类型与 key_types/0
类型相关。如果 key_types/0
是单个原子,则相应的 key/0
也是单个类型,但是如果 key_types/0
是一个元组,则 key/0
必须是相同大小的元组。
此类型在创建索引结构时使用,而 key/0
类型在从结构中插入和删除项时使用。
类型
-opaque index()
此类型表示 snmp 索引结构。
此类型与 key_types/0
类型相关。如果 key_types/0
是单个原子,则相应的 key/0
也是单个类型,但是如果 key_types/0
是一个元组,则 key/0
必须是相同大小的元组。
在上面的示例中,有效的 keys
可以是 {"hi", "mom"}
和 {"no", "thanks"}
,而 "hi"
、{"hi", 42}
和 {"hello", "there"}
将是无效的。
在 erlang 类型语言中无法正确描述此类型,这就是为什么上面使用了 tuple/0
。正确的定义如下所示
key() = key_spec() | {key_spec(), key_spec(), ...}
此类型在创建索引结构时使用,而 key/0
类型在从结构中插入和删除项时使用。
如果 INDEX 列的类型为 INTEGER 或从 INTEGER 派生,则相应的类型应为 integer
。 如果它是可变长度类型(例如,OBJECT IDENTIFIER、OCTET STRING),则相应的类型应为 string
。最后,如果类型是可变长度的,但具有固定大小限制(例如,IpAddress),则相应的类型应为 fix_string
。
在 erlang 类型语言中无法正确描述此类型,这就是为什么上面使用了 tuple/0
。正确的定义如下所示
key_types = type_spec() | {type_spec(), type_spec(), ...}
-type type_spec() :: fix_string | string | integer.
函数
-spec delete(Index) -> true when Index :: index().
删除完整的索引结构(即保存索引的 ets 表)。在此调用之后,该索引将不再被引用。请参阅上面的 警告说明。
从索引结构中删除键及其值。返回一个新的结构。
-spec get(Index, KeyOid) -> {ok, {KeyOid, Value}} | undefined when Index :: index(), KeyOid :: snmp:oid(), Value :: term().
获取键为 KeyOid
的项。可以从 SNMP 检测函数内部使用。
-spec get_last(Index) -> {ok, {KeyOid, Value}} | undefined when Index :: index(), KeyOid :: snmp:oid(), Value :: term().
获取索引结构中的最后一项。
-spec get_next(Index, KeyOid) -> {ok, {NextKeyOid, Value}} | undefined when Index :: index(), KeyOid :: snmp:oid(), NextKeyOid :: snmp:oid(), Value :: term().
获取索引结构中 KeyOid
之后的 SNMP 词典排序中的下一项。KeyOid
不必引用索引中现有的项。
-spec insert(Index, Key, Value) -> NewIndex when Index :: index(), Key :: key(), Value :: term(), NewIndex :: index().
将新的键值元组插入索引结构。如果已存在具有相同键的项,则新的 Value
会覆盖旧值。
将 Key
转换为 OBJECT IDENTIFIER。
创建一个新的匿名 snmp 索引结构。
创建一个新的命名 snmp 索引结构。