diff options
Diffstat (limited to 'lib/snmp/examples/ex1/ex1.erl')
-rw-r--r-- | lib/snmp/examples/ex1/ex1.erl | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/lib/snmp/examples/ex1/ex1.erl b/lib/snmp/examples/ex1/ex1.erl new file mode 100644 index 0000000000..3618cd3b8c --- /dev/null +++ b/lib/snmp/examples/ex1/ex1.erl @@ -0,0 +1,256 @@ +%%<copyright> +%% <year>1996-2007</year> +%% <holder>Ericsson AB, All Rights Reserved</holder> +%%</copyright> +%%<legalnotice> +%% 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. +%% +%% The Initial Developer of the Original Code is Ericsson AB. +%%</legalnotice> +%% +-module(ex1). + +%% External exports +-export([start/0, my_name/1, my_name/2, friends_table/3]). + +%% Internal exports +-export([init/0]). + +-define(status_col, 4). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). % Action; written, not read +-define(createAndWait, 5). % Action; written, not read +-define(destroy, 6). % Action; written, not read + +start() -> + spawn(ex1, init, []). + + +%%---------------------------------------------------------------- +%% Instrumentation function for variable myName. +%% Returns: (get) {value, Name} +%% (set) noError +%%---------------------------------------------------------------- +my_name(get) -> + ex1_server ! {self(), get_my_name}, + Name = wait_answer(), + {value, Name}. + +my_name(set, NewName) -> + ex1_server ! {self(), {set_my_name, NewName}}, + noError. + +%%---------------------------------------------------------------- +%% Instrumentation function for table friendsTable. +%%---------------------------------------------------------------- +friends_table(get, RowIndex, Cols) -> + case get_row(RowIndex) of + {ok, Row} -> + get_cols(Cols, Row); + _ -> + {noValue, noSuchInstance} + end; + +friends_table(get_next, RowIndex, Cols) -> + case get_next_row(RowIndex) of + {ok, Row} -> + get_next_cols(Cols, Row); + _ -> + case get_next_row([]) of + {ok, Row} -> + % Get next cols from first row. + NewCols = add_one_to_cols(Cols), + get_next_cols(NewCols, Row); + _ -> + end_of_table(Cols) + end + end; + +%%---------------------------------------------------------------- +%% If RowStatus is set, then: +%% *) If set to destroy, check that row does exist +%% *) If set to createAndGo, check that row doesn't exist AND +%% that all columns are given values. +%% *) Otherwise, error (for simplicity). +%% Otherwise, row is modified; check that row exists. +%%---------------------------------------------------------------- +friends_table(is_set_ok, RowIndex, Cols) -> + RowExists = + case get_row(RowIndex) of + {ok, _Row} -> true; + _ -> false + end, + case is_row_status_col_changed(Cols) of + {true, ?destroy} when RowExists == true -> + {noError, 0}; + {true, ?createAndGo} when RowExists == false, + length(Cols) == 3 -> + {noError, 0}; + {true, _} -> + {inconsistentValue, ?status_col}; + false when RowExists == true -> + {noError, 0}; + _ -> + [{Col, _NewVal} | _Cols] = Cols, + {inconsistentName, Col} + end; + +friends_table(set, RowIndex, Cols) -> + case is_row_status_col_changed(Cols) of + {true, ?destroy} -> + ex1_server ! {self(), {delete_row, RowIndex}}; + {true, ?createAndGo} -> + NewRow = make_row(RowIndex, Cols), + ex1_server ! {self(), {add_row, NewRow}}; + false -> + {ok, Row} = get_row(RowIndex), + NewRow = merge_rows(Row, Cols), + ex1_server ! {self(), {delete_row, RowIndex}}, + ex1_server ! {self(), {add_row, NewRow}} + end, + {noError, 0}. + +%%---------------------------------------------------------------- +%% Make a list of {value, Val} of the Row and Cols list. +%%---------------------------------------------------------------- +get_cols([Col | Cols], Row) -> + [{value, element(Col, Row)} | get_cols(Cols, Row)]; +get_cols([], _Row) -> + []. + +%%---------------------------------------------------------------- +%% As get_cols, but the Cols list may contain invalid column +%% numbers. If it does, we must find the next valid column, +%% or return endOfTable. +%%---------------------------------------------------------------- +get_next_cols([Col | Cols], Row) when Col < 2 -> + [{[2, element(1, Row)], element(2, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) when Col > 4 -> + [endOfTable | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) -> + [{[Col, element(1, Row)], element(Col, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([], _Row) -> + []. + +%%---------------------------------------------------------------- +%% Make a list of endOfTable with as many elems as Cols list. +%%---------------------------------------------------------------- +end_of_table([_Col | Cols]) -> + [endOfTable | end_of_table(Cols)]; +end_of_table([]) -> + []. + +add_one_to_cols([Col | Cols]) -> + [Col + 1 | add_one_to_cols(Cols)]; +add_one_to_cols([]) -> + []. + +is_row_status_col_changed(Cols) -> + case lists:keysearch(?status_col, 1, Cols) of + {value, {?status_col, StatusVal}} -> + {true, StatusVal}; + _ -> false + end. + +get_row(RowIndex) -> + ex1_server ! {self(), {get_row, RowIndex}}, + wait_answer(). + +get_next_row(RowIndex) -> + ex1_server ! {self(), {get_next_row, RowIndex}}, + wait_answer(). + +wait_answer() -> + receive + {ex1_server, Answer} -> + Answer + end. + +%%%---------------------------------------------------------------- +%%% Server code follows +%%%---------------------------------------------------------------- +init() -> + register(ex1_server, self()), + loop("", []). + +loop(MyName, Table) -> + receive + {From, get_my_name} -> + From ! {ex1_server, MyName}, + loop(MyName, Table); + {_From, {set_my_name, NewName}} -> + loop(NewName, Table); + {From, {get_row, RowIndex}} -> + Res = table_get_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {From, {get_next_row, RowIndex}} -> + Res = table_get_next_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {_From, {delete_row, RowIndex}} -> + NewTable = table_delete_row(Table, RowIndex), + loop(MyName, NewTable); + {_From, {add_row, NewRow}} -> + NewTable = table_add_row(Table, NewRow), + loop(MyName, NewTable) + end. + + +%%----------------------------------------------------------------- +%% Implementation of the table. +%%----------------------------------------------------------------- +table_get_row([{Index, Name, Address, Status} | _], [Index]) -> + {ok, {Index, Name, Address, Status}}; +table_get_row([_H | T], RowIndex) -> + table_get_row(T, RowIndex); +table_get_row([], _RowIndex) -> + no_such_row. + +table_get_next_row([Row | _T], []) -> + {ok, Row}; +table_get_next_row([Row | _T], [Index | _]) when element(1, Row) > Index -> + {ok, Row}; +table_get_next_row([_Row | T], RowIndex) -> + table_get_next_row(T, RowIndex); +table_get_next_row([], _RowIndex) -> + endOfTable. + +table_delete_row([{Index, _, _, _} | T], [Index]) -> + T; +table_delete_row([H | T], RowIndex) -> + [H | table_delete_row(T, RowIndex)]; +table_delete_row([], _RowIndex) -> + []. + +table_add_row([Row | T], NewRow) when element(1, Row) > element(1, NewRow) -> + [NewRow, Row | T]; +table_add_row([H | T], NewRow) -> + [H | table_add_row(T, NewRow)]; +table_add_row([], NewRow) -> + [NewRow]. + +make_row([Index], [{2, Name}, {3, Address} | _]) -> + {Index, Name, Address, ?active}. + +merge_rows(Row, [{Col, NewVal} | T]) -> + merge_rows(setelement(Col, Row, NewVal), T); +merge_rows(Row, []) -> + Row. + + |