aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp/src/agent/snmpa_agent_sup.erl
blob: 2805e2dc0d706bfe048a802d269b5612787590fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
%% 
%% 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.
%% 
%% %CopyrightEnd%
%%
-module(snmpa_agent_sup).

-include("snmp_debug.hrl").

-behaviour(supervisor).

%% External exports
-export([start_link/0, start_link/1, start_subagent/3, stop_subagent/1]).

%% Internal exports
-export([init/1]).

-define(SERVER, ?MODULE).
%% Always use plain ets for sub-agents
-ifdef(snmp_debug).
-define(DEFAULT_SA_OPTS, [{mib_storage, [{module, snmpa_mib_storage_ets}]}, 
			  {verbosity, trace}]).
-else.
-define(DEFAULT_SA_OPTS, [{mib_storage, [{module, snmpa_mib_storage_ets}]}]).
-endif.


%%%-----------------------------------------------------------------
%%% This is a supervisor for the mib processes.  Each agent has one
%%% mib process.
%%%-----------------------------------------------------------------
start_link() ->
    ?d("start_link -> entry", []),
    supervisor:start_link({local, ?SERVER}, ?MODULE, [[]]).

start_link(AgentSpec) ->
    ?d("start_link -> entry with"
	"~n   AgentSpec: ~p", [AgentSpec]),
    supervisor:start_link({local, ?SERVER}, ?MODULE, [[AgentSpec]]).

start_subagent(ParentAgent, Subtree, Mibs) ->
    ?d("start_subagent -> entry with"
	"~n   ParentAgent: ~p"
	"~n   Subtree:     ~p"
	"~n   Mibs:        ~p", [ParentAgent, Subtree, Mibs]),
    Children = supervisor:which_children(?SERVER),
    ?d("start_subagent -> Children: ~n~p", [Children]),
    Max = find_max(Children, 1),
    ?d("start_subagent -> Max: ~p", [Max]),
    [{_, Prio}] = ets:lookup(snmp_agent_table, priority),
    ?d("start_subagent -> Prio: ~p", [Prio]),
    Ref = make_ref(),
    ?d("start_subagent -> Ref: ~p", [Ref]),
    Options = [{priority, Prio}, 
	       {mibs,     Mibs}, 
	       {misc_sup, snmpa_misc_sup} | ?DEFAULT_SA_OPTS],
    Agent = {{sub_agent, Max},
	     {snmpa_agent, start_link,
	      [Prio, ParentAgent, Ref, Options]},
	     permanent, 2000, worker, [snmpa_agent]},
    case supervisor:start_child(?SERVER, Agent) of
	{ok, SA} -> 
	    ?d("start_subagent -> SA: ~p", [SA]),
	    snmpa_agent:register_subagent(ParentAgent, Subtree, SA),
	    {ok, SA};
	Error ->
	    ?d("start_subagent -> Error: ~p", [Error]),
	    Error
    end.

stop_subagent(SubAgentPid) ->
    case find_name(supervisor:which_children(?SERVER), SubAgentPid) of
	undefined -> 
	    no_such_child;
	Name ->
	    supervisor:terminate_child(?SERVER, Name),
	    supervisor:delete_child(?SERVER, Name),
	    ok
    end.

init([Children]) ->
    ?d("init -> entry with"
	"~n   Children: ~p", [Children]),
    %% 20 restarts in ten minutes.  If the agent crashes and restarts,
    %% it may very well crash again, because the management application
    %% tries to resend the very same request.  This depends on the resend
    %% strategy used by the management application.
    SupFlags = {one_for_one, 20, 600},
    {ok, {SupFlags, Children}}.


find_max([{{sub_agent, N}, _, _, _} | T], M) when N >= M -> find_max(T, N+1);
find_max([_|T], M) -> find_max(T, M);
find_max([], M) -> M.

find_name([{Name, Pid, _, _} | _T], Pid)-> Name;
find_name([_|T], Pid) -> find_name(T, Pid);
find_name([], _Pid) -> undefined.


% i(F) ->
%     i(F, []).

% i(F, A) ->
%     io:format("~p:~p: " ++ F ++ "~n", [node(),?MODULE|A]).