1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2003-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
21%%
22%%----------------------------------------------------------------------
23%% Purpose: Test suite of the agent mib-server.
24%%          Some of these tests should really be in a mib-storage suite.
25%%----------------------------------------------------------------------
26
27-module(snmp_agent_mibs_test).
28
29
30%%----------------------------------------------------------------------
31%% Include files
32%%----------------------------------------------------------------------
33
34-include_lib("common_test/include/ct.hrl").
35-include("snmp_test_lib.hrl").
36-include_lib("snmp/include/snmp_types.hrl").
37-include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl").
38-include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl").
39-include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl").
40-include("snmp_test_data/Test2.hrl").
41
42
43%%----------------------------------------------------------------------
44%% External exports
45%%----------------------------------------------------------------------
46-export([
47	 all/0,
48	 groups/0,
49
50	 init_per_suite/1,
51	 end_per_suite/1,
52
53	 init_per_group/2,
54	 end_per_group/2,
55
56         init_per_testcase/2,
57	 end_per_testcase/2,
58
59	 start_and_stop/1,
60
61	 size_check_ets1/1,
62	 size_check_ets2/1,
63	 size_check_ets2_bad_file1/1,
64	 size_check_ets3/1,
65	 size_check_ets3_bad_file1/1,
66	 size_check_dets/1,
67	 size_check_mnesia/1,
68	 load_unload/1,
69	 me_lookup/1,
70	 which_mib/1,
71	 cache_test/1
72
73	]).
74
75
76%%----------------------------------------------------------------------
77%% Internal exports
78%%----------------------------------------------------------------------
79
80%%----------------------------------------------------------------------
81%% Macros
82%%----------------------------------------------------------------------
83
84%%----------------------------------------------------------------------
85%% Records
86%%----------------------------------------------------------------------
87
88%%======================================================================
89%% External functions
90%%======================================================================
91
92init_per_suite(Config0) when is_list(Config0) ->
93
94    ?DBG("init_per_suite -> entry with"
95         "~n   Config0: ~p", [Config0]),
96
97    Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
98
99    ?DBG("init_per_suite -> done when"
100         "~n   Config1: ~p", [Config1]),
101
102    Config1.
103
104end_per_suite(Config) when is_list(Config) ->
105
106    ?DBG("end_per_suite -> entry with"
107         "~n   Config: ~p", [Config]),
108
109    Config.
110
111
112init_per_testcase(Case, Config0) when is_list(Config0) ->
113    Config1    = snmp_test_lib:fix_data_dir(Config0),
114    CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config1),
115    DbDir      = join(CaseTopDir, "db_dir/"),
116    ?line ok   = file:make_dir(DbDir),
117    init_per_testcase2(Case, [{db_dir,       DbDir},
118			      {case_top_dir, CaseTopDir} | Config1]).
119
120init_per_testcase2(size_check_ets2_bad_file1, Config) when is_list(Config) ->
121    DbDir = ?config(db_dir, Config),
122    %% Create a ad file
123    ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"),
124			 "calvin and hoppes play chess"),
125    Config;
126init_per_testcase2(size_check_ets3_bad_file1, Config) when is_list(Config) ->
127    DbDir = ?config(db_dir, Config),
128    %% Create a ad file
129    ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"),
130			 "calvin and hoppes play chess"),
131    Config;
132init_per_testcase2(size_check_mnesia, Config) when is_list(Config) ->
133    DbDir = ?config(db_dir, Config),
134    mnesia_start([{dir, DbDir}]),
135    Config;
136init_per_testcase2(cache_test, Config) when is_list(Config) ->
137    Min = timer:minutes(5),
138    Timeout =
139	case lists:keysearch(tc_timeout, 1, Config) of
140	    {value, {tc_timeout, TcTimeout}} when TcTimeout < Min ->
141		Min;
142	    {value, {tc_timeout, TcTimeout}} ->
143		TcTimeout;
144	    _ ->
145		Min
146	end,
147    Dog = test_server:timetrap(Timeout),
148    [{watchdog, Dog} | Config];
149init_per_testcase2(_Case, Config) when is_list(Config) ->
150    Config.
151
152%% end_per_testcase(EtsCase, Config)
153%%   when (is_list(Config) andalso
154%% 	((EtsCase =:= size_check_ets2) orelse
155%% 	 (EtsCase =:= size_check_ets3))) ->
156%%     Dir = ?config(ets_dir, Config),
157%%     ?line ok = ?DEL_DIR(Dir),
158%%     lists:keydelete(ets_dir, 1, Config);
159%% end_per_testcase(size_check_dets, Config) when is_list(Config) ->
160%%     Dir = ?config(dets_dir, Config),
161%%     ?line ok = ?DEL_DIR(Dir),
162%%     lists:keydelete(dets_dir, 1, Config);
163end_per_testcase(size_check_mnesia, Config) when is_list(Config) ->
164    mnesia_stop(),
165    %% Dir = ?config(db_dir, Config),
166    %% ?line ok = ?DEL_DIR(Dir),
167    %% lists:keydelete(mnesia_dir, 1, Config);
168    Config;
169end_per_testcase(cache_test, Config) when is_list(Config) ->
170    Dog = ?config(watchdog, Config),
171    test_server:timetrap_cancel(Dog),
172    Config;
173end_per_testcase(_Case, Config) when is_list(Config) ->
174    Config.
175
176
177%%======================================================================
178%% Test case definitions
179%%======================================================================
180
181all() ->
182    cases().
183
184groups() ->
185    [{size_check, [],
186      [
187       size_check_ets1,            % Plain ets
188       size_check_ets2,            % ets with a file
189       size_check_ets2_bad_file1,  % ets with a bad file
190       size_check_ets3,            % ets with a checksummed file
191       size_check_ets3_bad_file1,  % ets with bad file (checksummed)
192       size_check_dets,            % Plain dets
193       size_check_mnesia           % Plain mnesia
194      ]
195     }].
196
197
198init_per_group(GroupName, Config) ->
199    snmp_test_lib:init_group_top_dir(GroupName, Config).
200
201end_per_group(_GroupName, Config) ->
202    %% Do we really need to do this?
203    %% lists:keydelete(snmp_group_top_dir, 1, Config).
204    Config.
205
206
207cases() ->
208    [
209     start_and_stop,
210     load_unload,
211     {group, size_check},
212     me_lookup,
213     which_mib,
214     cache_test
215    ].
216
217
218%%======================================================================
219%% Test functions
220%%======================================================================
221
222start_and_stop(suite) -> [];
223start_and_stop(Config) when is_list(Config) ->
224    Prio      = normal,
225    Verbosity = trace,
226
227    ?line sym_start(Prio, Verbosity),
228    ?line MibsPid = mibs_start(Prio, Verbosity),
229
230    ?line mibs_info(MibsPid),
231
232    ?line mibs_stop(MibsPid),
233    ?line sym_stop(),
234
235    ok.
236
237
238%% ---------------------------------------------------------------------
239
240load_unload(suite) -> [];
241load_unload(Config) when is_list(Config) ->
242    ?DBG("load_unload -> start", []),
243
244    Prio       = normal,
245    Verbosity  = log,
246    MibDir     = ?config(data_dir, Config),
247
248    ?DBG("load_unload -> start symbolic store", []),
249    ?line sym_start(Prio, Verbosity),
250
251    ?DBG("load_unload -> start mib server", []),
252    ?line MibsPid = mibs_start(Prio, Verbosity),
253
254    ?DBG("load_unload -> load one not already loaded mib", []),
255    ?line ok = verify_loaded_mibs(MibsPid, MibDir, []),
256    ?line ok = load_mibs(MibsPid, MibDir, ["Test2"]),
257    ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]),
258
259    ?DBG("load_unload -> try load one *already loaded* mib", []),
260    EMib = join(MibDir, "Test2"),
261    ?line {error, {'load aborted at', EMib, already_loaded}} =
262	load_mibs(MibsPid, MibDir, ["Test2"]),
263
264    ?DBG("load_unload -> load 2 not already loaded mibs", []),
265    ?line ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
266    ?line ok = verify_loaded_mibs(MibsPid, MibDir,
267				  ["Test2", "TestTrap", "TestTrapv2"]),
268
269    ?DBG("load_unload -> unload one loaded mib", []),
270    ?line ok = unload_mibs(MibsPid, ["Test2"]),
271    ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
272
273    ?DBG("load_unload -> try unload two loaded mibs and one not loaded", []),
274    ?line {error, {'unload aborted at', "Test2", not_loaded}} =
275	   unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]),
276    ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]),
277
278    ?DBG("load_unload -> unload the remaining loaded mib", []),
279    ?line ok = unload_mibs(MibsPid, ["TestTrapv2"]),
280    ?line ok = verify_loaded_mibs(MibsPid, MibDir, []),
281
282    ?DBG("load_unload -> stop mib server", []),
283    ?line mibs_stop(MibsPid),
284
285    ?DBG("load_unload -> stop symbolic store", []),
286    ?line sym_stop(),
287
288    ?DBG("load_unload -> done", []),
289    ok.
290
291
292%% ---------------------------------------------------------------------
293
294
295size_check_ets1(suite) ->
296    [];
297size_check_ets1(Config) when is_list(Config) ->
298    MibStorage = [{module, snmpa_mib_storage_ets}],
299    do_size_check([{mib_storage, MibStorage}|Config]).
300
301size_check_ets2(suite) ->
302    [];
303size_check_ets2(Config) when is_list(Config) ->
304    Dir = ?config(db_dir, Config),
305    MibStorage = [{module,  snmpa_mib_storage_ets},
306		  {options, [{dir, Dir}]}],
307    do_size_check([{mib_storage, MibStorage}|Config]).
308
309size_check_ets2_bad_file1(suite) ->
310    [];
311size_check_ets2_bad_file1(Config) when is_list(Config) ->
312    Dir = ?config(db_dir, Config),
313    %% Ensure that the bad file does not cause any problems (action = clear)
314    MibStorage = [{module,  snmpa_mib_storage_ets},
315		  {options, [{dir,    Dir},
316			     {action, clear}]}],
317    do_size_check([{mib_storage, MibStorage}|Config]).
318
319size_check_ets3(suite) ->
320    [];
321size_check_ets3(Config) when is_list(Config) ->
322    Dir = ?config(db_dir, Config),
323    MibStorage = [{module,  snmpa_mib_storage_ets},
324		  {options, [{dir,      Dir},
325			     {checksum, true}]}],
326    do_size_check([{mib_storage, MibStorage}|Config]).
327
328size_check_ets3_bad_file1(suite) ->
329    [];
330size_check_ets3_bad_file1(Config) when is_list(Config) ->
331    Dir = ?config(db_dir, Config),
332    %% Ensure that the bad file does not cause any problems (action = clear)
333    MibStorage = [{module,  snmpa_mib_storage_ets},
334		  {options, [{dir,      Dir},
335			     {action,   clear},
336			     {checksum, true}]}],
337    do_size_check([{mib_storage, MibStorage}|Config]).
338
339size_check_dets(suite) ->
340    [];
341size_check_dets(Config) when is_list(Config) ->
342    Dir = ?config(db_dir, Config),
343    MibStorage = [{module,  snmpa_mib_storage_dets},
344		  {options, [{dir, Dir}]}],
345    do_size_check([{mib_storage, MibStorage}|Config]).
346
347size_check_mnesia(suite) ->
348    [];
349size_check_mnesia(Config) when is_list(Config) ->
350    MibStorage = [{module,  snmpa_mib_storage_mnesia},
351		  {options, [{nodes, [node()]}]}],
352    do_size_check([{mib_storage, MibStorage}|Config]).
353
354do_size_check(Config) ->
355    ?DBG("do_size_check -> start with"
356	 "~n   Config: ~p", [Config]),
357    Prio      = normal,
358    Verbosity = trace,
359
360    MibStorage = ?config(mib_storage, Config),
361    ?DBG("do_size_check -> MibStorage: ~p", [MibStorage]),
362    MibDir     = ?config(data_dir, Config),
363    StdMibDir  = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
364
365    ?DBG("do_size_check -> start symbolic store", []),
366    ?line sym_start(Prio, MibStorage, Verbosity),
367    ?DBG("do_size_check -> start mib server", []),
368    ?line MibsPid = mibs_start(Prio, MibStorage, Verbosity),
369
370    Mibs    = ["Test2", "TestTrap", "TestTrapv2"],
371    StdMibs = ["OTP-SNMPEA-MIB",
372	       "SNMP-COMMUNITY-MIB",
373	       "SNMP-FRAMEWORK-MIB",
374	       "SNMP-MPD-MIB",
375	       "SNMP-NOTIFICATION-MIB",
376	       "SNMP-TARGET-MIB",
377	       "SNMP-USER-BASED-SM-MIB",
378	       "SNMP-VIEW-BASED-ACM-MIB",
379	       "SNMPv2-MIB",
380	       "SNMPv2-TC",
381	       "SNMPv2-TM"],
382
383    ?DBG("do_size_check -> load mibs", []),
384    ?line load_mibs(MibsPid, MibDir, Mibs),
385    ?DBG("do_size_check -> load std mibs", []),
386    ?line load_mibs(MibsPid, StdMibDir, StdMibs),
387
388    ?SLEEP(2000),
389    ?DBG("do_size_check -> display mem usage", []),
390    ?line display_memory_usage(MibsPid),
391
392    ?DBG("do_size_check -> unload std mibs", []),
393    ?line unload_mibs(MibsPid, StdMibs),
394    ?DBG("do_size_check -> unload mibs", []),
395    ?line unload_mibs(MibsPid, Mibs),
396
397    ?DBG("do_size_check -> stop mib server", []),
398    ?line mibs_stop(MibsPid),
399    ?DBG("do_size_check -> stop symbolic store", []),
400    ?line sym_stop(),
401
402    ?DBG("do_size_check -> done", []),
403    ok.
404
405
406%% ---------------------------------------------------------------------
407
408me_lookup(suite) -> [];
409me_lookup(Config) when is_list(Config) ->
410    Prio       = normal,
411    Verbosity  = trace,
412    MibDir     = ?config(data_dir, Config),
413    StdMibDir  = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
414    Mibs    = ["Test2", "TestTrap", "TestTrapv2"],
415    StdMibs = ["OTP-SNMPEA-MIB",
416	       "SNMP-COMMUNITY-MIB",
417	       "SNMP-FRAMEWORK-MIB",
418	       "SNMP-MPD-MIB",
419	       "SNMP-NOTIFICATION-MIB",
420	       "SNMP-TARGET-MIB",
421	       %% "SNMP-USER-BASED-SM-MIB",
422	       "SNMP-VIEW-BASED-ACM-MIB",
423	       "SNMPv2-MIB",
424	       "SNMPv2-TC",
425	       "SNMPv2-TM"],
426
427    ?DBG("me_lookup -> start symbolic store", []),
428    ?line sym_start(Prio, Verbosity),
429
430    ?DBG("me_lookup -> start mib server", []),
431    ?line MibsPid = mibs_start(Prio, Verbosity),
432
433    ?DBG("me_lookup -> load mibs", []),
434    ?line load_mibs(MibsPid, MibDir, Mibs),
435    ?DBG("me_lookup -> load std mibs", []),
436    ?line load_mibs(MibsPid, StdMibDir, StdMibs),
437
438    ?DBG("me_lookup -> find ~w from SNMP-COMMUNITY-MIB",
439	 [?snmpTrapCommunity_instance]),
440    ?line ok = me_lookup(MibsPid, ?snmpTrapCommunity_instance),
441
442    ?DBG("me_lookup -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
443	 [?vacmViewSpinLock_instance]),
444    ?line ok = me_lookup(MibsPid, ?vacmViewSpinLock_instance),
445
446    ?DBG("me_lookup -> find ~w from SNMP-USER-BASED-SM-MIB",
447	 [?usmStatsNotInTimeWindows_instance]),
448    ?line {error, _} = me_lookup(MibsPid, ?usmStatsNotInTimeWindows_instance),
449
450    ?DBG("me_lookup -> stop mib server", []),
451    ?line mibs_stop(MibsPid),
452
453    ?DBG("me_lookup -> stop symbolic store", []),
454    ?line sym_stop(),
455
456    ok.
457
458
459%% ---------------------------------------------------------------------
460
461which_mib(suite) -> [];
462which_mib(Config) when is_list(Config) ->
463    Prio       = normal,
464    Verbosity  = trace,
465    MibDir     = ?config(data_dir, Config),
466    StdMibDir  = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
467    Mibs    = ["Test2", "TestTrap", "TestTrapv2"],
468    StdMibs = ["OTP-SNMPEA-MIB",
469	       "SNMP-COMMUNITY-MIB",
470	       "SNMP-FRAMEWORK-MIB",
471	       "SNMP-MPD-MIB",
472	       "SNMP-NOTIFICATION-MIB",
473	       "SNMP-TARGET-MIB",
474	       %% "SNMP-USER-BASED-SM-MIB",
475	       "SNMP-VIEW-BASED-ACM-MIB",
476	       "SNMPv2-MIB",
477	       "SNMPv2-TC",
478	       "SNMPv2-TM"],
479
480    ?DBG("which_mib -> start symbolic store", []),
481    ?line sym_start(Prio, Verbosity),
482
483    ?DBG("which_mib -> start mib server", []),
484    ?line MibsPid = mibs_start(Prio, Verbosity),
485
486    ?DBG("which_mib -> load mibs", []),
487    ?line load_mibs(MibsPid, MibDir, Mibs),
488    ?DBG("which_mib -> load std mibs", []),
489    ?line load_mibs(MibsPid, StdMibDir, StdMibs),
490
491    ?DBG("which_mib -> find ~w from SNMP-COMMUNITY-MIB",
492	 [?snmpTrapCommunity_instance]),
493    ?line ok = which_mib(MibsPid, ?snmpTrapCommunity_instance,
494			 "SNMP-COMMUNITY-MIB"),
495
496    ?DBG("which_mib -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
497	 [?vacmViewSpinLock_instance]),
498    ?line ok = which_mib(MibsPid, ?vacmViewSpinLock_instance,
499			 "SNMP-VIEW-BASED-ACM-MIB"),
500
501    ?DBG("which_mib -> find ~w from SNMP-USER-BASED-SM-MIB (not loaded)",
502	 [?usmStatsNotInTimeWindows_instance]),
503    ?line {error, _} = which_mib(MibsPid, ?usmStatsNotInTimeWindows_instance,
504				"SNMP-USER-BASED-SM-MIB"),
505
506    ?DBG("which_mib -> stop mib server", []),
507    ?line mibs_stop(MibsPid),
508
509    ?DBG("which_mib -> stop symbolic store", []),
510    ?line sym_stop(),
511
512    ok.
513
514
515%% ---------------------------------------------------------------------
516
517cache_test(suite) -> [];
518cache_test(Config) when is_list(Config) ->
519    ?DBG("cache_test -> start", []),
520    Prio       = normal,
521    Verbosity  = trace,
522    MibStorage = [{module, snmpa_mib_storage_ets}],
523    MibDir     = ?config(data_dir, Config),
524    StdMibDir  = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
525    Mibs       = ["Test2", "TestTrap", "TestTrapv2"],
526    StdMibs    = ["OTP-SNMPEA-MIB",
527		  "SNMP-COMMUNITY-MIB",
528		  "SNMP-FRAMEWORK-MIB",
529		  "SNMP-MPD-MIB",
530		  "SNMP-NOTIFICATION-MIB",
531		  "SNMP-TARGET-MIB",
532		  %% "SNMP-USER-BASED-SM-MIB",
533		  "SNMP-VIEW-BASED-ACM-MIB",
534		  "SNMPv2-MIB",
535		  "SNMPv2-TC",
536		  "SNMPv2-TM"],
537
538    ?DBG("cache_test -> start symbolic store", []),
539    ?line sym_start(Prio, MibStorage, Verbosity),
540
541    ?DBG("cache_test -> start mib server", []),
542    GcLimit   = 2,
543    Age       = timer:seconds(10),
544    CacheOpts = [{autogc, false}, {age, Age}, {gclimit, GcLimit}],
545    ?line MibsPid = mibs_start(Prio, MibStorage, [], Verbosity, CacheOpts),
546
547    ?DBG("cache_test -> load mibs", []),
548    ?line load_mibs(MibsPid, MibDir, Mibs),
549    ?DBG("cache_test -> load std mibs", []),
550    ?line load_mibs(MibsPid, StdMibDir, StdMibs),
551
552    ?DBG("cache_test -> do a simple walk to populate the cache", []),
553    ?line ok = walk(MibsPid),
554
555    {ok, Sz1} = snmpa_mib:which_cache_size(MibsPid),
556    ?DBG("cache_test -> Size1: ~p", [Sz1]),
557
558    ?DBG("cache_test -> sleep 5 secs", []),
559    ?SLEEP(timer:seconds(5)),
560
561    ?DBG("cache_test -> perform gc, expect nothing", []),
562    {ok, 0} = snmpa_mib:gc_cache(MibsPid),
563
564    ?DBG("cache_test -> sleep 10 secs", []),
565    ?SLEEP(timer:seconds(10)),
566
567    ?DBG("cache_test -> perform gc, expect GcLimit", []),
568    GcLimit1 = GcLimit + 1,
569    {ok, GcLimit1} = snmpa_mib:gc_cache(MibsPid, Age, GcLimit1),
570
571    Sz2 = Sz1 - GcLimit1,
572    {ok, Sz2} = snmpa_mib:which_cache_size(MibsPid),
573    ?DBG("cache_test -> Size2: ~p", [Sz2]),
574
575    ?DBG("cache_test -> enable cache autogc", []),
576    ?line ok = snmpa_mib:enable_cache_autogc(MibsPid),
577
578    ?DBG("cache_test -> wait 65 seconds to allow gc to happen", []),
579    ?SLEEP(timer:seconds(65)),
580    Sz3 = Sz2 - GcLimit,
581    {ok, Sz3} = snmpa_mib:which_cache_size(MibsPid),
582    ?DBG("cache_test -> Size3: ~p", [Sz3]),
583
584    ?DBG("cache_test -> "
585	 "wait 2 minutes to allow gc to happen, expect empty cache", []),
586    ?SLEEP(timer:minutes(2)),
587    {ok, 0} = snmpa_mib:which_cache_size(MibsPid),
588
589    ?DBG("cache_test -> stop mib server", []),
590    ?line mibs_stop(MibsPid),
591
592    ?DBG("cache_test -> stop symbolic store", []),
593    ?line sym_stop(),
594    ok.
595
596walk(MibsPid) ->
597    MibView = snmpa_acm:get_root_mib_view(),
598    do_walk(MibsPid, ?snmpTrapCommunity_instance, MibView),
599    do_walk(MibsPid, ?vacmViewSpinLock_instance, MibView),
600    do_walk(MibsPid, ?usmStatsNotInTimeWindows_instance, MibView),
601    do_walk(MibsPid, ?tDescr_instance, MibView).
602
603
604do_walk(MibsPid, Oid, MibView) ->
605    io:format("do_walk -> entry with"
606	      "~n   Oid: ~p"
607	      "~n", [Oid]),
608    case snmpa_mib:next(MibsPid, Oid, MibView) of
609	{table, _, _, #me{oid = Oid}} ->
610	    ok;
611	{table, _, _, #me{oid = Next}} ->
612	    do_walk(MibsPid, Next, MibView);
613	{variable, #me{oid = Oid}, _} ->
614	    ok;
615	{variable, #me{oid = Next}, _} ->
616	    do_walk(MibsPid, Next, MibView)
617    end.
618
619
620%%======================================================================
621%% Internal functions
622%%======================================================================
623
624%% -- Mnesia functions
625
626mnesia_start(Opts) ->
627    mnesia_start(Opts, [node()]).
628
629mnesia_start(Opts, Nodes) ->
630    ?DBG("mnesia_start -> load mnesia", []),
631    ?line ok = application:load(mnesia),
632    F = fun({Key, Val}) ->
633		?DBG("mnesia_start -> set mnesia env: ~n~p -> ~p", [Key,Val]),
634		?line application_controller:set_env(mnesia, Key, Val)
635	end,
636    lists:foreach(F, Opts),
637    ?DBG("mnesia_start -> create mnesia schema on ~p", [Nodes]),
638    ?line ok = mnesia:create_schema(Nodes),
639    ?DBG("mnesia_start -> start mnesia", []),
640    ?line ok = application:start(mnesia),
641    ok.
642
643mnesia_stop() ->
644    ?DBG("mnesia_stop -> stop mnesia", []),
645    application:stop(mnesia),
646    ?DBG("mnesia_stop -> unload mnesia", []),
647    application:unload(mnesia),
648    ok.
649
650%% - Symbolic Store mini interface
651
652sym_start(Prio, Verbosity) ->
653    sym_start(Prio, mib_storage(), Verbosity).
654
655sym_start(Prio, MibStorage, Verbosity) ->
656    Opts = [{mib_storage, MibStorage}, {verbosity,Verbosity}],
657    {ok, _Pid} = snmpa_symbolic_store:start_link(Prio, Opts),
658    ok.
659
660sym_stop() ->
661    ok = snmpa_symbolic_store:stop().
662
663sym_info() ->
664    snmpa_symbolic_store:info().
665
666
667%% -- MIB server mini interface
668
669mibs_start(Prio, Verbosity) when is_atom(Prio) andalso is_atom(Verbosity) ->
670    mibs_start(Prio, mib_storage(), [], Verbosity).
671
672mibs_start(Prio, MibStorage, Verbosity)
673  when is_atom(Prio) andalso is_atom(Verbosity) ->
674    mibs_start(Prio, MibStorage, [], Verbosity).
675
676mibs_start(Prio, MibStorage, Mibs, Verbosity)
677  when is_atom(Prio)       andalso
678       is_list(Mibs)       andalso
679       is_atom(Verbosity) ->
680    mibs_start(Prio, MibStorage, Mibs, Verbosity, []).
681
682mibs_start(Prio, MibStorage, Mibs, Verbosity, CacheOpts)
683  when is_atom(Prio)       andalso
684       is_list(Mibs)       andalso
685       is_atom(Verbosity)  andalso
686       is_list(CacheOpts) ->
687    Opts = [{mib_storage, MibStorage},
688	    {verbosity,   Verbosity},
689	    {cache,       CacheOpts}],
690    {ok, Pid} = snmpa_mib:start_link(Prio, Mibs, Opts),
691    Pid.
692
693mibs_stop(Pid) ->
694    ok = snmpa_mib:stop(Pid).
695
696mibs_info(Pid) ->
697    snmpa_mib:info(Pid).
698
699load_mibs(Pid, Dir, Mibs0) ->
700    Mibs = [join(Dir, Mib) || Mib <- Mibs0],
701    Res = snmpa_mib:load_mibs(Pid, Mibs),
702    %% ?DBG("load_mibs -> "
703    %% 	 "~n   Res: ~p", [Res]),
704    Res.
705
706unload_mibs(Pid, Mibs) ->
707    Res = snmpa_mib:unload_mibs(Pid, Mibs),
708    %% ?DBG("unload_mibs -> "
709    %% 	 "~n   Res: ~p", [Res]),
710    Res.
711
712verify_loaded_mibs(Pid, Dir, ExpectedMibs0) ->
713    ExpectedMibs = [join(Dir, Mib) || Mib <- ExpectedMibs0],
714    case snmpa_mib:info(Pid, loaded_mibs) of
715	ExpectedMibs ->
716	    ok;
717	LoadedMibs0 ->
718	    ?DBG("verify_loaded_mibs -> LoadedMibs0: ~p", [LoadedMibs0]),
719	    LoadedMibs = [filename:rootname(FN, ".bin") || FN <- LoadedMibs0],
720	    ?DBG("verify_loaded_mibs -> LoadedMibs: ~p", [LoadedMibs]),
721	    ExpNotLoadedMibs = ExpectedMibs -- LoadedMibs,
722	    LoadedNotExpMibs = LoadedMibs -- ExpectedMibs,
723	    ?DBG("verify_loaded_mibs -> "
724		 "~n   ExpNotLoadedMibs: ~p"
725		 "~n   LoadedNotExpMibs: ~p",
726		 [ExpNotLoadedMibs, LoadedNotExpMibs]),
727	    case ExpNotLoadedMibs of
728		[] ->
729		    case LoadedNotExpMibs of
730			[] ->
731			    ok;
732			_ ->
733			    {error, {unexpected_loaded_mibs, LoadedNotExpMibs}}
734		    end;
735		_ ->
736		    case LoadedNotExpMibs of
737			[] ->
738			    {error, {not_loaded_mibs, ExpNotLoadedMibs}};
739			_ ->
740			    {error, {unexpected_mibs,
741				     ExpNotLoadedMibs, LoadedNotExpMibs}}
742		    end
743	    end
744
745    end.
746
747me_lookup(Pid, Oid) ->
748    case snmpa_mib:lookup(Pid, Oid) of
749	{variable, #me{oid = Oid}} ->
750	    ok;
751	{variable, #me{oid = OtherOid}} ->
752	    case lists:reverse(Oid) of
753		[0|Rest] ->
754		    case lists:reverse(Rest) of
755			OtherOid ->
756			    ok;
757			AnotherOid ->
758			    {error, {invalid_oid, Oid, AnotherOid}}
759		    end;
760		_ ->
761		    {error, {invalid_oid, Oid, OtherOid}}
762	    end;
763	{table_column, _ME, _TableEntryOid} ->
764            ok;
765        {subagent, SubAgentPid, _SANextOid} ->
766            {error, {subagent, SubAgentPid}};
767        {false, Reason} ->
768            {error, Reason};
769        Else ->
770            {error, Else}
771    end.
772
773
774which_mib(Pid, Oid, Mib1) ->
775    case snmpa_mib:which_mib(Pid, Oid) of
776	{ok, Mib2} when is_atom(Mib2) ->
777	    Mib3 = atom_to_list(Mib2),
778	    which_mib(Mib1, Mib3);
779	{ok, Mib2} ->
780	    which_mib(Mib1, Mib2);
781        {error, Reason} ->
782            {error, Reason};
783        Else ->
784            {error, Else}
785    end.
786
787which_mib(M, M) ->
788    ok;
789which_mib(M1, M2) ->
790    {error, {invalid_mib, M1, M2}}.
791
792
793%% Default mib-storage
794mib_storage() ->
795    [{module, snmpa_mib_storage_ets}].
796
797
798%% --
799
800display_memory_usage(MibsPid) ->
801    SymInfo     = sym_info(),
802    SymProcSize = key1search(process_memory, SymInfo),
803    DbSize      = key1search(db_memory,      SymInfo),
804    MibsInfo    = mibs_info(MibsPid),
805    TreeSize    = key1search(tree_size_bytes,  MibsInfo),
806    MibsProcMem = key1search(process_memory,   MibsInfo),
807    MibDbSize   = key1search([db_memory,mib],  MibsInfo),
808    NodeDbSize  = key1search([db_memory,node], MibsInfo),
809    TreeDbSize  = key1search([db_memory,tree], MibsInfo),
810    ?INF("Symbolic store memory usage: "
811	"~n   Process memory size: ~p"
812	"~n   Db size:             ~p"
813	"~n"
814	"~nMib server memory usage: "
815	"~n   Tree size:           ~p"
816	"~n   Process memory size: ~p"
817	"~n   Mib db size:         ~p"
818	"~n   Node db size:        ~p"
819	"~n   Tree db size:        ~p"
820	"~n",
821	[SymProcSize, DbSize,
822	TreeSize, MibsProcMem, MibDbSize, NodeDbSize, TreeDbSize]).
823
824key1search([], Res) ->
825    Res;
826key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) ->
827    case lists:keysearch(Key, 1, List) of
828	{value, {Key, Val}} ->
829	    key1search(Keys, Val);
830	false ->
831	    undefined
832    end;
833key1search(Key, List) when is_atom(Key) ->
834    case lists:keysearch(Key, 1, List) of
835	{value, {Key, Val}} ->
836	    Val;
837	false ->
838	    undefined
839    end.
840
841join(Dir, File) ->
842    filename:join(Dir, File).
843