aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp/src/agent/snmpa_svbl.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/snmp/src/agent/snmpa_svbl.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/snmp/src/agent/snmpa_svbl.erl')
-rw-r--r--lib/snmp/src/agent/snmpa_svbl.erl159
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/snmp/src/agent/snmpa_svbl.erl b/lib/snmp/src/agent/snmpa_svbl.erl
new file mode 100644
index 0000000000..9c2910580e
--- /dev/null
+++ b/lib/snmp/src/agent/snmpa_svbl.erl
@@ -0,0 +1,159 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-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(snmpa_svbl).
+
+-include("snmp_types.hrl").
+
+-define(VMODULE,"SVBL").
+-include("snmp_verbosity.hrl").
+
+-export([sort_varbindlist/2, sort_varbinds_rows/1, sa_split/1,
+ delete_org_index/1, col_to_orgindex/2]).
+
+%%-----------------------------------------------------------------
+%% Func: sort_varbindlist/2
+%% Args: Varbinds is a list of #varbind
+%% Purpose: Group all variablebindings that corresponds to logically
+%% the same entity, i.e. group all plain variables, all
+%% table operations for each table, all varbinds to each
+%% subagent.
+%% Returns: {VarbindsForThisAgent
+%% VarbindsForSubAgents} where
+%% VarbindsForThisAgent = List of {TableOid, List of #ivarbinds} |
+%% #ivarbinds
+%% VarbindsForSubAgents = List of {SubAgentPid,
+%% List of {SAOid, #varbinds}}
+%%-----------------------------------------------------------------
+sort_varbindlist(Mib, Varbinds) ->
+ {Vars, Tabs, Subagents} = partition(Mib, Varbinds),
+ {lists:append(Tabs, Vars), Subagents}.
+
+partition(Mib, Vbs) ->
+ partition(Mib, Vbs, [], [], []).
+partition(Mib, [Varbind | Vbs], Vars, Tabs, Subs) ->
+ #varbind{oid = Oid} = Varbind,
+ ?vtrace("partition -> Oid: ~p", [Oid]),
+ case snmpa_mib:lookup(Mib, Oid) of
+ {table_column, MibEntry, TableOid} ->
+ IVarbind = #ivarbind{varbind = fix_bits(Varbind, MibEntry),
+ mibentry = MibEntry},
+ NewTabs = insert_key(TableOid, IVarbind, Tabs),
+ partition(Mib, Vbs, Vars, NewTabs, Subs);
+ {subagent, SubagentPid, SAOid} ->
+ NewSubs = insert_key(SubagentPid, {SAOid, Varbind}, Subs),
+ partition(Mib, Vbs, Vars, Tabs, NewSubs);
+ {variable, MibEntry} ->
+ IVarbind = #ivarbind{varbind = fix_bits(Varbind, MibEntry),
+ mibentry = MibEntry},
+ partition(Mib, Vbs, [IVarbind | Vars], Tabs, Subs);
+ {false, ErrorCode} -> % ErrorCode = noSuchObject | noSuchInstance
+ IVarbind = #ivarbind{status = ErrorCode, varbind = Varbind},
+ partition(Mib, Vbs, [IVarbind | Vars], Tabs, Subs)
+ end;
+partition(_Mib, [], Vars, Subs, Tabs) ->
+ {Vars, Subs, Tabs}.
+
+% fix_bits(#varbind{bertype = 'BITS',
+% variabletype = 'OCTET STRING',
+% value = V} = VarBind, #me{asn1_type = A}) ->
+% VarBind#varbind{variabletype = 'BITS',
+% value = snmp_pdus:octet_str_to_bits(V)};
+fix_bits(VarBind, #me{asn1_type=A})
+ when ((A#asn1_type.bertype =:= 'BITS') andalso
+ (VarBind#varbind.variabletype =:= 'OCTET STRING') andalso
+ is_list(VarBind#varbind.value)) ->
+ VarBind#varbind{variabletype = 'BITS',
+ value = snmp_pdus:octet_str_to_bits(VarBind#varbind.value)};
+fix_bits(Vb,_me) -> Vb.
+
+insert_key(Key, Value, [{Key, Values} | Rest]) ->
+ [{Key, [Value | Values]} | Rest];
+insert_key(Key, Value, [{KeyX, Values} | Rest]) ->
+ [{KeyX, Values} | insert_key(Key, Value, Rest)];
+insert_key(Key, Value, []) ->
+ [{Key, [Value]}].
+
+%%-----------------------------------------------------------------
+%% Tranforms a list of {Oid, Vb} to a 2-tuple with all
+%% Oids and all Vbs. These lists will be reversed.
+%%-----------------------------------------------------------------
+sa_split(Vbs) -> sa_split(Vbs, [], []).
+sa_split([{SAOid, Vb} | T], Oids, Vbs) ->
+ sa_split(T, [SAOid | Oids], [Vb | Vbs]);
+sa_split([], Oids, Vbs) ->
+ {Oids, Vbs}.
+
+%%-----------------------------------------------------------------
+%% Func: sort_varbinds_rows/1
+%% Args: Varbinds is a list of {Oid, Value}.
+%% Pre: Varbinds is for one table.
+%% Purpose: Sorts all varbinds in Oid order, and in row order.
+%% Returns: list of Row where
+%% Row = {Indexes, List of Col} and
+%% Col = {ColNo, Value, OrgIndex} and
+%% OrgIndex is index in original varbind list.
+%%-----------------------------------------------------------------
+sort_varbinds_rows(Varbinds) ->
+ P = pack(Varbinds),
+ S = lists:keysort(1, P),
+ unpack(S).
+
+%% In: list of {Oid, Value}
+%% Out: list of {{Indexes_for_row, Col}, Val, Index}
+pack(V) -> pack(1, V).
+pack(Index, [{[Col | Rest], Val} | T]) ->
+ [{{Rest, Col}, Val, Index} | pack(Index+1, T)];
+pack(_, []) -> [].
+
+unpack([{{Rest, Col}, Val, Index} | T]) ->
+ unpack(Rest, [[{Col, Val, Index}]], T);
+unpack([]) -> [].
+
+unpack(Rest, [Row | Rows], [{{Rest, Col}, Val, Index} | T]) ->
+ unpack(Rest, [[{Col, Val, Index} | Row] | Rows], T);
+unpack(Rest, [Row | Rows], [{{Rest2, Col}, Val, Index} | T]) ->
+ unpack(Rest2, [[{Col, Val, Index}],
+ {Rest, lists:reverse(Row)} | Rows], T);
+unpack(Rest, [Row | Rows], []) ->
+ NewRow = {Rest, lists:reverse(Row)},
+ lists:reverse([NewRow | Rows]).
+
+%% OrgIndex should not be present when we call the is_set_ok/set/undo
+%% table functions. They just see the list of cols, and if an error
+%% occurs, they return the column nunber.
+%% Also, delete duplicate columns. If a SET is performed with duplicate
+%% columns, it is undefined which column to use. We just pick one.
+delete_org_index([{RowIndex, Cols} | Rows]) ->
+ [{RowIndex, doi(Cols)} | delete_org_index(Rows)];
+delete_org_index([]) -> [].
+
+doi([{Col, Val, OrgIndex}, {Col, _Val, _OrgIndex} | T]) ->
+ doi([{Col, Val, OrgIndex} | T]);
+doi([{Col, Val, _OrgIndex} | T]) ->
+ [{Col, Val} | doi(T)];
+doi([]) -> [].
+
+%% Maps the column number to OrgIndex.
+col_to_orgindex(0, _) -> 0;
+col_to_orgindex(Col, [{Col, _Val, OrgIndex}|_]) ->
+ OrgIndex;
+col_to_orgindex(Col, [_|Cols]) ->
+ col_to_orgindex(Col, Cols);
+col_to_orgindex(BadCol, _) ->
+ {false, BadCol}.