1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2013-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(snmpa_mib_storage_mnesia). 21 22 23-behaviour(snmpa_mib_storage). 24 25%%%----------------------------------------------------------------- 26%%% This module implements the snmpa_mib_storage behaviour. 27%%% It uses mnesia for storage. 28%%%----------------------------------------------------------------- 29 30-export([ 31 open/5, 32 close/1, 33 read/2, 34 write/2, 35 delete/1, 36 delete/2, 37 match_object/2, 38 match_delete/2, 39 tab2list/1, 40 info/1, info/2, 41 sync/1, 42 backup/2 43 ]). 44 45 46-define(VMODULE,"MS-MNESIA"). 47-include("snmp_verbosity.hrl"). 48 49-record(tab, {id}). 50 51 52%% --------------------------------------------------------------- 53%% open 54%% 55%% Open or create a mnesia table. 56%% 57%% Opts - A list of implementation dependent options 58%% mnesia_open_options() = [mnesia_open_option()] 59%% mnesia_open_option() = {action, keep | clear} | 60%% {nodes, [node()]} 61%% 62%% --------------------------------------------------------------- 63 64open(Name, RecName, Fields, Type, Opts) -> 65 ?vtrace("open ~p table ~p for record ~p", 66 [Type, Name, RecName]), 67 Action = get_action(Opts), 68 Nodes = get_nodes(Opts), 69 case table_exists(Name) of 70 true when (Action =:= keep) -> 71 ?vtrace("open table ~p - exist (keep)", [Name]), 72 {ok, #tab{id = Name}}; 73 true when (Action =:= clear) -> 74 ?vtrace("open table ~p - exist (clear)", [Name]), 75 F = fun() -> mnesia:clear_table(Name) end, 76 case mnesia:transaction(F) of 77 {aborted, Reason} -> 78 {error, {clear, Reason}}; 79 {atomic, _} -> 80 {ok, #tab{id = Name}} 81 end; 82 false -> 83 ?vtrace("open table ~p - does not exist", [Name]), 84 Args = [{record_name, RecName}, 85 {attributes, Fields}, 86 {type, Type}, 87 {disc_copies, Nodes}], 88 case mnesia:create_table(Name, Args) of 89 {atomic, ok} -> 90 ?vtrace("open table ~p - ok", [Name]), 91 {ok, #tab{id = Name}}; 92 {aborted, Reason} -> 93 ?vinfo("open table ~p - aborted" 94 "~n Reason: ~p", [Name, Reason]), 95 {error, {create, Reason}} 96 end 97 end. 98 99table_exists(Name) -> 100 case (catch mnesia:table_info(Name, type)) of 101 {'EXIT', _Reason} -> 102 false; 103 _ -> 104 true 105 end. 106 107 108%% --------------------------------------------------------------- 109%% close 110%% 111%% Close the mib-storage table. 112%% This does nothing in the mnesia case. 113%% --------------------------------------------------------------- 114 115close(_) -> 116 ?vtrace("close mib-storage - ignore",[]), 117 ok. 118 119 120%% --------------------------------------------------------------- 121%% read 122%% 123%% Retrieve a record from the mib-storage table. 124%% --------------------------------------------------------------- 125 126read(#tab{id = ID}, Key) -> 127 ?vtrace("read (dirty) from database ~p: ~p", [ID, Key]), 128 case (catch mnesia:dirty_read(ID, Key)) of 129 [Rec|_] -> {value,Rec}; 130 _ -> false 131 end. 132 133 134%% --------------------------------------------------------------- 135%% write 136%% 137%% Write a record to the mib-storage table. 138%% --------------------------------------------------------------- 139 140write(#tab{id = ID}, Rec) -> 141 ?vtrace("write to database ~p", [ID]), 142 F = fun() -> mnesia:write(ID, Rec, write) end, 143 case mnesia:transaction(F) of 144 {aborted, _Reason} = ABORTED -> 145 {error, ABORTED}; 146 {atomic,_} -> 147 ok 148 end. 149 150 151%% --------------------------------------------------------------- 152%% delete 153%% 154%% Delete the mib-storage table. 155%% --------------------------------------------------------------- 156 157delete(#tab{id = ID}) -> 158 ?vtrace("delete database: ~p", [ID]), 159 mnesia:delete_table(ID). 160 161 162%% --------------------------------------------------------------- 163%% delete 164%% 165%% Delete a record from the mib-storage table. 166%% --------------------------------------------------------------- 167 168delete(#tab{id = ID}, Key) -> 169 ?vtrace("delete from database ~p: ~p", [ID, Key]), 170 F = fun() -> mnesia:delete(ID, Key, write) end, 171 case mnesia:transaction(F) of 172 {aborted, _Reason} = ABORTED -> 173 {error, ABORTED}; 174 {atomic, _} -> 175 ok 176 end. 177 178 179%% --------------------------------------------------------------- 180%% match_object 181%% 182%% Search the mib-storage table for records witch matches 183%% the pattern. 184%% --------------------------------------------------------------- 185 186match_object(#tab{id = ID}, Pattern) -> 187 ?vtrace("match_object in ~p of ~p", [ID, Pattern]), 188 F = fun() -> mnesia:match_object(ID, Pattern, read) end, 189 case mnesia:transaction(F) of 190 {aborted, _Reason} = ABORTED -> 191 {error, ABORTED}; 192 {atomic, Rs} -> 193 Rs 194 end. 195 196 197%% --------------------------------------------------------------- 198%% match_delete 199%% 200%% Search the mib-storage table for records witch matches 201%% the pattern and deletes them from the table. 202%% --------------------------------------------------------------- 203 204match_delete(#tab{id = ID}, Pattern) -> 205 ?vtrace("match_delete in ~p with pattern ~p", [ID, Pattern]), 206 F = fun() -> 207 Recs = mnesia:match_object(ID, Pattern, read), 208 lists:foreach(fun(Rec) -> 209 mnesia:delete_object(ID, Rec, write) 210 end, Recs), 211 Recs 212 end, 213 case mnesia:transaction(F) of 214 {aborted, _Reason} = ABORTED -> 215 {error, ABORTED}; 216 {atomic, Rs} -> 217 Rs 218 end. 219 220 221%% --------------------------------------------------------------- 222%% tab2list 223%% 224%% Return all records in the mib-storage table in the form of 225%% a list. 226%% --------------------------------------------------------------- 227 228tab2list(#tab{id = ID} = Tab) -> 229 ?vtrace("tab2list -> list of ~p", [ID]), 230 match_object(Tab, mnesia:table_info(ID, wild_pattern)). 231 232 233%% --------------------------------------------------------------- 234%% info 235%% 236%% Retrieve implementation dependent mib-storage table 237%% information. 238%% --------------------------------------------------------------- 239 240info(#tab{id = ID}) -> 241 case (catch mnesia:table_info(ID, all)) of 242 Info when is_list(Info) -> 243 Info; 244 {'EXIT', {aborted, Reason}} -> 245 {error, Reason} 246 end. 247 248 249info(#tab{id = ID}, Item) -> 250 mnesia:table_info(ID, Item). 251 252 253%% --------------------------------------------------------------- 254%% sync 255%% 256%% Ignore 257%% --------------------------------------------------------------- 258 259sync(_) -> 260 ok. 261 262 263%% --------------------------------------------------------------- 264%% backup 265%% 266%% Ignore. Mnesia handles its own backups. 267%% --------------------------------------------------------------- 268 269backup(_, _) -> 270 ok. 271 272 273%%---------------------------------------------------------------------- 274 275get_action(Opts) -> 276 snmp_misc:get_option(action, Opts, keep). 277 278get_nodes(Opts) -> 279 case snmp_misc:get_option(nodes, Opts, erlang:nodes()) of 280 [] -> 281 [node()]; 282 Nodes when is_list(Nodes) -> 283 Nodes; 284 all -> 285 erlang:nodes(); 286 visible -> 287 erlang:nodes(visible); 288 connected -> 289 erlang:nodes(connected); 290 db_nodes -> 291 try mnesia:system_info(db_nodes) of 292 DbNodes when is_list(DbNodes) -> 293 DbNodes; 294 _ -> 295 erlang:nodes() 296 catch 297 _:_ -> 298 erlang:nodes() 299 end 300 end. 301 302%% user_err(F, A) -> 303%% snmpa_error:user_err(F, A). 304