%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2013-2013. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% -module(snmpa_mib_storage_mnesia). -behaviour(snmpa_mib_storage). %%%----------------------------------------------------------------- %%% This module implements the snmpa_mib_storage behaviour. %%% It uses mnesia for storage. %%%----------------------------------------------------------------- -export([ open/5, close/1, read/2, write/2, delete/1, delete/2, match_object/2, match_delete/2, tab2list/1, info/1, info/2, sync/1, backup/2 ]). -define(VMODULE,"MS-MNESIA"). -include("snmp_verbosity.hrl"). -record(tab, {id}). %% --------------------------------------------------------------- %% open %% %% Open or create a mnesia table. %% %% Opts - A list of implementation dependent options %% mnesia_open_options() = [mnesia_open_option()] %% mnesia_open_option() = {action, keep | clear} | %% {nodes, [node()]} %% %% --------------------------------------------------------------- open(Name, RecName, Fields, Type, Opts) -> ?vtrace("open ~p table ~p for record ~p", [Type, Name, RecName]), Action = get_action(Opts), Nodes = get_nodes(Opts), case table_exists(Name) of true when (Action =:= keep) -> ?vtrace("open table ~p - exist (keep)", [Name]), {ok, #tab{id = Name}}; true when (Action =:= clear) -> ?vtrace("open table ~p - exist (clear)", [Name]), F = fun() -> mnesia:clear_table(Name) end, case mnesia:transaction(F) of {aborted, Reason} -> {error, {clear, Reason}}; {atomic, _} -> {ok, #tab{id = Name}} end; false -> ?vtrace("open table ~p - does not exist", [Name]), Args = [{record_name, RecName}, {attributes, Fields}, {type, Type}, {disc_copies, Nodes}], case mnesia:create_table(Name, Args) of {atomic, ok} -> ?vtrace("open table ~p - ok", [Name]), {ok, #tab{id = Name}}; {aborted, Reason} -> ?vinfo("open table ~p - aborted" "~n Reason: ~p", [Name, Reason]), {error, {create, Reason}} end end. table_exists(Name) -> case (catch mnesia:table_info(Name, type)) of {'EXIT', _Reason} -> false; _ -> true end. %% --------------------------------------------------------------- %% close %% %% Close the mib-storage table. %% This does nothing in the mnesia case. %% --------------------------------------------------------------- close(_) -> ?vtrace("close mib-storage - ignore",[]), ok. %% --------------------------------------------------------------- %% read %% %% Retrieve a record from the mib-storage table. %% --------------------------------------------------------------- read(#tab{id = ID}, Key) -> ?vtrace("read (dirty) from database ~p: ~p", [ID, Key]), case (catch mnesia:dirty_read(ID, Key)) of [Rec|_] -> {value,Rec}; _ -> false end. %% --------------------------------------------------------------- %% write %% %% Write a record to the mib-storage table. %% --------------------------------------------------------------- write(#tab{id = ID}, Rec) -> ?vtrace("write to database ~p", [ID]), F = fun() -> mnesia:write(ID, Rec, write) end, case mnesia:transaction(F) of {aborted, _Reason} = ABORTED -> {error, ABORTED}; {atomic,_} -> ok end. %% --------------------------------------------------------------- %% delete %% %% Delete the mib-storage table. %% --------------------------------------------------------------- delete(#tab{id = ID}) -> ?vtrace("delete database: ~p", [ID]), mnesia:delete_table(ID). %% --------------------------------------------------------------- %% delete %% %% Delete a record from the mib-storage table. %% --------------------------------------------------------------- delete(#tab{id = ID}, Key) -> ?vtrace("delete from database ~p: ~p", [ID, Key]), F = fun() -> mnesia:delete(ID, Key, write) end, case mnesia:transaction(F) of {aborted, _Reason} = ABORTED -> {error, ABORTED}; {atomic, _} -> ok end. %% --------------------------------------------------------------- %% match_object %% %% Search the mib-storage table for records witch matches %% the pattern. %% --------------------------------------------------------------- match_object(#tab{id = ID}, Pattern) -> ?vtrace("match_object in ~p of ~p", [ID, Pattern]), F = fun() -> mnesia:match_object(ID, Pattern, read) end, case mnesia:transaction(F) of {aborted, _Reason} = ABORTED -> {error, ABORTED}; {atomic, Rs} -> Rs end. %% --------------------------------------------------------------- %% match_delete %% %% Search the mib-storage table for records witch matches %% the pattern and deletes them from the table. %% --------------------------------------------------------------- match_delete(#tab{id = ID}, Pattern) -> ?vtrace("match_delete in ~p with pattern ~p", [ID, Pattern]), F = fun() -> Recs = mnesia:match_object(ID, Pattern, read), lists:foreach(fun(Rec) -> mnesia:delete_object(ID, Rec, write) end, Recs), Recs end, case mnesia:transaction(F) of {aborted, _Reason} = ABORTED -> {error, ABORTED}; {atomic, Rs} -> Rs end. %% --------------------------------------------------------------- %% tab2list %% %% Return all records in the mib-storage table in the form of %% a list. %% --------------------------------------------------------------- tab2list(#tab{id = ID} = Tab) -> ?vtrace("tab2list -> list of ~p", [ID]), match_object(Tab, mnesia:table_info(ID, wild_pattern)). %% --------------------------------------------------------------- %% info %% %% Retrieve implementation dependent mib-storage table %% information. %% --------------------------------------------------------------- info(#tab{id = ID}) -> case (catch mnesia:table_info(ID, all)) of Info when is_list(Info) -> Info; {'EXIT', {aborted, Reason}} -> {error, Reason} end. info(#tab{id = ID}, Item) -> mnesia:table_info(ID, Item). %% --------------------------------------------------------------- %% sync %% %% Ignore %% --------------------------------------------------------------- sync(_) -> ok. %% --------------------------------------------------------------- %% backup %% %% Ignore. Mnesia handles its own backups. %% --------------------------------------------------------------- backup(_, _) -> ok. %%---------------------------------------------------------------------- get_action(Opts) -> snmp_misc:get_option(action, Opts, keep). get_nodes(Opts) -> case snmp_misc:get_option(nodes, Opts, erlang:nodes()) of [] -> [node()]; Nodes when is_list(Nodes) -> Nodes; all -> erlang:nodes(); visible -> erlang:nodes(visible); connected -> erlang:nodes(connected); db_nodes -> try mnesia:system_info(db_nodes) of DbNodes when is_list(DbNodes) -> DbNodes; _ -> erlang:nodes() catch _:_ -> erlang:nodes() end end. %% user_err(F, A) -> %% snmpa_error:user_err(F, A).