diff options
Diffstat (limited to 'lib/snmp/src/agent/snmp_index.erl')
-rw-r--r-- | lib/snmp/src/agent/snmp_index.erl | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/snmp/src/agent/snmp_index.erl b/lib/snmp/src/agent/snmp_index.erl new file mode 100644 index 0000000000..1902fe2613 --- /dev/null +++ b/lib/snmp/src/agent/snmp_index.erl @@ -0,0 +1,163 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(snmp_index). + +-export([new/1, new/2, + insert/3, + delete/1, delete/2, + get/2, get_next/2, + get_last/1, + key_to_oid/2]). + + +-define(VMODULE,"IDX"). +-include("snmp_verbosity.hrl"). + +-record(tab, {id, keys}). + +-define(badarg(F, A), exit({badarg, {?MODULE, F, A}})). +-define(bad_new(A), ?badarg(new, A)). +-define(bad_get(A), ?badarg(get, A)). + + +%%%----------------------------------------------------------------- +%%% This module implements an SNMP index structure as an ADT. +%%% It is supposed to be used as a separate structure which implements +%%% the SNMP ordering of the keys in the SNMP table. The advantage +%%% with this is that the get-next operation is automatically +%%% taken care of. +%%%----------------------------------------------------------------- + +%%----------------------------------------------------------------- +%% Args: KeyTypes = key() | {key(), ...} +%% key() = integer | string | fix_string +%% Returns: handle() +%%----------------------------------------------------------------- + +new(KeyTypes) -> + ?vlog("new -> entry with" + "~n KeyTypes: ~p", [KeyTypes]), + do_new(KeyTypes, ?MODULE, [public, ordered_set]). + +new(KeyTypes, Name) when is_atom(Name) -> + ?vlog("new -> entry with" + "~n KeyTypes: ~p" + "~n Name: ~p", [KeyTypes, Name]), + do_new(KeyTypes, Name, [public, ordered_set, named_table]); +new(KeyTypes, Name) -> + ?vinfo("new -> bad data" + "~n KeyTypes: ~p" + "~n Name: ~p", [KeyTypes, Name]), + ?bad_new([KeyTypes, Name]). + +do_new(KeyTypes, EtsName, EtsOpts) -> + ?vdebug("do_new -> entry with" + "~n KeyTypes: ~p" + "~n EtsName: ~p" + "~n EtsOpts: ~p", [KeyTypes, EtsName, EtsOpts]), + case is_snmp_type(to_list(KeyTypes)) of + true -> + Tab = #tab{id = ets:new(EtsName, EtsOpts), keys = KeyTypes}, + ?vtrace("do_new -> " + "~n Tab: ~p", [Tab]), + Tab; + false -> + ?bad_new([KeyTypes, EtsName]) + end. + + +get(#tab{id = OrdSet}, KeyOid) -> + ?vlog("get -> entry with" + "~n OrdSet: ~p" + "~n KeyOid: ~p", [OrdSet, KeyOid]), + case ets:lookup(OrdSet, KeyOid) of + [X] -> + {ok, X}; + _ -> + undefined + end. + + + +get_next(#tab{id = OrdSet} = Tab, KeyOid) -> + ?vlog("get_next -> entry with" + "~n Tab: ~p" + "~n KeyOid: ~p", [Tab, KeyOid]), + case ets:next(OrdSet, KeyOid) of + '$end_of_table' -> + undefined; + Key -> + get(Tab, Key) + end. + +get_last(#tab{id = OrdSet} = Tab) -> + ?vlog("get_last -> entry with" + "~n Tab: ~p", [Tab]), + case ets:last(OrdSet) of + '$end_of_table' -> + undefined; + Key -> + get(Tab, Key) + end. + +insert(#tab{id = OrdSet, keys = KeyTypes} = Tab, Key, Val) -> + ets:insert(OrdSet, {key_to_oid_i(Key, KeyTypes), Val}), + Tab. + +delete(#tab{id = OrdSet, keys = KeyTypes} = Tab, Key) -> + ets:delete(OrdSet, key_to_oid_i(Key, KeyTypes)), + Tab. + +delete(#tab{id = OrdSet}) -> + ets:delete(OrdSet). + +key_to_oid(#tab{keys = KeyTypes}, Key) -> + key_to_oid_i(Key, KeyTypes). + +to_list(Tuple) when is_tuple(Tuple) -> tuple_to_list(Tuple); +to_list(X) -> [X]. + +is_snmp_type([integer | T]) -> is_snmp_type(T); +is_snmp_type([string | T]) -> is_snmp_type(T); +is_snmp_type([fix_string | T]) -> is_snmp_type(T); +is_snmp_type([]) -> true; +is_snmp_type(_) -> false. + + +%%----------------------------------------------------------------- +%% Args: Key = key() +%% key() = int() | string() | {int() | string(), ...} +%% Type = {fix_string | term()} +%% Make an OBJECT IDENTIFIER out of it. +%% Variable length objects are prepended by their length. +%% Ex. Key = {"pelle", 42} AND Type = {string, integer} => +%% OID [5, $p, $e, $l, $l, $e, 42] +%% Key = {"pelle", 42} AND Type = {fix_string, integer} => +%% OID [$p, $e, $l, $l, $e, 42] +%%----------------------------------------------------------------- +key_to_oid_i(Key, _Type) when is_integer(Key) -> [Key]; +key_to_oid_i(Key, fix_string) -> Key; +key_to_oid_i(Key, _Type) when is_list(Key) -> [length(Key) | Key]; +key_to_oid_i(Key, Types) -> keys_to_oid(size(Key), Key, [], Types). + +keys_to_oid(0, _Key, Oid, _Types) -> Oid; +keys_to_oid(N, Key, Oid, Types) -> + Oid2 = lists:append(key_to_oid_i(element(N, Key), element(N, Types)), Oid), + keys_to_oid(N-1, Key, Oid2, Types). + |