1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-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_symbolic_store). 21 22%%---------------------------------------------------------------------- 23%% This module implements a multipurpose symbolic store. 24%% 1) For internal and use from application: aliasname_to_value/1. 25%% If this was stored in the mib, deadlock would occur. 26%% 2 table_info/1. Getting information about a table. Used by default 27%% implementation of tables. 28%% 3) variable_info/1. Used by default implementation of variables. 29%% 4) notification storage. Used by snmpa_trap. 30%% There is one symbolic store per node and it uses the ets table 31%% snmp_agent_table, owned by the snmpa_supervisor. 32%% 33%%---------------------------------------------------------------------- 34 35-include_lib("kernel/include/file.hrl"). 36-include("snmp_types.hrl"). 37-include("snmp_debug.hrl"). 38-include("snmp_verbosity.hrl"). 39-include("SNMPv2-MIB.hrl"). 40 41 42%% API 43-export([start_link/2, 44 stop/0, 45 info/0, 46 backup/1, 47 aliasname_to_oid/1, oid_to_aliasname/1, 48 add_aliasnames/2, delete_aliasnames/1, 49 which_aliasnames/0, 50 which_tables/0, 51 which_variables/0, 52 enum_to_int/2, int_to_enum/2, 53 table_info/1, add_table_infos/2, delete_table_infos/1, 54 variable_info/1, add_variable_infos/2, delete_variable_infos/1, 55 get_notification/1, set_notification/2, 56 delete_notifications/1, which_notifications/0, 57 add_types/2, delete_types/1]). 58 59%% API (for quick access to the db, note that this is only reads). 60-export([get_db/0, 61 aliasname_to_oid/2, oid_to_aliasname/2, 62 enum_to_int/3, int_to_enum/3]). 63 64 65%% Internal exports 66-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, 67 code_change/3]). 68 69-export([verbosity/1]). 70 71-define(SERVER, ?MODULE). 72 73-ifdef(snmp_debug). 74-define(GS_START_LINK(Prio, Opts), 75 gen_server:start_link({local, ?SERVER}, ?MODULE, [Prio, Opts], 76 [{debug,[trace]}])). 77-else. 78-define(GS_START_LINK(Prio, Opts), 79 gen_server:start_link({local, ?SERVER}, ?MODULE, [Prio, Opts], [])). 80-endif. 81 82-record(state, {module, db, backup}). 83-record(symbol, {key, mib_name, info}). 84 85 86%%----------------------------------------------------------------- 87%% Func: start_link/1 88%% Args: Prio is priority of mib-server 89%% Opts is a list of options 90%% Purpose: starts the mib server synchronized 91%% Returns: {ok, Pid} | {error, Reason} 92%%----------------------------------------------------------------- 93start_link(Prio, Opts) -> 94 ?d("start_link -> entry with" 95 "~n Prio: ~p" 96 "~n Opts: ~p", [Prio,Opts]), 97 ?GS_START_LINK(Prio,Opts). 98 99stop() -> 100 call(stop). 101 102info() -> 103 call(info). 104 105backup(BackupDir) -> 106 call({backup, BackupDir}). 107 108 109%%---------------------------------------------------------------------- 110%% Returns: Db 111%%---------------------------------------------------------------------- 112 113get_db() -> 114 call(get_db). 115 116which_module() -> 117 call(which_module). 118 119 120%%---------------------------------------------------------------------- 121%% Returns: {value, Oid} | false 122%%---------------------------------------------------------------------- 123aliasname_to_oid(Aliasname) -> 124 call({aliasname_to_oid, Aliasname}). 125 126oid_to_aliasname(OID) -> 127 call({oid_to_aliasname, OID}). 128 129int_to_enum(TypeOrObjName, Int) -> 130 call({int_to_enum,TypeOrObjName,Int}). 131 132enum_to_int(TypeOrObjName, Enum) -> 133 call({enum_to_int,TypeOrObjName,Enum}). 134 135add_types(MibName, Types) -> 136 cast({add_types, MibName, Types}). 137 138delete_types(MibName) -> 139 cast({delete_types, MibName}). 140 141add_aliasnames(MibName, MEs) -> 142 cast({add_aliasnames, MibName, MEs}). 143 144delete_aliasnames(MibName) -> 145 cast({delete_aliasname, MibName}). 146 147which_aliasnames() -> 148 call(which_aliasnames). 149 150which_tables() -> 151 call(which_tables). 152 153which_variables() -> 154 call(which_variables). 155 156 157%%---------------------------------------------------------------------- 158%% Returns: false|{value, Info} 159%%---------------------------------------------------------------------- 160table_info(TableName) -> 161 call({table_info, TableName}). 162 163 164%%---------------------------------------------------------------------- 165%% Returns: false|{value, Info} 166%%---------------------------------------------------------------------- 167variable_info(VariableName) -> 168 call({variable_info, VariableName}). 169 170add_table_infos(MibName, TableInfos) -> 171 cast({add_table_infos, MibName, TableInfos}). 172 173delete_table_infos(MibName) -> 174 cast({delete_table_infos, MibName}). 175 176add_variable_infos(MibName, VariableInfos) -> 177 cast({add_variable_infos, MibName, VariableInfos}). 178 179delete_variable_infos(MibName) -> 180 cast({delete_variable_infos, MibName}). 181 182 183%%----------------------------------------------------------------- 184%% Store traps 185%%----------------------------------------------------------------- 186%% A notification is stored as {Key, Value}, where 187%% Key is the symbolic trap name, and Value is 188%% a #trap record. 189%%----------------------------------------------------------------- 190%% Returns: {value, Val} | undefined 191%%----------------------------------------------------------------- 192get_notification(Key) -> 193 call({get_notification, Key}). 194set_notification(Trap, MibName) -> 195 call({set_notification, MibName, Trap}). 196delete_notifications(MibName) -> 197 call({delete_notifications, MibName}). 198which_notifications() -> 199 call(which_notifications). 200 201 202verbosity(Verbosity) -> 203 cast({verbosity,Verbosity}). 204 205 206%%---------------------------------------------------------------------- 207%% DB access (read) functions: Returns: {value, Oid} | false 208%%---------------------------------------------------------------------- 209 210aliasname_to_oid(Db, Aliasname) -> 211 Mod = which_module(), 212 aliasname_to_oid(Mod, Db, Aliasname). 213 214aliasname_to_oid(Mod, Db, Aliasname) -> 215 case Mod:read(Db, {alias, Aliasname}) of 216 {value,#symbol{info = {Oid, _Enums}}} -> {value, Oid}; 217 false -> false 218 end. 219 220oid_to_aliasname(Db, Oid) -> 221 Mod = which_module(), 222 oid_to_aliasname(Mod, Db, Oid). 223 224oid_to_aliasname(Mod, Db, Oid) -> 225 case Mod:read(Db, {oid, Oid}) of 226 {value,#symbol{info = Aliasname}} -> {value, Aliasname}; 227 _ -> false 228 end. 229 230which_notifications(Mod, Db) -> 231 Pattern = #symbol{key = {trap, '_'}, _ = '_'}, 232 Symbols = Mod:match_object(Db, Pattern), 233 [{Name, Mib, Rec} || #symbol{key = {trap, Name}, 234 mib_name = Mib, 235 info = Rec} <- Symbols]. 236 237which_aliasnames(Mod, Db) -> 238 Pattern = #symbol{key = {alias, '_'}, _ = '_'}, 239 Symbols = Mod:match_object(Db, Pattern), 240 [Alias || #symbol{key = {alias, Alias}} <- Symbols]. 241 242which_tables(Mod, Db) -> 243 Pattern = #symbol{key = {table_info, '_'}, _ = '_'}, 244 Symbols = Mod:match_object(Db, Pattern), 245 [Name || #symbol{key = {table_info, Name}} <- Symbols]. 246 247which_variables(Mod, Db) -> 248 Pattern = #symbol{key = {variable_info, '_'}, _ = '_'}, 249 Symbols = Mod:match_object(Db, Pattern), 250 [Name || #symbol{key = {variable_info, Name}} <- Symbols]. 251 252 253int_to_enum(Db, TypeOrObjName, Int) -> 254 Mod = which_module(), 255 int_to_enum(Mod, Db, TypeOrObjName, Int). 256 257int_to_enum(Mod, Db, TypeOrObjName, Int) -> 258 case Mod:read(Db, {alias, TypeOrObjName}) of 259 {value,#symbol{info = {_Oid, Enums}}} -> 260 case lists:keysearch(Int, 2, Enums) of 261 {value, {Enum, _Int}} -> {value, Enum}; 262 false -> false 263 end; 264 false -> % Not an Aliasname -> 265 case Mod:read(Db, {type, TypeOrObjName}) of 266 {value,#symbol{info = Enums}} -> 267 case lists:keysearch(Int, 2, Enums) of 268 {value, {Enum, _Int}} -> {value, Enum}; 269 false -> false 270 end; 271 false -> 272 false 273 end 274 end. 275 276enum_to_int(Db, TypeOrObjName, Enum) -> 277 Mod = which_module(), 278 enum_to_int(Mod, Db, TypeOrObjName, Enum). 279 280enum_to_int(Mod, Db, TypeOrObjName, Enum) -> 281 case Mod:read(Db, {alias, TypeOrObjName}) of 282 {value,#symbol{info = {_Oid, Enums}}} -> 283 case lists:keysearch(Enum, 1, Enums) of 284 {value, {_Enum, Int}} -> {value, Int}; 285 false -> false 286 end; 287 false -> % Not an Aliasname 288 case Mod:read(Db, {type, TypeOrObjName}) of 289 {value,#symbol{info = Enums}} -> 290 case lists:keysearch(Enum, 1, Enums) of 291 {value, {_Enum, Int}} -> {value, Int}; 292 false -> false 293 end; 294 false -> 295 false 296 end 297 end. 298 299 300%%---------------------------------------------------------------------- 301%% DB access (read) functions: Returns: false|{value, Info} 302%%---------------------------------------------------------------------- 303 304table_info(Mod, Db, TableName) -> 305 case Mod:read(Db, {table_info, TableName}) of 306 {value,#symbol{info = Info}} -> {value, Info}; 307 false -> false 308 end. 309 310 311%%---------------------------------------------------------------------- 312%% DB access (read) functions: Returns: false|{value, Info} 313%%---------------------------------------------------------------------- 314variable_info(Mod, Db, VariableName) -> 315 case Mod:read(Db, {variable_info, VariableName}) of 316 {value,#symbol{info = Info}} -> {value, Info}; 317 false -> false 318 end. 319 320 321%%---------------------------------------------------------------------- 322%% Implementation 323%%---------------------------------------------------------------------- 324 325init([Prio, Opts]) -> 326 ?d("init -> entry with" 327 "~n Prio: ~p" 328 "~n Opts: ~p", [Prio,Opts]), 329 case (catch do_init(Prio, Opts)) of 330 {ok, State} -> 331 {ok, State}; 332 Error -> 333 config_err("failed starting symbolic-store: ~n~p", [Error]), 334 {stop, {error, Error}} 335 end. 336 337do_init(Prio, Opts) -> 338 process_flag(priority, Prio), 339 process_flag(trap_exit, true), 340 put(sname,ss), 341 put(verbosity,get_verbosity(Opts)), 342 ?vlog("starting",[]), 343 MibStorage = get_mib_storage(Opts), 344 Mod = snmp_misc:get_option(module, MibStorage), 345 MsOpts = snmp_misc:get_option(options, MibStorage, []), 346 347 %% type = bag solves the problem with import and multiple 348 %% object/type definitions. 349 case Mod:open(?MODULE, symbol, record_info(fields, symbol), bag, MsOpts) of 350 {ok, Db} -> 351 S = #state{module = Mod, db = Db}, 352 ?vdebug("started",[]), 353 {ok, S}; 354 {error, _} = ERROR -> 355 ERROR 356 end. 357 358 359handle_call(get_db, _From, #state{db = DB} = S) -> 360 ?vlog("get db",[]), 361 {reply, DB, S}; 362 363handle_call(which_module, _From, #state{module = Mod} = S) -> 364 ?vlog("which module",[]), 365 {reply, Mod, S}; 366 367handle_call({table_info, TableName}, _From, 368 #state{module = Mod, db = DB} = S) -> 369 ?vlog("table info: ~p",[TableName]), 370 Res = table_info(Mod, DB, TableName), 371 ?vdebug("table info result: ~p",[Res]), 372 {reply, Res, S}; 373 374handle_call({variable_info, VariableName}, _From, 375 #state{module = Mod, db = DB} = S) -> 376 ?vlog("variable info: ~p",[VariableName]), 377 Res = variable_info(Mod, DB, VariableName), 378 ?vdebug("variable info result: ~p",[Res]), 379 {reply, Res, S}; 380 381handle_call({aliasname_to_oid, Aliasname}, _From, 382 #state{module = Mod, db = DB} = S) -> 383 ?vlog("aliasname to oid: ~p",[Aliasname]), 384 Res = aliasname_to_oid(Mod, DB, Aliasname), 385 ?vdebug("aliasname to oid result: ~p",[Res]), 386 {reply, Res, S}; 387 388handle_call({oid_to_aliasname, Oid}, _From, 389 #state{module = Mod, db = DB} = S) -> 390 ?vlog("oid to aliasname: ~p",[Oid]), 391 Res = oid_to_aliasname(Mod, DB, Oid), 392 ?vdebug("oid to aliasname result: ~p",[Res]), 393 {reply, Res, S}; 394 395handle_call(which_aliasnames, _From, 396 #state{module = Mod, db = DB} = S) -> 397 ?vlog("which aliasnames",[]), 398 Res = which_aliasnames(Mod, DB), 399 ?vdebug("which aliasnames: ~p",[Res]), 400 {reply, Res, S}; 401 402handle_call(which_tables, _From, 403 #state{module = Mod, db = DB} = S) -> 404 ?vlog("which tables",[]), 405 Res = which_tables(Mod, DB), 406 ?vdebug("which tables: ~p",[Res]), 407 {reply, Res, S}; 408 409handle_call(which_variables, _From, 410 #state{module = Mod, db = DB} = S) -> 411 ?vlog("which variables",[]), 412 Res = which_variables(Mod, DB), 413 ?vdebug("which variables: ~p",[Res]), 414 {reply, Res, S}; 415 416handle_call({enum_to_int, TypeOrObjName, Enum}, _From, 417 #state{module = Mod, db = DB} = S) -> 418 ?vlog("enum to int: ~p, ~p",[TypeOrObjName,Enum]), 419 Res = enum_to_int(Mod, DB, TypeOrObjName, Enum), 420 ?vdebug("enum to int result: ~p",[Res]), 421 {reply, Res, S}; 422 423handle_call({int_to_enum, TypeOrObjName, Int}, _From, 424 #state{module = Mod, db = DB} = S) -> 425 ?vlog("int to enum: ~p, ~p",[TypeOrObjName,Int]), 426 Res = int_to_enum(Mod, DB, TypeOrObjName, Int), 427 ?vdebug("int to enum result: ~p",[Res]), 428 {reply, Res, S}; 429 430handle_call({set_notification, MibName, Trap}, _From, 431 #state{module = Mod, db = DB} = S) -> 432 ?vlog("set notification:" 433 "~n ~p~n ~p", [MibName,Trap]), 434 set_notif(Mod, DB, MibName, Trap), 435 {reply, true, S}; 436 437handle_call({delete_notifications, MibName}, _From, 438 #state{module = Mod, db = DB} = S) -> 439 ?vlog("delete notification: ~p",[MibName]), 440 delete_notif(Mod, DB, MibName), 441 {reply, true, S}; 442 443handle_call(which_notifications, _From, 444 #state{module = Mod, db = DB} = S) -> 445 ?vlog("which notifications", []), 446 Reply = which_notifications(Mod, DB), 447 {reply, Reply, S}; 448 449handle_call({get_notification, Key}, _From, 450 #state{module = Mod, db = DB} = S) -> 451 ?vlog("get notification: ~p",[Key]), 452 Res = get_notif(Mod, DB, Key), 453 ?vdebug("get notification result: ~p",[Res]), 454 {reply, Res, S}; 455 456handle_call(info, _From, #state{module = Mod, db = DB} = S) -> 457 ?vlog("info",[]), 458 Info = get_info(Mod, DB), 459 {reply, Info, S}; 460 461handle_call({backup, BackupDir}, From, #state{module = Mod, db = DB} = S) -> 462 ?vlog("info to ~p",[BackupDir]), 463 Pid = self(), 464 V = get(verbosity), 465 case file:read_file_info(BackupDir) of 466 {ok, #file_info{type = directory}} -> 467 BackupServer = 468 erlang:spawn_link( 469 fun() -> 470 put(sname, albs), 471 put(verbosity, V), 472 Dir = filename:join([BackupDir]), 473 Reply = Mod:backup(DB, Dir), 474 Pid ! {backup_done, Reply}, 475 unlink(Pid) 476 end), 477 ?vtrace("backup server: ~p", [BackupServer]), 478 {noreply, S#state{backup = {BackupServer, From}}}; 479 {ok, _} -> 480 {reply, {error, not_a_directory}, S}; 481 Error -> 482 {reply, Error, S} 483 end; 484 485handle_call(stop, _From, S) -> 486 ?vlog("stop",[]), 487 {stop, normal, ok, S}; 488 489handle_call(Req, _From, S) -> 490 info_msg("received unknown request: ~n~p", [Req]), 491 Reply = {error, {unknown, Req}}, 492 {reply, Reply, S}. 493 494 495handle_cast({add_types, MibName, Types}, #state{module = Mod, db = DB} = S) -> 496 ?vlog("add types for ~p:",[MibName]), 497 F = fun(#asn1_type{assocList = Alist, aliasname = Name}) -> 498 case snmp_misc:assq(enums, Alist) of 499 {value, Es} -> 500 ?vlog("add type~n ~p -> ~p",[Name,Es]), 501 Rec = #symbol{key = {type, Name}, 502 mib_name = MibName, 503 info = Es}, 504 Mod:write(DB, Rec); 505 false -> done 506 end 507 end, 508 lists:foreach(F, Types), 509 {noreply, S}; 510 511handle_cast({delete_types, MibName}, #state{module = Mod, db = DB} = S) -> 512 ?vlog("delete types: ~p",[MibName]), 513 Pattern = #symbol{key = {type, '_'}, mib_name = MibName, info = '_'}, 514 Mod:match_delete(DB, Pattern), 515 {noreply, S}; 516 517handle_cast({add_aliasnames, MibName, MEs}, 518 #state{module = Mod, db = DB} = S) -> 519 ?vlog("add aliasnames for ~p:",[MibName]), 520 F = fun(#me{aliasname = AN, oid = Oid, asn1_type = AT}) -> 521 Enums = 522 case AT of 523 #asn1_type{assocList = Alist} -> 524 case lists:keysearch(enums, 1, Alist) of 525 {value, {enums, Es}} -> Es; 526 _ -> [] 527 end; 528 _ -> [] 529 end, 530 write_alias(Mod, AN, DB, Enums, MibName, Oid) 531 end, 532 lists:foreach(F, MEs), 533 {noreply, S}; 534 535handle_cast({delete_aliasname, MibName}, #state{module = Mod, db = DB} = S) -> 536 ?vlog("delete aliasname: ~p",[MibName]), 537 Pattern1 = #symbol{key = {alias, '_'}, mib_name = MibName, info = '_'}, 538 Mod:match_delete(DB, Pattern1), 539 Pattern2 = #symbol{key = {oid, '_'}, mib_name = MibName, info = '_'}, 540 Mod:match_delete(DB, Pattern2), 541 {noreply, S}; 542 543handle_cast({add_table_infos, MibName, TableInfos}, 544 #state{module = Mod, db = DB} = S) -> 545 ?vlog("add table infos for ~p:",[MibName]), 546 F = fun({Name, TableInfo}) -> 547 ?vlog("add table info~n ~p -> ~p", 548 [Name, TableInfo]), 549 Rec = #symbol{key = {table_info, Name}, 550 mib_name = MibName, 551 info = TableInfo}, 552 Mod:write(DB, Rec) 553 end, 554 lists:foreach(F, TableInfos), 555 {noreply, S}; 556 557handle_cast({delete_table_infos, MibName}, 558 #state{module = Mod, db = DB} = S) -> 559 ?vlog("delete table infos: ~p",[MibName]), 560 Pattern = #symbol{key = {table_info, '_'}, mib_name = MibName, info = '_'}, 561 Mod:match_delete(DB, Pattern), 562 {noreply, S}; 563 564handle_cast({add_variable_infos, MibName, VariableInfos}, 565 #state{module = Mod, db = DB} = S) -> 566 ?vlog("add variable infos for ~p:",[MibName]), 567 F = fun({Name, VariableInfo}) -> 568 ?vlog("add variable info~n ~p -> ~p", 569 [Name,VariableInfo]), 570 Rec = #symbol{key = {variable_info, Name}, 571 mib_name = MibName, 572 info = VariableInfo}, 573 Mod:write(DB, Rec) 574 end, 575 lists:foreach(F, VariableInfos), 576 {noreply, S}; 577 578handle_cast({delete_variable_infos, MibName}, 579 #state{module = Mod, db = DB} = S) -> 580 ?vlog("delete variable infos: ~p",[MibName]), 581 Pattern = #symbol{key = {variable_info,'_'}, 582 mib_name = MibName, 583 info = '_'}, 584 Mod:match_delete(DB, Pattern), 585 {noreply, S}; 586 587handle_cast({verbosity,Verbosity}, State) -> 588 ?vlog("verbosity: ~p -> ~p",[get(verbosity),Verbosity]), 589 put(verbosity,snmp_verbosity:validate(Verbosity)), 590 {noreply, State}; 591 592handle_cast(Msg, S) -> 593 info_msg("received unknown message: ~n~p", [Msg]), 594 {noreply, S}. 595 596 597handle_info({'EXIT', Pid, Reason}, #state{backup = {Pid, From}} = S) -> 598 ?vlog("backup server (~p) exited for reason ~n~p", [Pid, Reason]), 599 gen_server:reply(From, {error, Reason}), 600 {noreply, S#state{backup = undefined}}; 601 602handle_info({'EXIT', Pid, Reason}, S) -> 603 %% The only other processes we should be linked to are 604 %% either the master agent or our supervisor, so die... 605 {stop, {received_exit, Pid, Reason}, S}; 606 607handle_info({backup_done, Reply}, #state{backup = {_, From}} = S) -> 608 ?vlog("backup done:" 609 "~n Reply: ~p", [Reply]), 610 gen_server:reply(From, Reply), 611 {noreply, S#state{backup = undefined}}; 612 613handle_info(Info, S) -> 614 info_msg("received unknown info: ~n~p", [Info]), 615 {noreply, S}. 616 617 618terminate(Reason, #state{module = Mod, db = DB}) -> 619 ?vlog("terminate: ~p", [Reason]), 620 Mod:close(DB). 621 622 623%%---------------------------------------------------------- 624%% Code change 625%%---------------------------------------------------------- 626 627% downgrade 628%% code_change({down, _Vsn}, #state{db = DB, backup = B}, downgrade_to_pre_4_7) -> 629%% ?d("code_change(down) -> entry", []), 630%% stop_backup_server(B), 631%% S = {state, DB}, 632%% {ok, S}; 633 634%% % upgrade 635%% code_change(_Vsn, S, upgrade_from_pre_4_7) -> 636%% ?d("code_change(up) -> entry", []), 637%% {state, DB} = S, 638%% S1 = #state{db = DB}, 639%% {ok, S1}; 640 641code_change(_Vsn, S, _Extra) -> 642 ?d("code_change -> entry [do nothing]", []), 643 {ok, S}. 644 645 646%% stop_backup_server(undefined) -> 647%% ok; 648%% stop_backup_server({Pid, _}) when is_pid(Pid) -> 649%% exit(Pid, kill). 650 651 652 653%%----------------------------------------------------------------- 654%% Trap operations (write, read, delete) 655%%----------------------------------------------------------------- 656%% A notification is stored as {Key, Value}, where 657%% Key is the symbolic trap name, and Value is 658%% a #trap or a #notification record. 659%%----------------------------------------------------------------- 660%% Returns: {value, Value} | undefined 661%%----------------------------------------------------------------- 662get_notif(Mod, Db, Key) -> 663 case Mod:read(Db, {trap, Key}) of 664 {value,#symbol{info = Value}} -> {value, Value}; 665 false -> undefined 666 end. 667 668set_notif(Mod, Db, MibName, Trap) when is_record(Trap, trap) -> 669 #trap{trapname = Name} = Trap, 670 Rec = #symbol{key = {trap, Name}, mib_name = MibName, info = Trap}, 671 %% convert old v1 trap to oid 672 Oid = case Trap#trap.enterpriseoid of 673 ?snmp -> 674 ?snmpTraps ++ [Trap#trap.specificcode + 1]; 675 Oid0 -> 676 Oid0 ++ [0, Trap#trap.specificcode] 677 end, 678 write_alias(Mod, Name, Db, MibName, Oid), 679 Mod:write(Db, Rec); 680set_notif(Mod, Db, MibName, Trap) -> 681 #notification{trapname = Name, oid = Oid} = Trap, 682 Rec = #symbol{key = {trap, Name}, mib_name = MibName, info = Trap}, 683 write_alias(Mod, Name, Db, MibName, Oid), 684 Mod:write(Db, Rec). 685 686delete_notif(Mod, Db, MibName) -> 687 Pattern = #symbol{key = {trap, '_'}, mib_name = MibName, info = '_'}, 688 Mod:match_delete(Db, Pattern). 689 690 691write_alias(Mod, AN, DB, MibName, Oid) -> 692 write_alias(Mod, AN, DB, [], MibName, Oid). 693 694write_alias(Mod, AN, DB, Enums, MibName, Oid) -> 695 ?vlog("add alias~n ~p -> {~p,~p}",[AN, Oid, Enums]), 696 Rec1 = #symbol{key = {alias, AN}, 697 mib_name = MibName, 698 info = {Oid,Enums}}, 699 Mod:write(DB, Rec1), 700 ?vlog("add oid~n ~p -> ~p",[Oid, AN]), 701 Rec2 = #symbol{key = {oid, Oid}, 702 mib_name = MibName, 703 info = AN}, 704 Mod:write(DB, Rec2). 705 706 707%% ------------------------------------- 708 709get_info(Mod, DB) -> 710 ProcSize = proc_mem(self()), 711 DbMemory = Mod:info(DB, memory), 712 [{process_memory, ProcSize}, {db_memory, DbMemory}]. 713 714proc_mem(P) when is_pid(P) -> 715 case (catch erlang:process_info(P, memory)) of 716 {memory, Sz} when is_integer(Sz) -> 717 Sz; 718 _ -> 719 undefined 720 end. 721 722 723%% ------------------------------------- 724 725get_verbosity(L) -> 726 snmp_misc:get_option(verbosity, L, ?default_verbosity). 727 728get_mib_storage(L) -> 729 snmp_misc:get_option(mib_storage, L). 730 731 732%% ------------------------------------- 733 734call(Req) -> 735 call(Req, infinity). 736 737call(Req, Timeout) -> 738 gen_server:call(?SERVER, Req, Timeout). 739 740cast(Msg) -> 741 gen_server:cast(?SERVER, Msg). 742 743 744%% ---------------------------------------------------------------- 745 746info_msg(F, A) -> 747 error_logger:info_msg("~w: " ++ F ++ "~n", [?MODULE|A]). 748 749config_err(F, A) -> 750 snmpa_error:config_err(F, A). 751 752